OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/renderer/p2p/ipc_socket_factory.h" | 5 #include "content/renderer/p2p/ipc_socket_factory.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
10 #include "content/renderer/p2p/socket_client.h" | 10 #include "content/renderer/p2p/socket_client.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 public: | 22 public: |
23 IpcPacketSocket(); | 23 IpcPacketSocket(); |
24 virtual ~IpcPacketSocket(); | 24 virtual ~IpcPacketSocket(); |
25 | 25 |
26 // Always takes ownership of client even if initialization fails. | 26 // Always takes ownership of client even if initialization fails. |
27 bool Init(P2PSocketType type, P2PSocketClient* client, | 27 bool Init(P2PSocketType type, P2PSocketClient* client, |
28 const talk_base::SocketAddress& local_address, | 28 const talk_base::SocketAddress& local_address, |
29 const talk_base::SocketAddress& remote_address); | 29 const talk_base::SocketAddress& remote_address); |
30 | 30 |
31 // talk_base::AsyncPacketSocket interface. | 31 // talk_base::AsyncPacketSocket interface. |
32 virtual bool GetLocalAddress(talk_base::SocketAddress* address) const; | 32 virtual talk_base::SocketAddress GetLocalAddress() const; |
33 virtual talk_base::SocketAddress GetRemoteAddress() const; | 33 virtual talk_base::SocketAddress GetRemoteAddress() const; |
34 virtual int Send(const void *pv, size_t cb); | 34 virtual int Send(const void *pv, size_t cb); |
35 virtual int SendTo(const void *pv, size_t cb, | 35 virtual int SendTo(const void *pv, size_t cb, |
36 const talk_base::SocketAddress& addr); | 36 const talk_base::SocketAddress& addr); |
37 virtual int Close(); | 37 virtual int Close(); |
38 virtual talk_base::Socket::ConnState GetState() const; | 38 virtual State GetState() const; |
39 virtual int GetOption(talk_base::Socket::Option opt, int* value); | 39 virtual int GetOption(talk_base::Socket::Option opt, int* value); |
40 virtual int SetOption(talk_base::Socket::Option opt, int value); | 40 virtual int SetOption(talk_base::Socket::Option opt, int value); |
41 virtual int GetError() const; | 41 virtual int GetError() const; |
42 virtual void SetError(int error); | 42 virtual void SetError(int error); |
43 | 43 |
44 // P2PSocketClient::Delegate implementation. | 44 // P2PSocketClient::Delegate implementation. |
45 virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE; | 45 virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE; |
46 virtual void OnIncomingTcpConnection(const net::IPEndPoint& address, | 46 virtual void OnIncomingTcpConnection(const net::IPEndPoint& address, |
47 P2PSocketClient* client) OVERRIDE; | 47 P2PSocketClient* client) OVERRIDE; |
48 virtual void OnError(); | 48 virtual void OnError(); |
49 virtual void OnDataReceived(const net::IPEndPoint& address, | 49 virtual void OnDataReceived(const net::IPEndPoint& address, |
50 const std::vector<char>& data) OVERRIDE; | 50 const std::vector<char>& data) OVERRIDE; |
51 | 51 |
52 private: | 52 private: |
53 enum State { | 53 enum InternalState { |
54 STATE_UNINITIALIZED, | 54 IS_UNINITIALIZED, |
55 STATE_OPENING, | 55 IS_OPENING, |
56 STATE_OPEN, | 56 IS_OPEN, |
57 STATE_CLOSED, | 57 IS_CLOSED, |
58 STATE_ERROR, | 58 IS_ERROR, |
59 }; | 59 }; |
60 | 60 |
61 void InitAcceptedTcp(P2PSocketClient* client, | 61 void InitAcceptedTcp(P2PSocketClient* client, |
62 const talk_base::SocketAddress& local_address, | 62 const talk_base::SocketAddress& local_address, |
63 const talk_base::SocketAddress& remote_address); | 63 const talk_base::SocketAddress& remote_address); |
64 | 64 |
| 65 P2PSocketType type_; |
| 66 |
65 // Message loop on which this socket was created and being used. | 67 // Message loop on which this socket was created and being used. |
66 MessageLoop* message_loop_; | 68 MessageLoop* message_loop_; |
67 | 69 |
68 // Corresponding P2P socket client. | 70 // Corresponding P2P socket client. |
69 scoped_refptr<P2PSocketClient> client_; | 71 scoped_refptr<P2PSocketClient> client_; |
70 | 72 |
71 // Local address is allocated by the browser process, and the | 73 // Local address is allocated by the browser process, and the |
72 // renderer side doesn't know the address until it receives OnOpen() | 74 // renderer side doesn't know the address until it receives OnOpen() |
73 // event from the browser. | 75 // event from the browser. |
74 talk_base::SocketAddress local_address_; | 76 talk_base::SocketAddress local_address_; |
75 bool address_initialized_; | |
76 | 77 |
77 // Remote address for client TCP connections. | 78 // Remote address for client TCP connections. |
78 talk_base::SocketAddress remote_address_; | 79 talk_base::SocketAddress remote_address_; |
79 | 80 |
80 // Current state of the object. | 81 // Current state of the object. |
81 State state_; | 82 InternalState state_; |
82 | 83 |
83 // Current error code. Valid when state_ == STATE_ERROR. | 84 // Current error code. Valid when state_ == IS_ERROR. |
84 int error_; | 85 int error_; |
85 | 86 |
86 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket); | 87 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket); |
87 }; | 88 }; |
88 | 89 |
89 IpcPacketSocket::IpcPacketSocket() | 90 IpcPacketSocket::IpcPacketSocket() |
90 : message_loop_(MessageLoop::current()), | 91 : message_loop_(MessageLoop::current()), |
91 address_initialized_(false), | 92 state_(IS_UNINITIALIZED), error_(0) { |
92 state_(STATE_UNINITIALIZED), error_(0) { | |
93 } | 93 } |
94 | 94 |
95 IpcPacketSocket::~IpcPacketSocket() { | 95 IpcPacketSocket::~IpcPacketSocket() { |
96 if (state_ == STATE_OPENING || state_ == STATE_OPEN || | 96 if (state_ == IS_OPENING || state_ == IS_OPEN || |
97 state_ == STATE_ERROR) { | 97 state_ == IS_ERROR) { |
98 Close(); | 98 Close(); |
99 } | 99 } |
100 } | 100 } |
101 | 101 |
102 bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client, | 102 bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client, |
103 const talk_base::SocketAddress& local_address, | 103 const talk_base::SocketAddress& local_address, |
104 const talk_base::SocketAddress& remote_address) { | 104 const talk_base::SocketAddress& remote_address) { |
105 DCHECK_EQ(MessageLoop::current(), message_loop_); | 105 DCHECK_EQ(MessageLoop::current(), message_loop_); |
106 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 106 DCHECK_EQ(state_, IS_UNINITIALIZED); |
107 | 107 |
| 108 type_ = type; |
108 client_ = client; | 109 client_ = client; |
109 local_address_ = local_address; | 110 local_address_ = local_address; |
110 remote_address_ = remote_address; | 111 remote_address_ = remote_address; |
111 state_ = STATE_OPENING; | 112 state_ = IS_OPENING; |
112 | 113 |
113 net::IPEndPoint local_endpoint; | 114 net::IPEndPoint local_endpoint; |
114 if (!jingle_glue::SocketAddressToIPEndPoint(local_address, &local_endpoint)) { | 115 if (!jingle_glue::SocketAddressToIPEndPoint(local_address, &local_endpoint)) { |
115 return false; | 116 return false; |
116 } | 117 } |
117 | 118 |
118 net::IPEndPoint remote_endpoint; | 119 net::IPEndPoint remote_endpoint; |
119 if (!jingle_glue::SocketAddressToIPEndPoint( | 120 if (!jingle_glue::SocketAddressToIPEndPoint( |
120 remote_address, &remote_endpoint)) { | 121 remote_address, &remote_endpoint)) { |
121 return false; | 122 return false; |
122 } | 123 } |
123 | 124 |
124 client_->Init(type, local_endpoint, remote_endpoint, this, | 125 client_->Init(type, local_endpoint, remote_endpoint, this, |
125 base::MessageLoopProxy::CreateForCurrentThread()); | 126 base::MessageLoopProxy::CreateForCurrentThread()); |
126 | 127 |
127 return true; | 128 return true; |
128 } | 129 } |
129 | 130 |
130 void IpcPacketSocket::InitAcceptedTcp( | 131 void IpcPacketSocket::InitAcceptedTcp( |
131 P2PSocketClient* client, | 132 P2PSocketClient* client, |
132 const talk_base::SocketAddress& local_address, | 133 const talk_base::SocketAddress& local_address, |
133 const talk_base::SocketAddress& remote_address) { | 134 const talk_base::SocketAddress& remote_address) { |
134 DCHECK_EQ(MessageLoop::current(), message_loop_); | 135 DCHECK_EQ(MessageLoop::current(), message_loop_); |
135 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 136 DCHECK_EQ(state_, IS_UNINITIALIZED); |
136 | 137 |
137 client_ = client; | 138 client_ = client; |
138 local_address_ = local_address; | 139 local_address_ = local_address; |
139 remote_address_ = remote_address; | 140 remote_address_ = remote_address; |
140 state_ = STATE_OPEN; | 141 state_ = IS_OPEN; |
141 client_->set_delegate(this); | 142 client_->set_delegate(this); |
142 } | 143 } |
143 | 144 |
144 // talk_base::AsyncPacketSocket interface. | 145 // talk_base::AsyncPacketSocket interface. |
145 bool IpcPacketSocket::GetLocalAddress(talk_base::SocketAddress* address) const { | 146 talk_base::SocketAddress IpcPacketSocket::GetLocalAddress() const { |
146 DCHECK_EQ(MessageLoop::current(), message_loop_); | 147 DCHECK_EQ(MessageLoop::current(), message_loop_); |
147 | 148 return local_address_; |
148 if (!address_initialized_) | |
149 return false; | |
150 | |
151 *address = local_address_; | |
152 return true; | |
153 } | 149 } |
154 | 150 |
155 talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const { | 151 talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const { |
156 DCHECK_EQ(MessageLoop::current(), message_loop_); | 152 DCHECK_EQ(MessageLoop::current(), message_loop_); |
157 | |
158 return remote_address_; | 153 return remote_address_; |
159 } | 154 } |
160 | 155 |
161 int IpcPacketSocket::Send(const void *data, size_t data_size) { | 156 int IpcPacketSocket::Send(const void *data, size_t data_size) { |
162 DCHECK_EQ(MessageLoop::current(), message_loop_); | 157 DCHECK_EQ(MessageLoop::current(), message_loop_); |
163 return SendTo(data, data_size, remote_address_); | 158 return SendTo(data, data_size, remote_address_); |
164 } | 159 } |
165 | 160 |
166 int IpcPacketSocket::SendTo(const void *data, size_t data_size, | 161 int IpcPacketSocket::SendTo(const void *data, size_t data_size, |
167 const talk_base::SocketAddress& address) { | 162 const talk_base::SocketAddress& address) { |
168 DCHECK_EQ(MessageLoop::current(), message_loop_); | 163 DCHECK_EQ(MessageLoop::current(), message_loop_); |
169 | 164 |
170 switch (state_) { | 165 switch (state_) { |
171 case STATE_UNINITIALIZED: | 166 case IS_UNINITIALIZED: |
172 NOTREACHED(); | 167 NOTREACHED(); |
173 return EWOULDBLOCK; | 168 return EWOULDBLOCK; |
174 case STATE_OPENING: | 169 case IS_OPENING: |
175 return EWOULDBLOCK; | 170 return EWOULDBLOCK; |
176 case STATE_CLOSED: | 171 case IS_CLOSED: |
177 return ENOTCONN; | 172 return ENOTCONN; |
178 case STATE_ERROR: | 173 case IS_ERROR: |
179 return error_; | 174 return error_; |
180 case STATE_OPEN: | 175 case IS_OPEN: |
181 // Continue sending the packet. | 176 // Continue sending the packet. |
182 break; | 177 break; |
183 } | 178 } |
184 | 179 |
185 const char* data_char = reinterpret_cast<const char*>(data); | 180 const char* data_char = reinterpret_cast<const char*>(data); |
186 std::vector<char> data_vector(data_char, data_char + data_size); | 181 std::vector<char> data_vector(data_char, data_char + data_size); |
187 | 182 |
188 net::IPEndPoint address_chrome; | 183 net::IPEndPoint address_chrome; |
189 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { | 184 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { |
190 // Just drop the packet if we failed to convert the address. | 185 // Just drop the packet if we failed to convert the address. |
191 return 0; | 186 return 0; |
192 } | 187 } |
193 | 188 |
194 client_->Send(address_chrome, data_vector); | 189 client_->Send(address_chrome, data_vector); |
195 | 190 |
196 // Fake successful send. The caller ignores result anyway. | 191 // Fake successful send. The caller ignores result anyway. |
197 return data_size; | 192 return data_size; |
198 } | 193 } |
199 | 194 |
200 int IpcPacketSocket::Close() { | 195 int IpcPacketSocket::Close() { |
201 DCHECK_EQ(MessageLoop::current(), message_loop_); | 196 DCHECK_EQ(MessageLoop::current(), message_loop_); |
202 | 197 |
203 client_->Close(); | 198 client_->Close(); |
204 state_ = STATE_CLOSED; | 199 state_ = IS_CLOSED; |
205 | 200 |
206 return 0; | 201 return 0; |
207 } | 202 } |
208 | 203 |
209 talk_base::Socket::ConnState IpcPacketSocket::GetState() const { | 204 talk_base::AsyncPacketSocket::State IpcPacketSocket::GetState() const { |
210 DCHECK_EQ(MessageLoop::current(), message_loop_); | 205 DCHECK_EQ(MessageLoop::current(), message_loop_); |
211 | 206 |
212 switch (state_) { | 207 switch (state_) { |
213 case STATE_UNINITIALIZED: | 208 case IS_UNINITIALIZED: |
214 NOTREACHED(); | 209 NOTREACHED(); |
215 return talk_base::Socket::CS_CONNECTING; | 210 return STATE_CLOSED; |
216 | 211 |
217 case STATE_OPENING: | 212 case IS_OPENING: |
218 return talk_base::Socket::CS_CONNECTING; | 213 return STATE_BINDING; |
219 | 214 |
220 case STATE_OPEN: | 215 case IS_OPEN: |
221 return talk_base::Socket::CS_CONNECTED; | 216 if (type_ == P2P_SOCKET_TCP_CLIENT) { |
| 217 return STATE_CONNECTED; |
| 218 } else { |
| 219 return STATE_BOUND; |
| 220 } |
222 | 221 |
223 case STATE_CLOSED: | 222 case IS_CLOSED: |
224 case STATE_ERROR: | 223 case IS_ERROR: |
225 return talk_base::Socket::CS_CLOSED; | 224 return STATE_CLOSED; |
226 } | 225 } |
227 | 226 |
228 NOTREACHED(); | 227 NOTREACHED(); |
229 return talk_base::Socket::CS_CLOSED; | 228 return STATE_CLOSED; |
230 } | 229 } |
231 | 230 |
232 int IpcPacketSocket::GetOption(talk_base::Socket::Option opt, int* value) { | 231 int IpcPacketSocket::GetOption(talk_base::Socket::Option opt, int* value) { |
233 // We don't support socket options for IPC sockets. | 232 // We don't support socket options for IPC sockets. |
234 return -1; | 233 return -1; |
235 } | 234 } |
236 | 235 |
237 int IpcPacketSocket::SetOption(talk_base::Socket::Option opt, int value) { | 236 int IpcPacketSocket::SetOption(talk_base::Socket::Option opt, int value) { |
238 // We don't support socket options for IPC sockets. | 237 // We don't support socket options for IPC sockets. |
239 // | 238 // |
(...skipping 15 matching lines...) Expand all Loading... |
255 void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) { | 254 void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) { |
256 DCHECK_EQ(MessageLoop::current(), message_loop_); | 255 DCHECK_EQ(MessageLoop::current(), message_loop_); |
257 | 256 |
258 if (!jingle_glue::IPEndPointToSocketAddress(address, &local_address_)) { | 257 if (!jingle_glue::IPEndPointToSocketAddress(address, &local_address_)) { |
259 // Always expect correct IPv4 address to be allocated. | 258 // Always expect correct IPv4 address to be allocated. |
260 NOTREACHED(); | 259 NOTREACHED(); |
261 OnError(); | 260 OnError(); |
262 return; | 261 return; |
263 } | 262 } |
264 SignalAddressReady(this, local_address_); | 263 SignalAddressReady(this, local_address_); |
265 address_initialized_ = true; | 264 if (type_ == P2P_SOCKET_TCP_CLIENT) |
266 state_ = STATE_OPEN; | 265 SignalConnect(this); |
| 266 state_ = IS_OPEN; |
267 } | 267 } |
268 | 268 |
269 void IpcPacketSocket::OnIncomingTcpConnection( | 269 void IpcPacketSocket::OnIncomingTcpConnection( |
270 const net::IPEndPoint& address, | 270 const net::IPEndPoint& address, |
271 P2PSocketClient* client) { | 271 P2PSocketClient* client) { |
272 DCHECK_EQ(MessageLoop::current(), message_loop_); | 272 DCHECK_EQ(MessageLoop::current(), message_loop_); |
273 | 273 |
274 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); | 274 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); |
275 | 275 |
276 talk_base::SocketAddress remote_address; | 276 talk_base::SocketAddress remote_address; |
277 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) { | 277 if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) { |
278 // Always expect correct IPv4 address to be allocated. | 278 // Always expect correct IPv4 address to be allocated. |
279 NOTREACHED(); | 279 NOTREACHED(); |
280 } | 280 } |
281 socket->InitAcceptedTcp(client, local_address_, remote_address); | 281 socket->InitAcceptedTcp(client, local_address_, remote_address); |
282 SignalNewConnection(this, socket.release()); | 282 SignalNewConnection(this, socket.release()); |
283 } | 283 } |
284 | 284 |
285 void IpcPacketSocket::OnError() { | 285 void IpcPacketSocket::OnError() { |
286 DCHECK_EQ(MessageLoop::current(), message_loop_); | 286 DCHECK_EQ(MessageLoop::current(), message_loop_); |
287 state_ = STATE_ERROR; | 287 state_ = IS_ERROR; |
288 error_ = ECONNABORTED; | 288 error_ = ECONNABORTED; |
289 } | 289 } |
290 | 290 |
291 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, | 291 void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, |
292 const std::vector<char>& data) { | 292 const std::vector<char>& data) { |
293 DCHECK_EQ(MessageLoop::current(), message_loop_); | 293 DCHECK_EQ(MessageLoop::current(), message_loop_); |
294 | 294 |
295 talk_base::SocketAddress address_lj; | 295 talk_base::SocketAddress address_lj; |
296 if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) { | 296 if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) { |
297 // We should always be able to convert address here because we | 297 // We should always be able to convert address here because we |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 return NULL; | 354 return NULL; |
355 | 355 |
356 talk_base::SocketAddress crome_address; | 356 talk_base::SocketAddress crome_address; |
357 P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); | 357 P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); |
358 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); | 358 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); |
359 if (!socket->Init(P2P_SOCKET_TCP_CLIENT, socket_client, local_address, | 359 if (!socket->Init(P2P_SOCKET_TCP_CLIENT, socket_client, local_address, |
360 remote_address)) | 360 remote_address)) |
361 return NULL; | 361 return NULL; |
362 return socket.release(); | 362 return socket.release(); |
363 } | 363 } |
OLD | NEW |