• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CORE_PORTS_NODE_H_
6 #define MOJO_CORE_PORTS_NODE_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <queue>
12 #include <unordered_map>
13 
14 #include "base/component_export.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/synchronization/lock.h"
18 #include "mojo/core/ports/event.h"
19 #include "mojo/core/ports/name.h"
20 #include "mojo/core/ports/port.h"
21 #include "mojo/core/ports/port_ref.h"
22 #include "mojo/core/ports/user_data.h"
23 
24 namespace mojo {
25 namespace core {
26 namespace ports {
27 
28 enum : int {
29   OK = 0,
30   ERROR_PORT_UNKNOWN = -10,
31   ERROR_PORT_EXISTS = -11,
32   ERROR_PORT_STATE_UNEXPECTED = -12,
33   ERROR_PORT_CANNOT_SEND_SELF = -13,
34   ERROR_PORT_PEER_CLOSED = -14,
35   ERROR_PORT_CANNOT_SEND_PEER = -15,
36   ERROR_NOT_IMPLEMENTED = -100,
37 };
38 
39 struct PortStatus {
40   bool has_messages;
41   bool receiving_messages;
42   bool peer_closed;
43   bool peer_remote;
44   size_t queued_message_count;
45   size_t queued_num_bytes;
46 };
47 
48 class MessageFilter;
49 class NodeDelegate;
50 
51 // A Node maintains a collection of Ports (see port.h) indexed by unique 128-bit
52 // addresses (names), performing routing and processing of events among the
53 // Ports within the Node and to or from other Nodes in the system. Typically
54 // (and practically, in all uses today) there is a single Node per system
55 // process. Thus a Node boundary effectively models a process boundary.
56 //
57 // New Ports can be created uninitialized using CreateUninitializedPort (and
58 // later initialized using InitializePort), or created in a fully initialized
59 // state using CreatePortPair(). Initialized ports have exactly one conjugate
60 // port which is the ultimate receiver of any user messages sent by that port.
61 // See SendUserMessage().
62 //
63 // In addition to routing user message events, various control events are used
64 // by Nodes to coordinate Port behavior and lifetime within and across Nodes.
65 // See Event documentation for description of different types of events used by
66 // a Node to coordinate behavior.
COMPONENT_EXPORT(MOJO_CORE_PORTS)67 class COMPONENT_EXPORT(MOJO_CORE_PORTS) Node {
68  public:
69   enum class ShutdownPolicy {
70     DONT_ALLOW_LOCAL_PORTS,
71     ALLOW_LOCAL_PORTS,
72   };
73 
74   // Does not take ownership of the delegate.
75   Node(const NodeName& name, NodeDelegate* delegate);
76   ~Node();
77 
78   // Returns true iff there are no open ports referring to another node or ports
79   // in the process of being transferred from this node to another. If this
80   // returns false, then to ensure clean shutdown, it is necessary to keep the
81   // node alive and continue routing messages to it via AcceptMessage. This
82   // method may be called again after AcceptMessage to check if the Node is now
83   // ready to be destroyed.
84   //
85   // If |policy| is set to |ShutdownPolicy::ALLOW_LOCAL_PORTS|, this will return
86   // |true| even if some ports remain alive, as long as none of them are proxies
87   // to another node.
88   bool CanShutdownCleanly(
89       ShutdownPolicy policy = ShutdownPolicy::DONT_ALLOW_LOCAL_PORTS);
90 
91   // Lookup the named port.
92   int GetPort(const PortName& port_name, PortRef* port_ref);
93 
94   // Creates a port on this node. Before the port can be used, it must be
95   // initialized using InitializePort. This method is useful for bootstrapping
96   // a connection between two nodes. Generally, ports are created using
97   // CreatePortPair instead.
98   int CreateUninitializedPort(PortRef* port_ref);
99 
100   // Initializes a newly created port.
101   int InitializePort(const PortRef& port_ref,
102                      const NodeName& peer_node_name,
103                      const PortName& peer_port_name);
104 
105   // Generates a new connected pair of ports bound to this node. These ports
106   // are initialized and ready to go.
107   int CreatePortPair(PortRef* port0_ref, PortRef* port1_ref);
108 
109   // User data associated with the port.
110   int SetUserData(const PortRef& port_ref, scoped_refptr<UserData> user_data);
111   int GetUserData(const PortRef& port_ref, scoped_refptr<UserData>* user_data);
112 
113   // Prevents further messages from being sent from this port or delivered to
114   // this port. The port is removed, and the port's peer is notified of the
115   // closure after it has consumed all pending messages.
116   int ClosePort(const PortRef& port_ref);
117 
118   // Returns the current status of the port.
119   int GetStatus(const PortRef& port_ref, PortStatus* port_status);
120 
121   // Returns the next available message on the specified port or returns a null
122   // message if there are none available. Returns ERROR_PORT_PEER_CLOSED to
123   // indicate that this port's peer has closed. In such cases GetMessage may
124   // be called until it yields a null message, indicating that no more messages
125   // may be read from the port.
126   //
127   // If |filter| is non-null, the next available message is returned only if it
128   // is matched by the filter. If the provided filter does not match the next
129   // available message, GetMessage() behaves as if there is no message
130   // available. Ownership of |filter| is not taken, and it must outlive the
131   // extent of this call.
132   int GetMessage(const PortRef& port_ref,
133                  std::unique_ptr<UserMessageEvent>* message,
134                  MessageFilter* filter);
135 
136   // Sends a message from the specified port to its peer. Note that the message
137   // notification may arrive synchronously (via PortStatusChanged() on the
138   // delegate) if the peer is local to this Node.
139   int SendUserMessage(const PortRef& port_ref,
140                       std::unique_ptr<UserMessageEvent> message);
141 
142   // Corresponding to NodeDelegate::ForwardEvent.
143   int AcceptEvent(ScopedEvent event);
144 
145   // Called to merge two ports with each other. If you have two independent
146   // port pairs A <=> B and C <=> D, the net result of merging B and C is a
147   // single connected port pair A <=> D.
148   //
149   // Note that the behavior of this operation is undefined if either port to be
150   // merged (B or C above) has ever been read from or written to directly, and
151   // this must ONLY be called on one side of the merge, though it doesn't matter
152   // which side.
153   //
154   // It is safe for the non-merged peers (A and D above) to be transferred,
155   // closed, and/or written to before, during, or after the merge.
156   int MergePorts(const PortRef& port_ref,
157                  const NodeName& destination_node_name,
158                  const PortName& destination_port_name);
159 
160   // Like above but merges two ports local to this node. Because both ports are
161   // local this can also verify that neither port has been written to before the
162   // merge. If this fails for any reason, both ports are closed. Otherwise OK
163   // is returned and the ports' receiving peers are connected to each other.
164   int MergeLocalPorts(const PortRef& port0_ref, const PortRef& port1_ref);
165 
166   // Called to inform this node that communication with another node is lost
167   // indefinitely. This triggers cleanup of ports bound to this node.
168   int LostConnectionToNode(const NodeName& node_name);
169 
170  private:
171   // Helper to ensure that a Node always calls into its delegate safely, i.e.
172   // without holding any internal locks.
173   class DelegateHolder {
174    public:
175     DelegateHolder(Node* node, NodeDelegate* delegate);
176     ~DelegateHolder();
177 
178     NodeDelegate* operator->() const {
179       EnsureSafeDelegateAccess();
180       return delegate_;
181     }
182 
183    private:
184 #if DCHECK_IS_ON()
185     void EnsureSafeDelegateAccess() const;
186 #else
187     void EnsureSafeDelegateAccess() const {}
188 #endif
189 
190     Node* const node_;
191     NodeDelegate* const delegate_;
192 
193     DISALLOW_COPY_AND_ASSIGN(DelegateHolder);
194   };
195 
196   int OnUserMessage(std::unique_ptr<UserMessageEvent> message);
197   int OnPortAccepted(std::unique_ptr<PortAcceptedEvent> event);
198   int OnObserveProxy(std::unique_ptr<ObserveProxyEvent> event);
199   int OnObserveProxyAck(std::unique_ptr<ObserveProxyAckEvent> event);
200   int OnObserveClosure(std::unique_ptr<ObserveClosureEvent> event);
201   int OnMergePort(std::unique_ptr<MergePortEvent> event);
202 
203   int AddPortWithName(const PortName& port_name, scoped_refptr<Port> port);
204   void ErasePort(const PortName& port_name);
205 
206   int SendUserMessageInternal(const PortRef& port_ref,
207                               std::unique_ptr<UserMessageEvent>* message);
208   int MergePortsInternal(const PortRef& port0_ref,
209                          const PortRef& port1_ref,
210                          bool allow_close_on_bad_state);
211   void ConvertToProxy(Port* port,
212                       const NodeName& to_node_name,
213                       PortName* port_name,
214                       Event::PortDescriptor* port_descriptor);
215   int AcceptPort(const PortName& port_name,
216                  const Event::PortDescriptor& port_descriptor);
217 
218   int PrepareToForwardUserMessage(const PortRef& forwarding_port_ref,
219                                   Port::State expected_port_state,
220                                   bool ignore_closed_peer,
221                                   UserMessageEvent* message,
222                                   NodeName* forward_to_node);
223   int BeginProxying(const PortRef& port_ref);
224   int ForwardUserMessagesFromProxy(const PortRef& port_ref);
225   void InitiateProxyRemoval(const PortRef& port_ref);
226   void TryRemoveProxy(const PortRef& port_ref);
227   void DestroyAllPortsWithPeer(const NodeName& node_name,
228                                const PortName& port_name);
229 
230   const NodeName name_;
231   const DelegateHolder delegate_;
232 
233   // Guards |ports_|. This must never be acquired while an individual port's
234   // lock is held on the same thread. Conversely, individual port locks may be
235   // acquired while this one is held.
236   //
237   // Because UserMessage events may execute arbitrary user code during
238   // destruction, it is also important to ensure that such events are never
239   // destroyed while this (or any individual Port) lock is held.
240   base::Lock ports_lock_;
241   std::unordered_map<PortName, scoped_refptr<Port>> ports_;
242 
243   DISALLOW_COPY_AND_ASSIGN(Node);
244 };
245 
246 }  // namespace ports
247 }  // namespace core
248 }  // namespace mojo
249 
250 #endif  // MOJO_CORE_PORTS_NODE_H_
251