| 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 |