Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1496)

Side by Side Diff: chrome/browser/sync/notifier/communicator/ssl_socket_adapter.cc

Issue 1956001: Moved XMPP notifier library from chrome/browser/sync to chrome/common.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 #include "chrome/browser/sync/notifier/communicator/ssl_socket_adapter.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/message_loop.h"
9 #include "net/base/address_list.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/ssl_config_service.h"
12 #include "net/base/sys_addrinfo.h"
13 #include "net/socket/client_socket_factory.h"
14 #include "net/url_request/url_request_context.h"
15
16 namespace notifier {
17
18 namespace {
19
20 // Convert values from <errno.h> to values from "net/base/net_errors.h"
21 int MapPosixError(int err) {
22 // There are numerous posix error codes, but these are the ones we thus far
23 // find interesting.
24 switch (err) {
25 case EAGAIN:
26 #if EWOULDBLOCK != EAGAIN
27 case EWOULDBLOCK:
28 #endif
29 return net::ERR_IO_PENDING;
30 case ENETDOWN:
31 return net::ERR_INTERNET_DISCONNECTED;
32 case ETIMEDOUT:
33 return net::ERR_TIMED_OUT;
34 case ECONNRESET:
35 case ENETRESET: // Related to keep-alive
36 return net::ERR_CONNECTION_RESET;
37 case ECONNABORTED:
38 return net::ERR_CONNECTION_ABORTED;
39 case ECONNREFUSED:
40 return net::ERR_CONNECTION_REFUSED;
41 case EHOSTUNREACH:
42 case ENETUNREACH:
43 return net::ERR_ADDRESS_UNREACHABLE;
44 case EADDRNOTAVAIL:
45 return net::ERR_ADDRESS_INVALID;
46 case 0:
47 return net::OK;
48 default:
49 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
50 return net::ERR_FAILED;
51 }
52 }
53
54 } // namespace
55
56 SSLSocketAdapter* SSLSocketAdapter::Create(AsyncSocket* socket) {
57 return new SSLSocketAdapter(socket);
58 }
59
60 SSLSocketAdapter::SSLSocketAdapter(AsyncSocket* socket)
61 : SSLAdapter(socket),
62 ignore_bad_cert_(false),
63 ALLOW_THIS_IN_INITIALIZER_LIST(
64 connected_callback_(this, &SSLSocketAdapter::OnConnected)),
65 ALLOW_THIS_IN_INITIALIZER_LIST(
66 io_callback_(this, &SSLSocketAdapter::OnIO)),
67 ssl_connected_(false),
68 state_(STATE_NONE) {
69 transport_socket_ = new TransportSocket(socket, this);
70 }
71
72 int SSLSocketAdapter::StartSSL(const char* hostname, bool restartable) {
73 DCHECK(!restartable);
74 hostname_ = hostname;
75
76 if (socket_->GetState() != Socket::CS_CONNECTED) {
77 state_ = STATE_SSL_WAIT;
78 return 0;
79 } else {
80 return BeginSSL();
81 }
82 }
83
84 int SSLSocketAdapter::BeginSSL() {
85 if (!MessageLoop::current()) {
86 // Certificate verification is done via the Chrome message loop.
87 // Without this check, if we don't have a chrome message loop the
88 // SSL connection just hangs silently.
89 LOG(DFATAL) << "Chrome message loop (needed by SSL certificate "
90 << "verification) does not exist";
91 return net::ERR_UNEXPECTED;
92 }
93
94 // SSLConfigService is not thread-safe, and the default values for SSLConfig
95 // are correct for us, so we don't use the config service to initialize this
96 // object.
97 net::SSLConfig ssl_config;
98 transport_socket_->set_addr(talk_base::SocketAddress(hostname_.c_str()));
99 ssl_socket_.reset(
100 net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
101 transport_socket_, hostname_.c_str(), ssl_config));
102
103 int result = ssl_socket_->Connect(&connected_callback_);
104
105 if (result == net::ERR_IO_PENDING || result == net::OK) {
106 return 0;
107 } else {
108 LOG(ERROR) << "Could not start SSL: " << net::ErrorToString(result);
109 return result;
110 }
111 }
112
113 int SSLSocketAdapter::Send(const void* buf, size_t len) {
114 if (!ssl_connected_) {
115 return AsyncSocketAdapter::Send(buf, len);
116 } else {
117 scoped_refptr<net::IOBuffer> transport_buf = new net::IOBuffer(len);
118 memcpy(transport_buf->data(), buf, len);
119
120 int result = ssl_socket_->Write(transport_buf, len, NULL);
121 if (result == net::ERR_IO_PENDING) {
122 SetError(EWOULDBLOCK);
123 }
124 transport_buf = NULL;
125 return result;
126 }
127 }
128
129 int SSLSocketAdapter::Recv(void* buf, size_t len) {
130 if (!ssl_connected_) {
131 return AsyncSocketAdapter::Recv(buf, len);
132 }
133
134 switch (state_) {
135 case STATE_NONE: {
136 transport_buf_ = new net::IOBuffer(len);
137 int result = ssl_socket_->Read(transport_buf_, len, &io_callback_);
138 if (result >= 0) {
139 memcpy(buf, transport_buf_->data(), len);
140 }
141
142 if (result == net::ERR_IO_PENDING) {
143 state_ = STATE_READ;
144 SetError(EWOULDBLOCK);
145 } else {
146 if (result < 0) {
147 SetError(result);
148 LOG(INFO) << "Socket error " << result;
149 }
150 transport_buf_ = NULL;
151 }
152 return result;
153 }
154 case STATE_READ_COMPLETE:
155 memcpy(buf, transport_buf_->data(), len);
156 transport_buf_ = NULL;
157 state_ = STATE_NONE;
158 return data_transferred_;
159
160 case STATE_READ:
161 case STATE_WRITE:
162 case STATE_WRITE_COMPLETE:
163 case STATE_SSL_WAIT:
164 SetError(EWOULDBLOCK);
165 return -1;
166
167 default:
168 NOTREACHED();
169 break;
170 }
171 return -1;
172 }
173
174 void SSLSocketAdapter::OnConnected(int result) {
175 if (result == net::OK) {
176 ssl_connected_ = true;
177 OnConnectEvent(this);
178 } else {
179 LOG(WARNING) << "OnConnected failed with error " << result;
180 }
181 }
182
183 void SSLSocketAdapter::OnIO(int result) {
184 switch (state_) {
185 case STATE_READ:
186 state_ = STATE_READ_COMPLETE;
187 data_transferred_ = result;
188 AsyncSocketAdapter::OnReadEvent(this);
189 break;
190 case STATE_WRITE:
191 state_ = STATE_WRITE_COMPLETE;
192 data_transferred_ = result;
193 AsyncSocketAdapter::OnWriteEvent(this);
194 break;
195 case STATE_NONE:
196 case STATE_READ_COMPLETE:
197 case STATE_WRITE_COMPLETE:
198 case STATE_SSL_WAIT:
199 default:
200 NOTREACHED();
201 break;
202 }
203 }
204
205 void SSLSocketAdapter::OnReadEvent(talk_base::AsyncSocket* socket) {
206 if (!transport_socket_->OnReadEvent(socket))
207 AsyncSocketAdapter::OnReadEvent(socket);
208 }
209
210 void SSLSocketAdapter::OnWriteEvent(talk_base::AsyncSocket* socket) {
211 if (!transport_socket_->OnWriteEvent(socket))
212 AsyncSocketAdapter::OnWriteEvent(socket);
213 }
214
215 void SSLSocketAdapter::OnConnectEvent(talk_base::AsyncSocket* socket) {
216 if (state_ != STATE_SSL_WAIT) {
217 AsyncSocketAdapter::OnConnectEvent(socket);
218 } else {
219 state_ = STATE_NONE;
220 int result = BeginSSL();
221 if (0 != result) {
222 // TODO(zork): Handle this case gracefully.
223 LOG(WARNING) << "BeginSSL() failed with " << result;
224 }
225 }
226 }
227
228 TransportSocket::TransportSocket(talk_base::AsyncSocket* socket,
229 SSLSocketAdapter *ssl_adapter)
230 : connect_callback_(NULL),
231 read_callback_(NULL),
232 write_callback_(NULL),
233 read_buffer_len_(0),
234 write_buffer_len_(0),
235 socket_(socket) {
236 socket_->SignalConnectEvent.connect(this, &TransportSocket::OnConnectEvent);
237 }
238
239 int TransportSocket::Connect(net::CompletionCallback* callback) {
240 connect_callback_ = callback;
241 return socket_->Connect(addr_);
242 }
243
244 void TransportSocket::Disconnect() {
245 socket_->Close();
246 }
247
248 bool TransportSocket::IsConnected() const {
249 return (socket_->GetState() == talk_base::Socket::CS_CONNECTED);
250 }
251
252 bool TransportSocket::IsConnectedAndIdle() const {
253 // Not implemented.
254 NOTREACHED();
255 return false;
256 }
257
258 int TransportSocket::GetPeerAddress(net::AddressList* address) const {
259 talk_base::SocketAddress socket_address = socket_->GetRemoteAddress();
260
261 // libjingle supports only IPv4 addresses.
262 sockaddr_in ipv4addr;
263 socket_address.ToSockAddr(&ipv4addr);
264
265 struct addrinfo ai;
266 memset(&ai, 0, sizeof(ai));
267 ai.ai_family = ipv4addr.sin_family;
268 ai.ai_socktype = SOCK_STREAM;
269 ai.ai_protocol = IPPROTO_TCP;
270 ai.ai_addr = reinterpret_cast<struct sockaddr*>(&ipv4addr);
271 ai.ai_addrlen = sizeof(ipv4addr);
272
273 address->Copy(&ai, false);
274 return net::OK;
275 }
276
277 int TransportSocket::Read(net::IOBuffer* buf, int buf_len,
278 net::CompletionCallback* callback) {
279 DCHECK(buf);
280 DCHECK(!read_callback_);
281 DCHECK(!read_buffer_.get());
282 int result = socket_->Recv(buf->data(), buf_len);
283 if (result < 0) {
284 result = MapPosixError(socket_->GetError());
285 if (result == net::ERR_IO_PENDING) {
286 read_callback_ = callback;
287 read_buffer_ = buf;
288 read_buffer_len_ = buf_len;
289 }
290 }
291 return result;
292 }
293
294 int TransportSocket::Write(net::IOBuffer* buf, int buf_len,
295 net::CompletionCallback* callback) {
296 DCHECK(buf);
297 DCHECK(!write_callback_);
298 DCHECK(!write_buffer_.get());
299 int result = socket_->Send(buf->data(), buf_len);
300 if (result < 0) {
301 result = MapPosixError(socket_->GetError());
302 if (result == net::ERR_IO_PENDING) {
303 write_callback_ = callback;
304 write_buffer_ = buf;
305 write_buffer_len_ = buf_len;
306 }
307 }
308 return result;
309 }
310
311 bool TransportSocket::SetReceiveBufferSize(int32 size) {
312 // Not implemented.
313 return false;
314 }
315
316 bool TransportSocket::SetSendBufferSize(int32 size) {
317 // Not implemented.
318 return false;
319 }
320
321 void TransportSocket::OnConnectEvent(talk_base::AsyncSocket * socket) {
322 if (connect_callback_) {
323 net::CompletionCallback *callback = connect_callback_;
324 connect_callback_ = NULL;
325 callback->RunWithParams(Tuple1<int>(MapPosixError(socket_->GetError())));
326 } else {
327 LOG(WARNING) << "OnConnectEvent called with no callback.";
328 }
329 }
330
331 bool TransportSocket::OnReadEvent(talk_base::AsyncSocket* socket) {
332 if (read_callback_) {
333 DCHECK(read_buffer_.get());
334 net::CompletionCallback* callback = read_callback_;
335 scoped_refptr<net::IOBuffer> buffer = read_buffer_;
336 int buffer_len = read_buffer_len_;
337
338 read_callback_ = NULL;
339 read_buffer_ = NULL;
340 read_buffer_len_ = 0;
341
342 int result = socket_->Recv(buffer->data(), buffer_len);
343 if (result < 0) {
344 result = MapPosixError(socket_->GetError());
345 if (result == net::ERR_IO_PENDING) {
346 read_callback_ = callback;
347 read_buffer_ = buffer;
348 read_buffer_len_ = buffer_len;
349 return true;
350 }
351 }
352 callback->RunWithParams(Tuple1<int>(result));
353 return true;
354 } else {
355 LOG(WARNING) << "OnReadEvent called with no callback.";
356 return false;
357 }
358 }
359
360 bool TransportSocket::OnWriteEvent(talk_base::AsyncSocket* socket) {
361 if (write_callback_) {
362 DCHECK(write_buffer_.get());
363 net::CompletionCallback* callback = write_callback_;
364 scoped_refptr<net::IOBuffer> buffer = write_buffer_;
365 int buffer_len = write_buffer_len_;
366
367 write_callback_ = NULL;
368 write_buffer_ = NULL;
369 write_buffer_len_ = 0;
370
371 int result = socket_->Send(buffer->data(), buffer_len);
372 if (result < 0) {
373 result = MapPosixError(socket_->GetError());
374 if (result == net::ERR_IO_PENDING) {
375 write_callback_ = callback;
376 write_buffer_ = buffer;
377 write_buffer_len_ = buffer_len;
378 return true;
379 }
380 }
381 callback->RunWithParams(Tuple1<int>(result));
382 return true;
383 } else {
384 LOG(WARNING) << "OnWriteEvent called with no callback.";
385 return false;
386 }
387 }
388
389 } // namespace notifier
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698