You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
6.7 KiB
220 lines
6.7 KiB
// Copyright 2019 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef OSP_PUBLIC_PRESENTATION_PRESENTATION_CONNECTION_H_
|
|
#define OSP_PUBLIC_PRESENTATION_PRESENTATION_CONNECTION_H_
|
|
|
|
#include <cstdint>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "absl/strings/string_view.h"
|
|
#include "absl/types/optional.h"
|
|
#include "osp/public/message_demuxer.h"
|
|
#include "platform/api/time.h"
|
|
#include "platform/base/error.h"
|
|
#include "platform/base/ip_address.h"
|
|
#include "platform/base/macros.h"
|
|
#include "util/osp_logging.h"
|
|
|
|
namespace openscreen {
|
|
namespace osp {
|
|
|
|
class ProtocolConnection;
|
|
|
|
enum class TerminationReason {
|
|
kReceiverTerminateCalled = 0,
|
|
kReceiverUserTerminated,
|
|
kControllerTerminateCalled,
|
|
kControllerUserTerminated,
|
|
kReceiverPresentationReplaced,
|
|
kReceiverIdleTooLong,
|
|
kReceiverPresentationUnloaded,
|
|
kReceiverShuttingDown,
|
|
kReceiverError,
|
|
};
|
|
|
|
class Connection {
|
|
public:
|
|
enum class CloseReason {
|
|
kClosed = 0,
|
|
kDiscarded,
|
|
kError,
|
|
};
|
|
|
|
enum class State {
|
|
// The library is currently attempting to connect to the presentation.
|
|
kConnecting,
|
|
// The connection to the presentation is open and communication is possible.
|
|
kConnected,
|
|
// The connection is closed or could not be opened. No communication is
|
|
// possible but it may be possible to reopen the connection via
|
|
// ReconnectPresentation.
|
|
kClosed,
|
|
// The connection is closed and the receiver has been terminated.
|
|
kTerminated,
|
|
};
|
|
|
|
// An object to receive callbacks related to a single Connection.
|
|
class Delegate {
|
|
public:
|
|
Delegate() = default;
|
|
virtual ~Delegate() = default;
|
|
|
|
// State changes.
|
|
virtual void OnConnected() = 0;
|
|
|
|
// Explicit close by other endpoint.
|
|
virtual void OnClosedByRemote() = 0;
|
|
|
|
// Closed because the script connection object was discarded.
|
|
virtual void OnDiscarded() = 0;
|
|
|
|
// Closed because of an error.
|
|
virtual void OnError(const absl::string_view message) = 0;
|
|
|
|
// Terminated through a different connection.
|
|
virtual void OnTerminated() = 0;
|
|
|
|
// A UTF-8 string message was received.
|
|
virtual void OnStringMessage(const absl::string_view message) = 0;
|
|
|
|
// A binary message was received.
|
|
virtual void OnBinaryMessage(const std::vector<uint8_t>& data) = 0;
|
|
|
|
private:
|
|
OSP_DISALLOW_COPY_AND_ASSIGN(Delegate);
|
|
};
|
|
|
|
// Allows different close, termination, and destruction behavior for both
|
|
// possible parents: controller and receiver. This is different from the
|
|
// normal delegate above, which would be supplied by the embedder to link it's
|
|
// presentation connection functionality.
|
|
class ParentDelegate {
|
|
public:
|
|
ParentDelegate() = default;
|
|
virtual ~ParentDelegate() = default;
|
|
|
|
virtual Error CloseConnection(Connection* connection,
|
|
CloseReason reason) = 0;
|
|
virtual Error OnPresentationTerminated(const std::string& presentation_id,
|
|
TerminationReason reason) = 0;
|
|
virtual void OnConnectionDestroyed(Connection* connection) = 0;
|
|
|
|
private:
|
|
OSP_DISALLOW_COPY_AND_ASSIGN(ParentDelegate);
|
|
};
|
|
|
|
struct PresentationInfo {
|
|
std::string id;
|
|
std::string url;
|
|
};
|
|
|
|
// Constructs a new connection using |delegate| for callbacks.
|
|
Connection(const PresentationInfo& info,
|
|
Delegate* delegate,
|
|
ParentDelegate* parent_delegate);
|
|
~Connection();
|
|
|
|
// Returns the ID and URL of this presentation.
|
|
const PresentationInfo& presentation_info() const { return presentation_; }
|
|
|
|
State state() const { return state_; }
|
|
|
|
ProtocolConnection* get_protocol_connection() const {
|
|
return protocol_connection_.get();
|
|
}
|
|
|
|
// These methods should only be called when we are connected.
|
|
uint64_t endpoint_id() const {
|
|
OSP_CHECK(endpoint_id_);
|
|
return endpoint_id_.value();
|
|
}
|
|
uint64_t connection_id() const {
|
|
OSP_CHECK(connection_id_);
|
|
return connection_id_.value();
|
|
}
|
|
|
|
// Sends a UTF-8 string message.
|
|
Error SendString(absl::string_view message);
|
|
|
|
// Sends a binary message.
|
|
Error SendBinary(std::vector<uint8_t>&& data);
|
|
|
|
// Closes the connection. This can be based on an explicit request from the
|
|
// embedder or because the connection object is being discarded (page
|
|
// navigated, object GC'd, etc.).
|
|
Error Close(CloseReason reason);
|
|
|
|
// Terminates the presentation associated with this connection.
|
|
void Terminate(TerminationReason reason);
|
|
|
|
void OnConnecting();
|
|
|
|
// Called by the receiver when the OnPresentationStarted logic happens. This
|
|
// notifies the delegate and updates our internal stream and ids.
|
|
void OnConnected(uint64_t connection_id,
|
|
uint64_t endpoint_id,
|
|
std::unique_ptr<ProtocolConnection> stream);
|
|
|
|
void OnClosedByError(Error cause);
|
|
void OnClosedByRemote();
|
|
void OnTerminated();
|
|
|
|
Delegate* get_delegate() { return delegate_; }
|
|
|
|
private:
|
|
// Helper method that handles closing down our internal state.
|
|
// Returns whether or not the connection state changed (and thus
|
|
// whether or not delegates should be informed).
|
|
bool OnClosed();
|
|
|
|
PresentationInfo presentation_;
|
|
State state_ = State::kConnecting;
|
|
Delegate* delegate_;
|
|
ParentDelegate* parent_delegate_;
|
|
absl::optional<uint64_t> connection_id_;
|
|
absl::optional<uint64_t> endpoint_id_;
|
|
std::unique_ptr<ProtocolConnection> protocol_connection_;
|
|
|
|
OSP_DISALLOW_COPY_AND_ASSIGN(Connection);
|
|
};
|
|
|
|
class ConnectionManager final : public MessageDemuxer::MessageCallback {
|
|
public:
|
|
explicit ConnectionManager(MessageDemuxer* demuxer);
|
|
|
|
void AddConnection(Connection* connection);
|
|
void RemoveConnection(Connection* connection);
|
|
|
|
// MessasgeDemuxer::MessageCallback overrides.
|
|
ErrorOr<size_t> OnStreamMessage(uint64_t endpoint_id,
|
|
uint64_t connection_id,
|
|
msgs::Type message_type,
|
|
const uint8_t* buffer,
|
|
size_t buffer_size,
|
|
Clock::time_point now) override;
|
|
|
|
Connection* GetConnection(uint64_t connection_id);
|
|
|
|
private:
|
|
// TODO(btolsch): Connection IDs were changed to be per-endpoint, but this
|
|
// table then needs to be <endpoint id, connection id> since connection id is
|
|
// still not unique globally.
|
|
std::map<uint64_t, Connection*> connections_;
|
|
|
|
MessageDemuxer::MessageWatch message_watch_;
|
|
MessageDemuxer::MessageWatch close_request_watch_;
|
|
MessageDemuxer::MessageWatch close_event_watch_;
|
|
|
|
OSP_DISALLOW_COPY_AND_ASSIGN(ConnectionManager);
|
|
};
|
|
|
|
} // namespace osp
|
|
} // namespace openscreen
|
|
|
|
#endif // OSP_PUBLIC_PRESENTATION_PRESENTATION_CONNECTION_H_
|