OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/edk/system/channel_endpoint.h" | 5 #include "mojo/edk/system/channel_endpoint.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 case State::RUNNING: | 28 case State::RUNNING: |
29 return WriteMessageNoLock(std::move(message)); | 29 return WriteMessageNoLock(std::move(message)); |
30 case State::DEAD: | 30 case State::DEAD: |
31 return false; | 31 return false; |
32 } | 32 } |
33 | 33 |
34 NOTREACHED(); | 34 NOTREACHED(); |
35 return false; | 35 return false; |
36 } | 36 } |
37 | 37 |
38 bool ChannelEndpoint::ReplaceClient(ChannelEndpointClient* client, | 38 bool ChannelEndpoint::ReplaceClient(RefPtr<ChannelEndpointClient>&& client, |
39 unsigned client_port) { | 39 unsigned client_port) { |
40 DCHECK(client); | 40 DCHECK(client); |
41 | 41 |
42 MutexLocker locker(&mutex_); | 42 MutexLocker locker(&mutex_); |
43 DCHECK(client_); | 43 DCHECK(client_); |
44 DCHECK(client != client_.get() || client_port != client_port_); | 44 DCHECK(client != client_ || client_port != client_port_); |
45 client_ = client; | 45 client_ = std::move(client); |
46 client_port_ = client_port; | 46 client_port_ = client_port; |
47 return state_ != State::DEAD; | 47 return state_ != State::DEAD; |
48 } | 48 } |
49 | 49 |
50 void ChannelEndpoint::DetachFromClient() { | 50 void ChannelEndpoint::DetachFromClient() { |
51 MutexLocker locker(&mutex_); | 51 MutexLocker locker(&mutex_); |
52 DCHECK(client_); | 52 DCHECK(client_); |
53 client_ = nullptr; | 53 client_ = nullptr; |
54 | 54 |
55 if (!channel_) | 55 if (!channel_) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT); | 95 DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT); |
96 | 96 |
97 // TODO(vtl) | 97 // TODO(vtl) |
98 // Note that this won't crash on Release builds, which is important (since the | 98 // Note that this won't crash on Release builds, which is important (since the |
99 // other side may be malicious). Doing nothing is safe and will dispose of the | 99 // other side may be malicious). Doing nothing is safe and will dispose of the |
100 // message. | 100 // message. |
101 NOTREACHED(); | 101 NOTREACHED(); |
102 } | 102 } |
103 | 103 |
104 void ChannelEndpoint::DetachFromChannel() { | 104 void ChannelEndpoint::DetachFromChannel() { |
105 scoped_refptr<ChannelEndpointClient> client; | 105 RefPtr<ChannelEndpointClient> client; |
106 unsigned client_port = 0; | 106 unsigned client_port = 0; |
107 { | 107 { |
108 MutexLocker locker(&mutex_); | 108 MutexLocker locker(&mutex_); |
109 | 109 |
110 if (client_) { | 110 if (client_) { |
111 // Take a ref, and call |OnDetachFromChannel()| outside the lock. | 111 // Take a ref, and call |OnDetachFromChannel()| outside the lock. |
112 client = client_; | 112 client = client_; |
113 client_port = client_port_; | 113 client_port = client_port_; |
114 } | 114 } |
115 | 115 |
116 // |channel_| may already be null if we already detached from the channel in | 116 // |channel_| may already be null if we already detached from the channel in |
117 // |DetachFromClient()| by calling |Channel::DetachEndpoint()| (and there | 117 // |DetachFromClient()| by calling |Channel::DetachEndpoint()| (and there |
118 // are racing detaches). | 118 // are racing detaches). |
119 if (channel_) | 119 if (channel_) |
120 DieNoLock(); | 120 DieNoLock(); |
121 else | 121 else |
122 DCHECK(state_ == State::DEAD); | 122 DCHECK(state_ == State::DEAD); |
123 } | 123 } |
124 | 124 |
125 // If |ReplaceClient()| is called (from another thread) after the above locked | 125 // If |ReplaceClient()| is called (from another thread) after the above locked |
126 // section but before we call |OnDetachFromChannel()|, |ReplaceClient()| | 126 // section but before we call |OnDetachFromChannel()|, |ReplaceClient()| |
127 // returns false to notify the caller that the channel was already detached. | 127 // returns false to notify the caller that the channel was already detached. |
128 // (The old client has to accept the arguably-spurious call to | 128 // (The old client has to accept the arguably-spurious call to |
129 // |OnDetachFromChannel()|.) | 129 // |OnDetachFromChannel()|.) |
130 if (client) | 130 if (client) |
131 client->OnDetachFromChannel(client_port); | 131 client->OnDetachFromChannel(client_port); |
132 } | 132 } |
133 | 133 |
134 ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client, | 134 ChannelEndpoint::ChannelEndpoint(RefPtr<ChannelEndpointClient>&& client, |
135 unsigned client_port, | 135 unsigned client_port, |
136 MessageInTransitQueue* message_queue) | 136 MessageInTransitQueue* message_queue) |
137 : state_(State::PAUSED), | 137 : state_(State::PAUSED), |
138 client_(client), | 138 client_(std::move(client)), |
139 client_port_(client_port), | 139 client_port_(client_port), |
140 channel_(nullptr) { | 140 channel_(nullptr) { |
141 DCHECK(client_ || message_queue); | 141 DCHECK(client_ || message_queue); |
142 | 142 |
143 if (message_queue) | 143 if (message_queue) |
144 channel_message_queue_.Swap(message_queue); | 144 channel_message_queue_.Swap(message_queue); |
145 } | 145 } |
146 | 146 |
147 ChannelEndpoint::~ChannelEndpoint() { | 147 ChannelEndpoint::~ChannelEndpoint() { |
148 DCHECK(!client_); | 148 DCHECK(!client_); |
(...skipping 15 matching lines...) Expand all Loading... |
164 message->SerializeAndCloseDispatchers(channel_); | 164 message->SerializeAndCloseDispatchers(channel_); |
165 message->set_source_id(local_id_); | 165 message->set_source_id(local_id_); |
166 message->set_destination_id(remote_id_); | 166 message->set_destination_id(remote_id_); |
167 return channel_->WriteMessage(std::move(message)); | 167 return channel_->WriteMessage(std::move(message)); |
168 } | 168 } |
169 | 169 |
170 void ChannelEndpoint::OnReadMessageForClient( | 170 void ChannelEndpoint::OnReadMessageForClient( |
171 std::unique_ptr<MessageInTransit> message) { | 171 std::unique_ptr<MessageInTransit> message) { |
172 DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); | 172 DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT); |
173 | 173 |
174 scoped_refptr<ChannelEndpointClient> client; | 174 RefPtr<ChannelEndpointClient> client; |
175 unsigned client_port = 0; | 175 unsigned client_port = 0; |
176 | 176 |
177 // This loop is to make |ReplaceClient()| work. We can't call the client's | 177 // This loop is to make |ReplaceClient()| work. We can't call the client's |
178 // |OnReadMessage()| under our lock, so by the time we do that, |client| may | 178 // |OnReadMessage()| under our lock, so by the time we do that, |client| may |
179 // no longer be our client. | 179 // no longer be our client. |
180 // | 180 // |
181 // In that case, |client| must return false. We'll then yield, and retry with | 181 // In that case, |client| must return false. We'll then yield, and retry with |
182 // the new client. (Theoretically, the client could be replaced again.) | 182 // the new client. (Theoretically, the client could be replaced again.) |
183 // | 183 // |
184 // This solution isn't terribly elegant, but it's the least costly way of | 184 // This solution isn't terribly elegant, but it's the least costly way of |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 DCHECK(remote_id_.is_valid()); | 219 DCHECK(remote_id_.is_valid()); |
220 | 220 |
221 state_ = State::DEAD; | 221 state_ = State::DEAD; |
222 channel_ = nullptr; | 222 channel_ = nullptr; |
223 local_id_ = ChannelEndpointId(); | 223 local_id_ = ChannelEndpointId(); |
224 remote_id_ = ChannelEndpointId(); | 224 remote_id_ = ChannelEndpointId(); |
225 } | 225 } |
226 | 226 |
227 } // namespace system | 227 } // namespace system |
228 } // namespace mojo | 228 } // namespace mojo |
OLD | NEW |