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

Side by Side Diff: remoting/jingle_glue/ssl_socket_adapter.cc

Issue 3136030: Unforked xmpp ssl adapter code. (Closed)
Patch Set: - Created 10 years, 4 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
« no previous file with comments | « remoting/jingle_glue/ssl_socket_adapter.h ('k') | remoting/jingle_glue/xmpp_socket_adapter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "remoting/jingle_glue/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 remoting {
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 read_callback_(this, &SSLSocketAdapter::OnRead)),
67 ALLOW_THIS_IN_INITIALIZER_LIST(
68 write_callback_(this, &SSLSocketAdapter::OnWrite)),
69 ssl_state_(SSLSTATE_NONE),
70 read_state_(IOSTATE_NONE),
71 write_state_(IOSTATE_NONE) {
72 transport_socket_ = new TransportSocket(socket, this);
73 }
74
75 int SSLSocketAdapter::StartSSL(const char* hostname, bool restartable) {
76 DCHECK(!restartable);
77 hostname_ = hostname;
78
79 if (socket_->GetState() != Socket::CS_CONNECTED) {
80 ssl_state_ = SSLSTATE_WAIT;
81 return 0;
82 } else {
83 return BeginSSL();
84 }
85 }
86
87 int SSLSocketAdapter::BeginSSL() {
88 if (!MessageLoop::current()) {
89 // Certificate verification is done via the Chrome message loop.
90 // Without this check, if we don't have a chrome message loop the
91 // SSL connection just hangs silently.
92 LOG(DFATAL) << "Chrome message loop (needed by SSL certificate "
93 << "verification) does not exist";
94 return net::ERR_UNEXPECTED;
95 }
96
97 // SSLConfigService is not thread-safe, and the default values for SSLConfig
98 // are correct for us, so we don't use the config service to initialize this
99 // object.
100 net::SSLConfig ssl_config;
101 transport_socket_->set_addr(talk_base::SocketAddress(hostname_, 0));
102 ssl_socket_.reset(
103 net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
104 transport_socket_, hostname_.c_str(), ssl_config));
105
106 int result = ssl_socket_->Connect(&connected_callback_);
107
108 if (result == net::ERR_IO_PENDING || result == net::OK) {
109 return 0;
110 } else {
111 LOG(ERROR) << "Could not start SSL: " << net::ErrorToString(result);
112 return result;
113 }
114 }
115
116 int SSLSocketAdapter::Send(const void* buf, size_t len) {
117 if (ssl_state_ != SSLSTATE_CONNECTED) {
118 return AsyncSocketAdapter::Send(buf, len);
119 } else {
120 scoped_refptr<net::IOBuffer> transport_buf = new net::IOBuffer(len);
121 memcpy(transport_buf->data(), buf, len);
122
123 int result = ssl_socket_->Write(transport_buf, len, NULL);
124 if (result == net::ERR_IO_PENDING) {
125 SetError(EWOULDBLOCK);
126 }
127 transport_buf = NULL;
128 return result;
129 }
130 }
131
132 int SSLSocketAdapter::Recv(void* buf, size_t len) {
133 switch (ssl_state_) {
134 case SSLSTATE_NONE:
135 return AsyncSocketAdapter::Recv(buf, len);
136
137 case SSLSTATE_WAIT:
138 SetError(EWOULDBLOCK);
139 return -1;
140
141 case SSLSTATE_CONNECTED:
142 switch (read_state_) {
143 case IOSTATE_NONE: {
144 transport_buf_ = new net::IOBuffer(len);
145 int result = ssl_socket_->Read(transport_buf_, len, &read_callback_);
146 if (result >= 0) {
147 memcpy(buf, transport_buf_->data(), len);
148 }
149
150 if (result == net::ERR_IO_PENDING) {
151 read_state_ = IOSTATE_PENDING;
152 SetError(EWOULDBLOCK);
153 } else {
154 if (result < 0) {
155 SetError(result);
156 LOG(INFO) << "Socket error " << result;
157 }
158 transport_buf_ = NULL;
159 }
160 return result;
161 }
162 case IOSTATE_PENDING:
163 SetError(EWOULDBLOCK);
164 return -1;
165
166 case IOSTATE_COMPLETE:
167 memcpy(buf, transport_buf_->data(), len);
168 transport_buf_ = NULL;
169 read_state_ = IOSTATE_NONE;
170 return data_transferred_;
171 }
172 }
173
174 NOTREACHED();
175 return -1;
176 }
177
178 void SSLSocketAdapter::OnConnected(int result) {
179 if (result == net::OK) {
180 ssl_state_ = SSLSTATE_CONNECTED;
181 OnConnectEvent(this);
182 } else {
183 LOG(WARNING) << "OnConnected failed with error " << result;
184 }
185 }
186
187 void SSLSocketAdapter::OnRead(int result) {
188 DCHECK(read_state_ == IOSTATE_PENDING);
189 read_state_ = IOSTATE_COMPLETE;
190 data_transferred_ = result;
191 AsyncSocketAdapter::OnReadEvent(this);
192 }
193
194 void SSLSocketAdapter::OnWrite(int result) {
195 DCHECK(write_state_ == IOSTATE_PENDING);
196 write_state_ = IOSTATE_COMPLETE;
197 data_transferred_ = result;
198 AsyncSocketAdapter::OnWriteEvent(this);
199 }
200
201 void SSLSocketAdapter::OnConnectEvent(talk_base::AsyncSocket* socket) {
202 if (ssl_state_ != SSLSTATE_WAIT) {
203 AsyncSocketAdapter::OnConnectEvent(socket);
204 } else {
205 ssl_state_ = SSLSTATE_NONE;
206 int result = BeginSSL();
207 if (0 != result) {
208 // TODO(zork): Handle this case gracefully.
209 LOG(WARNING) << "BeginSSL() failed with " << result;
210 }
211 }
212 }
213
214 TransportSocket::TransportSocket(talk_base::AsyncSocket* socket,
215 SSLSocketAdapter *ssl_adapter)
216 : read_callback_(NULL),
217 write_callback_(NULL),
218 read_buffer_len_(0),
219 write_buffer_len_(0),
220 socket_(socket) {
221 socket_->SignalReadEvent.connect(this, &TransportSocket::OnReadEvent);
222 socket_->SignalWriteEvent.connect(this, &TransportSocket::OnWriteEvent);
223 }
224
225 int TransportSocket::Connect(net::CompletionCallback* callback) {
226 // Connect is never called by SSLClientSocket, instead SSLSocketAdapter
227 // calls Connect() on socket_ directly.
228 NOTREACHED();
229 return false;
230 }
231
232 void TransportSocket::Disconnect() {
233 socket_->Close();
234 }
235
236 bool TransportSocket::IsConnected() const {
237 return (socket_->GetState() == talk_base::Socket::CS_CONNECTED);
238 }
239
240 bool TransportSocket::IsConnectedAndIdle() const {
241 // Not implemented.
242 NOTREACHED();
243 return false;
244 }
245
246 int TransportSocket::GetPeerAddress(net::AddressList* address) const {
247 talk_base::SocketAddress socket_address = socket_->GetRemoteAddress();
248
249 // libjingle supports only IPv4 addresses.
250 sockaddr_in ipv4addr;
251 socket_address.ToSockAddr(&ipv4addr);
252
253 struct addrinfo ai;
254 memset(&ai, 0, sizeof(ai));
255 ai.ai_family = ipv4addr.sin_family;
256 ai.ai_socktype = SOCK_STREAM;
257 ai.ai_protocol = IPPROTO_TCP;
258 ai.ai_addr = reinterpret_cast<struct sockaddr*>(&ipv4addr);
259 ai.ai_addrlen = sizeof(ipv4addr);
260
261 address->Copy(&ai, false);
262 return net::OK;
263 }
264
265 int TransportSocket::Read(net::IOBuffer* buf, int buf_len,
266 net::CompletionCallback* callback) {
267 DCHECK(buf);
268 DCHECK(!read_callback_);
269 DCHECK(!read_buffer_.get());
270 int result = socket_->Recv(buf->data(), buf_len);
271 if (result < 0) {
272 result = MapPosixError(socket_->GetError());
273 if (result == net::ERR_IO_PENDING) {
274 read_callback_ = callback;
275 read_buffer_ = buf;
276 read_buffer_len_ = buf_len;
277 }
278 }
279 return result;
280 }
281
282 int TransportSocket::Write(net::IOBuffer* buf, int buf_len,
283 net::CompletionCallback* callback) {
284 DCHECK(buf);
285 DCHECK(!write_callback_);
286 DCHECK(!write_buffer_.get());
287 int result = socket_->Send(buf->data(), buf_len);
288 if (result < 0) {
289 result = MapPosixError(socket_->GetError());
290 if (result == net::ERR_IO_PENDING) {
291 write_callback_ = callback;
292 write_buffer_ = buf;
293 write_buffer_len_ = buf_len;
294 }
295 }
296 return result;
297 }
298
299 bool TransportSocket::SetReceiveBufferSize(int32 size) {
300 // Not implemented.
301 return false;
302 }
303
304 bool TransportSocket::SetSendBufferSize(int32 size) {
305 // Not implemented.
306 return false;
307 }
308
309 void TransportSocket::OnReadEvent(talk_base::AsyncSocket* socket) {
310 if (read_callback_) {
311 DCHECK(read_buffer_.get());
312 net::CompletionCallback* callback = read_callback_;
313 scoped_refptr<net::IOBuffer> buffer = read_buffer_;
314 int buffer_len = read_buffer_len_;
315
316 read_callback_ = NULL;
317 read_buffer_ = NULL;
318 read_buffer_len_ = 0;
319
320 int result = socket_->Recv(buffer->data(), buffer_len);
321 if (result < 0) {
322 result = MapPosixError(socket_->GetError());
323 if (result == net::ERR_IO_PENDING) {
324 read_callback_ = callback;
325 read_buffer_ = buffer;
326 read_buffer_len_ = buffer_len;
327 return;
328 }
329 }
330 callback->RunWithParams(Tuple1<int>(result));
331 }
332 }
333
334 void TransportSocket::OnWriteEvent(talk_base::AsyncSocket* socket) {
335 if (write_callback_) {
336 DCHECK(write_buffer_.get());
337 net::CompletionCallback* callback = write_callback_;
338 scoped_refptr<net::IOBuffer> buffer = write_buffer_;
339 int buffer_len = write_buffer_len_;
340
341 write_callback_ = NULL;
342 write_buffer_ = NULL;
343 write_buffer_len_ = 0;
344
345 int result = socket_->Send(buffer->data(), buffer_len);
346 if (result < 0) {
347 result = MapPosixError(socket_->GetError());
348 if (result == net::ERR_IO_PENDING) {
349 write_callback_ = callback;
350 write_buffer_ = buffer;
351 write_buffer_len_ = buffer_len;
352 return;
353 }
354 }
355 callback->RunWithParams(Tuple1<int>(result));
356 }
357 }
358
359 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/jingle_glue/ssl_socket_adapter.h ('k') | remoting/jingle_glue/xmpp_socket_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698