OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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_SYSTEM_CHANNEL_ENDPOINT_H_ |
| 6 #define MOJO_SYSTEM_CHANNEL_ENDPOINT_H_ |
| 7 |
| 8 #include "base/macros.h" |
| 9 #include "base/memory/ref_counted.h" |
| 10 #include "mojo/system/message_pipe.h" |
| 11 #include "mojo/system/system_impl_export.h" |
| 12 |
| 13 namespace mojo { |
| 14 namespace system { |
| 15 |
| 16 class Channel; |
| 17 |
| 18 // TODO(vtl): The plan: |
| 19 // - (Done.) Move |Channel::Endpoint| to |ChannelEndpoint|. Make it |
| 20 // refcounted, and not copyable. Make |Channel| a friend. Make things work. |
| 21 // - Give |ChannelEndpoint| a lock (which nothing else should be called |
| 22 // under -- thus can be taken under any other lock, in particular |
| 23 // |Channel|'s lock and |MessagePipe|'s lock). Stop having |Channel| as a |
| 24 // friend. |
| 25 // - Move logic from |ProxyMessagePipeEndpoint| into |ChannelEndpoint|. Right |
| 26 // now, we have to go through lots of contortions to manipulate state owned |
| 27 // by |ProxyMessagePipeEndpoint| (in particular, |Channel::Endpoint| doesn't |
| 28 // know about the remote ID; the local ID is duplicated in two places). |
| 29 // Hollow out |ProxyMessagePipeEndpoint|, and have it just own a reference |
| 30 // to |ChannelEndpoint| (hence the refcounting). |
| 31 // - In essence, |ChannelEndpoint| becomes the thing that knows about |
| 32 // channel-specific aspects of an endpoint (notably local and remote IDs, |
| 33 // and knowledge about handshaking), and mediates between the |Channel| and |
| 34 // the |MessagePipe|. |
| 35 // |
| 36 // Things as they are now, before I change everything (TODO(vtl): update this |
| 37 // comment appropriately): |
| 38 // |
| 39 // Terminology: |
| 40 // - "Message pipe endpoint": In the implementation, a |MessagePipe| owns |
| 41 // two |MessagePipeEndpoint| objects, one for each port. The |
| 42 // |MessagePipeEndpoint| objects are only accessed via the |MessagePipe| |
| 43 // (which has the lock), with the additional information of the port |
| 44 // number. So as far as the channel is concerned, a message pipe endpoint |
| 45 // is a pointer to a |MessagePipe| together with the port number. |
| 46 // - The value of |port| in |EndpointInfo| refers to the |
| 47 // |ProxyMessagePipeEndpoint| (i.e., the endpoint that is logically on |
| 48 // the other side). Messages received by a channel for a message pipe |
| 49 // are thus written to the *peer* of this port. |
| 50 // - "Attached"/"detached": A message pipe endpoint is attached to a channel |
| 51 // if it has a pointer to it. It must be detached before the channel gives |
| 52 // up its pointer to it in order to break a reference cycle. (This cycle |
| 53 // is needed to allow a channel to be shut down cleanly, without shutting |
| 54 // down everything else first.) |
| 55 // - "Running" (message pipe endpoint): A message pipe endpoint is running |
| 56 // if messages written to it (via some |MessagePipeDispatcher|, to which |
| 57 // some |MojoHandle| is assigned) are being transmitted through the |
| 58 // channel. |
| 59 // - Before a message pipe endpoint is run, it will queue messages. |
| 60 // - When a message pipe endpoint is detached from a channel, it is also |
| 61 // taken out of the running state. After that point, messages should |
| 62 // no longer be written to it. |
| 63 // - "Normal" message pipe endpoint (state): The channel itself does not |
| 64 // have knowledge of whether a message pipe endpoint has started running |
| 65 // yet. It will *receive* messages for a message pipe in either state (but |
| 66 // the message pipe endpoint won't *send* messages to the channel if it |
| 67 // has not started running). |
| 68 // - "Zombie" message pipe endpoint (state): A message pipe endpoint is a |
| 69 // zombie if it is still in |local_id_to_endpoint_info_map_|, but the |
| 70 // channel is no longer forwarding messages to it (even if it may still be |
| 71 // receiving messages for it). |
| 72 // - There are various types of zombies, depending on the reason the |
| 73 // message pipe endpoint cannot yet be removed. |
| 74 // - If the remote side is closed, it will send a "remove" control |
| 75 // message. After the channel receives that message (to which it |
| 76 // responds with a "remove ack" control message), it knows that it |
| 77 // shouldn't receive any more messages for that message pipe endpoint |
| 78 // (local ID), but it must wait for the endpoint to detach. (It can't |
| 79 // do so without a race, since it can't call into the message pipe |
| 80 // under |lock_|.) [TODO(vtl): When I add remotely-allocated IDs, |
| 81 // we'll have to remove the |EndpointInfo| from |
| 82 // |local_id_to_endpoint_info_map_| -- i.e., remove the local ID, |
| 83 // since it's no longer valid and may be reused by the remote side -- |
| 84 // and keep the |EndpointInfo| alive in some other way.] |
| 85 // - If the local side is closed and the message pipe endpoint was |
| 86 // already running (so there are no queued messages left to send), it |
| 87 // will detach the endpoint, and send a "remove" control message. |
| 88 // However, the channel may still receive messages for that endpoint |
| 89 // until it receives a "remove ack" control message. |
| 90 // - If the local side is closed but the message pipe endpoint was not |
| 91 // yet running , the detaching is delayed until after it is run and |
| 92 // all the queued messages are sent to the channel. On being detached, |
| 93 // things proceed as in one of the above cases. The endpoint is *not* |
| 94 // a zombie until it is detached (or a "remove" message is received). |
| 95 // [TODO(vtl): Maybe we can get rid of this case? It'd only not yet be |
| 96 // running since under the current scheme it wouldn't have a remote ID |
| 97 // yet.] |
| 98 // - Note that even if the local side is closed, it may still receive a |
| 99 // "remove" message from the other side (if the other side is closed |
| 100 // simultaneously, and both sides send "remove" messages). In that |
| 101 // case, it must still remain alive until it receives the "remove |
| 102 // ack" (and it must ack the "remove" message that it received). |
| 103 class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint |
| 104 : public base::RefCountedThreadSafe<ChannelEndpoint> { |
| 105 public: |
| 106 ChannelEndpoint(MessagePipe* message_pipe, unsigned port); |
| 107 |
| 108 private: |
| 109 enum State { |
| 110 // Attached, possibly running or not. |
| 111 STATE_NORMAL, |
| 112 // "Zombie" states: |
| 113 // Waiting for |DetachMessagePipeEndpoint()| before removing. |
| 114 STATE_WAIT_LOCAL_DETACH, |
| 115 // Waiting for a |kSubtypeChannelRemoveMessagePipeEndpointAck| before |
| 116 // removing. |
| 117 STATE_WAIT_REMOTE_REMOVE_ACK, |
| 118 }; |
| 119 |
| 120 // TODO(vtl): This is totally temporary, until this becomes a proper |
| 121 // self-contained class. See the plan above. |
| 122 friend class Channel; |
| 123 |
| 124 friend class base::RefCountedThreadSafe<ChannelEndpoint>; |
| 125 ~ChannelEndpoint(); |
| 126 |
| 127 State state_; |
| 128 scoped_refptr<MessagePipe> message_pipe_; |
| 129 unsigned port_; |
| 130 |
| 131 DISALLOW_COPY_AND_ASSIGN(ChannelEndpoint); |
| 132 }; |
| 133 |
| 134 } // namespace system |
| 135 } // namespace mojo |
| 136 |
| 137 #endif // MOJO_SYSTEM_CHANNEL_ENDPOINT_H_ |
OLD | NEW |