OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef MOJO_EDK_SYSTEM_PORTS_NODE_H_ |
| 6 #define MOJO_EDK_SYSTEM_PORTS_NODE_H_ |
| 7 |
| 8 #include <stddef.h> |
| 9 #include <stdint.h> |
| 10 |
| 11 #include <queue> |
| 12 #include <unordered_map> |
| 13 |
| 14 #include "base/macros.h" |
| 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/synchronization/lock.h" |
| 17 #include "mojo/edk/system/ports/event.h" |
| 18 #include "mojo/edk/system/ports/hash_functions.h" |
| 19 #include "mojo/edk/system/ports/message.h" |
| 20 #include "mojo/edk/system/ports/name.h" |
| 21 #include "mojo/edk/system/ports/port.h" |
| 22 #include "mojo/edk/system/ports/port_ref.h" |
| 23 #include "mojo/edk/system/ports/user_data.h" |
| 24 |
| 25 #undef SendMessage // Gah, windows |
| 26 |
| 27 namespace mojo { |
| 28 namespace edk { |
| 29 namespace ports { |
| 30 |
| 31 enum : int { |
| 32 OK = 0, |
| 33 ERROR_PORT_UNKNOWN = -10, |
| 34 ERROR_PORT_EXISTS = -11, |
| 35 ERROR_PORT_STATE_UNEXPECTED = -12, |
| 36 ERROR_PORT_CANNOT_SEND_SELF = -13, |
| 37 ERROR_PORT_PEER_CLOSED = -14, |
| 38 ERROR_PORT_CANNOT_SEND_PEER = -15, |
| 39 ERROR_NOT_IMPLEMENTED = -100, |
| 40 }; |
| 41 |
| 42 struct PortStatus { |
| 43 bool has_messages; |
| 44 bool receiving_messages; |
| 45 bool peer_closed; |
| 46 }; |
| 47 |
| 48 class NodeDelegate; |
| 49 |
| 50 class Node { |
| 51 public: |
| 52 // Does not take ownership of the delegate. |
| 53 Node(const NodeName& name, NodeDelegate* delegate); |
| 54 ~Node(); |
| 55 |
| 56 // Returns true iff there are no open ports referring to another node or ports |
| 57 // in the process of being transferred from this node to another. If this |
| 58 // returns false, then to ensure clean shutdown, it is necessary to keep the |
| 59 // node alive and continue routing messages to it via AcceptMessage. This |
| 60 // method may be called again after AcceptMessage to check if the Node is now |
| 61 // ready to be destroyed. |
| 62 // |
| 63 // If |allow_local_ports| is |true|, this will only return |false| when there |
| 64 // are transient ports referring to other nodes. |
| 65 bool CanShutdownCleanly(bool allow_local_ports); |
| 66 |
| 67 // Lookup the named port. |
| 68 int GetPort(const PortName& port_name, PortRef* port_ref); |
| 69 |
| 70 // Creates a port on this node. Before the port can be used, it must be |
| 71 // initialized using InitializePort. This method is useful for bootstrapping |
| 72 // a connection between two nodes. Generally, ports are created using |
| 73 // CreatePortPair instead. |
| 74 int CreateUninitializedPort(PortRef* port_ref); |
| 75 |
| 76 // Initializes a newly created port. |
| 77 int InitializePort(const PortRef& port_ref, |
| 78 const NodeName& peer_node_name, |
| 79 const PortName& peer_port_name); |
| 80 |
| 81 // Generates a new connected pair of ports bound to this node. These ports |
| 82 // are initialized and ready to go. |
| 83 int CreatePortPair(PortRef* port0_ref, PortRef* port1_ref); |
| 84 |
| 85 // User data associated with the port. |
| 86 int SetUserData(const PortRef& port_ref, |
| 87 const scoped_refptr<UserData>& user_data); |
| 88 int GetUserData(const PortRef& port_ref, |
| 89 scoped_refptr<UserData>* user_data); |
| 90 |
| 91 // Prevents further messages from being sent from this port or delivered to |
| 92 // this port. The port is removed, and the port's peer is notified of the |
| 93 // closure after it has consumed all pending messages. |
| 94 int ClosePort(const PortRef& port_ref); |
| 95 |
| 96 // Returns the current status of the port. |
| 97 int GetStatus(const PortRef& port_ref, PortStatus* port_status); |
| 98 |
| 99 // Returns the next available message on the specified port or returns a null |
| 100 // message if there are none available. Returns ERROR_PORT_PEER_CLOSED to |
| 101 // indicate that this port's peer has closed. In such cases GetMessage may |
| 102 // be called until it yields a null message, indicating that no more messages |
| 103 // may be read from the port. |
| 104 int GetMessage(const PortRef& port_ref, ScopedMessage* message); |
| 105 |
| 106 // Like GetMessage, but the caller may optionally supply a selector function |
| 107 // that decides whether or not to return the message. If |selector| is a |
| 108 // nullptr, then GetMessageIf acts just like GetMessage. The |selector| may |
| 109 // not call any Node methods. |
| 110 int GetMessageIf(const PortRef& port_ref, |
| 111 std::function<bool(const Message&)> selector, |
| 112 ScopedMessage* message); |
| 113 |
| 114 // Sends a message from the specified port to its peer. Note that the message |
| 115 // notification may arrive synchronously (via PortStatusChanged() on the |
| 116 // delegate) if the peer is local to this Node. |
| 117 // |
| 118 // If send fails for any reason, |message| is left unchanged. On success, |
| 119 // ownserhip is transferred and |message| is reset. |
| 120 int SendMessage(const PortRef& port_ref, ScopedMessage* message); |
| 121 |
| 122 // Corresponding to NodeDelegate::ForwardMessage. |
| 123 int AcceptMessage(ScopedMessage message); |
| 124 |
| 125 // Called to inform this node that communication with another node is lost |
| 126 // indefinitely. This triggers cleanup of ports bound to this node. |
| 127 int LostConnectionToNode(const NodeName& node_name); |
| 128 |
| 129 private: |
| 130 int OnUserMessage(ScopedMessage message); |
| 131 int OnPortAccepted(const PortName& port_name); |
| 132 int OnObserveProxy(const PortName& port_name, |
| 133 const ObserveProxyEventData& event); |
| 134 int OnObserveProxyAck(const PortName& port_name, uint64_t last_sequence_num); |
| 135 int OnObserveClosure(const PortName& port_name, uint64_t last_sequence_num); |
| 136 |
| 137 int AddPortWithName(const PortName& port_name, |
| 138 const scoped_refptr<Port>& port); |
| 139 void ErasePort(const PortName& port_name); |
| 140 void ErasePort_Locked(const PortName& port_name); |
| 141 scoped_refptr<Port> GetPort(const PortName& port_name); |
| 142 scoped_refptr<Port> GetPort_Locked(const PortName& port_name); |
| 143 |
| 144 void WillSendPort_Locked(Port* port, |
| 145 const NodeName& to_node_name, |
| 146 PortName* port_name, |
| 147 PortDescriptor* port_descriptor); |
| 148 int AcceptPort(const PortName& port_name, |
| 149 const PortDescriptor& port_descriptor); |
| 150 |
| 151 int WillSendMessage_Locked(Port* port, |
| 152 const PortName& port_name, |
| 153 Message* message); |
| 154 int ForwardMessages_Locked(Port* port, const PortName& port_name); |
| 155 void InitiateProxyRemoval_Locked(Port* port, const PortName& port_name); |
| 156 void MaybeRemoveProxy_Locked(Port* port, const PortName& port_name); |
| 157 |
| 158 ScopedMessage NewInternalMessage_Helper(const PortName& port_name, |
| 159 const EventType& type, |
| 160 const void* data, |
| 161 size_t num_data_bytes); |
| 162 |
| 163 ScopedMessage NewInternalMessage(const PortName& port_name, |
| 164 const EventType& type) { |
| 165 return NewInternalMessage_Helper(port_name, type, nullptr, 0); |
| 166 } |
| 167 |
| 168 template <typename EventData> |
| 169 ScopedMessage NewInternalMessage(const PortName& port_name, |
| 170 const EventType& type, |
| 171 const EventData& data) { |
| 172 return NewInternalMessage_Helper(port_name, type, &data, sizeof(data)); |
| 173 } |
| 174 |
| 175 const NodeName name_; |
| 176 NodeDelegate* const delegate_; |
| 177 |
| 178 // Guards |ports_| as well as any operation which needs to hold multiple port |
| 179 // locks simultaneously. Usage of this is subtle: it must NEVER be acquired |
| 180 // after a Port lock is acquired, and it must ALWAYS be acquired before |
| 181 // calling WillSendMessage_Locked or ForwardMessages_Locked. |
| 182 base::Lock ports_lock_; |
| 183 std::unordered_map<PortName, scoped_refptr<Port>> ports_; |
| 184 |
| 185 DISALLOW_COPY_AND_ASSIGN(Node); |
| 186 }; |
| 187 |
| 188 } // namespace ports |
| 189 } // namespace edk |
| 190 } // namespace mojo |
| 191 |
| 192 #endif // MOJO_EDK_SYSTEM_PORTS_NODE_H_ |
OLD | NEW |