1// Copyright (c) 2012 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 "content/browser/renderer_host/pepper/pepper_tcp_socket.h"
6
7#include <string.h>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/compiler_specific.h"
12#include "base/logging.h"
13#include "base/strings/string_util.h"
14#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
15#include "content/public/browser/browser_thread.h"
16#include "net/base/host_port_pair.h"
17#include "net/base/io_buffer.h"
18#include "net/base/ip_endpoint.h"
19#include "net/base/net_errors.h"
20#include "net/cert/cert_verifier.h"
21#include "net/cert/x509_certificate.h"
22#include "net/dns/host_resolver.h"
23#include "net/dns/single_request_host_resolver.h"
24#include "net/socket/client_socket_factory.h"
25#include "net/socket/client_socket_handle.h"
26#include "net/socket/ssl_client_socket.h"
27#include "net/socket/tcp_client_socket.h"
28#include "ppapi/host/error_conversion.h"
29#include "ppapi/proxy/ppapi_messages.h"
30#include "ppapi/shared_impl/private/net_address_private_impl.h"
31#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
32#include "ppapi/shared_impl/socket_option_data.h"
33#include "ppapi/shared_impl/tcp_socket_shared.h"
34
35using ppapi::host::NetErrorToPepperError;
36using ppapi::NetAddressPrivateImpl;
37
38namespace content {
39
40PepperTCPSocket::PepperTCPSocket(PepperMessageFilter* manager,
41                                 int32 routing_id,
42                                 uint32 plugin_dispatcher_id,
43                                 uint32 socket_id,
44                                 bool private_api)
45    : manager_(manager),
46      routing_id_(routing_id),
47      plugin_dispatcher_id_(plugin_dispatcher_id),
48      socket_id_(socket_id),
49      private_api_(private_api),
50      connection_state_(BEFORE_CONNECT),
51      end_of_file_reached_(false) {
52  DCHECK(manager);
53}
54
55PepperTCPSocket::PepperTCPSocket(PepperMessageFilter* manager,
56                                 int32 routing_id,
57                                 uint32 plugin_dispatcher_id,
58                                 uint32 socket_id,
59                                 net::StreamSocket* socket,
60                                 bool private_api)
61    : manager_(manager),
62      routing_id_(routing_id),
63      plugin_dispatcher_id_(plugin_dispatcher_id),
64      socket_id_(socket_id),
65      private_api_(private_api),
66      connection_state_(CONNECTED),
67      end_of_file_reached_(false),
68      socket_(socket) {
69  DCHECK(manager);
70}
71
72PepperTCPSocket::~PepperTCPSocket() {
73  // Make sure no further callbacks from socket_.
74  if (socket_)
75    socket_->Disconnect();
76}
77
78void PepperTCPSocket::Connect(const std::string& host, uint16_t port) {
79  DCHECK_CURRENTLY_ON(BrowserThread::IO);
80
81  if (connection_state_ != BEFORE_CONNECT) {
82    SendConnectACKError(PP_ERROR_FAILED);
83    return;
84  }
85
86  connection_state_ = CONNECT_IN_PROGRESS;
87  net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
88  resolver_.reset(
89      new net::SingleRequestHostResolver(manager_->GetHostResolver()));
90  int net_result = resolver_->Resolve(
91      request_info,
92      net::DEFAULT_PRIORITY,
93      &address_list_,
94      base::Bind(&PepperTCPSocket::OnResolveCompleted, base::Unretained(this)),
95      net::BoundNetLog());
96  if (net_result != net::ERR_IO_PENDING)
97    OnResolveCompleted(net_result);
98}
99
100void PepperTCPSocket::ConnectWithNetAddress(
101    const PP_NetAddress_Private& net_addr) {
102  DCHECK_CURRENTLY_ON(BrowserThread::IO);
103
104  if (connection_state_ != BEFORE_CONNECT) {
105    SendConnectACKError(PP_ERROR_FAILED);
106    return;
107  }
108
109  net::IPAddressNumber address;
110  int port;
111  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
112          net_addr, &address, &port)) {
113    SendConnectACKError(PP_ERROR_ADDRESS_INVALID);
114    return;
115  }
116
117  // Copy the single IPEndPoint to address_list_.
118  address_list_.clear();
119  address_list_.push_back(net::IPEndPoint(address, port));
120  connection_state_ = CONNECT_IN_PROGRESS;
121  StartConnect(address_list_);
122}
123
124void PepperTCPSocket::SSLHandshake(
125    const std::string& server_name,
126    uint16_t server_port,
127    const std::vector<std::vector<char> >& trusted_certs,
128    const std::vector<std::vector<char> >& untrusted_certs) {
129  DCHECK_CURRENTLY_ON(BrowserThread::IO);
130
131  // Allow to do SSL handshake only if currently the socket has been connected
132  // and there isn't pending read or write.
133  // IsConnected() includes the state that SSL handshake has been finished and
134  // therefore isn't suitable here.
135  if (connection_state_ != CONNECTED || read_buffer_.get() ||
136      write_buffer_base_.get() || write_buffer_.get()) {
137    SendSSLHandshakeACK(false);
138    return;
139  }
140
141  connection_state_ = SSL_HANDSHAKE_IN_PROGRESS;
142  // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
143
144  scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
145  handle->SetSocket(socket_.Pass());
146  net::ClientSocketFactory* factory =
147      net::ClientSocketFactory::GetDefaultFactory();
148  net::HostPortPair host_port_pair(server_name, server_port);
149  net::SSLClientSocketContext ssl_context;
150  ssl_context.cert_verifier = manager_->GetCertVerifier();
151  ssl_context.transport_security_state = manager_->GetTransportSecurityState();
152  socket_ = factory->CreateSSLClientSocket(
153      handle.Pass(), host_port_pair, manager_->ssl_config(), ssl_context);
154  if (!socket_) {
155    LOG(WARNING) << "Failed to create an SSL client socket.";
156    OnSSLHandshakeCompleted(net::ERR_UNEXPECTED);
157    return;
158  }
159
160  int net_result = socket_->Connect(base::Bind(
161      &PepperTCPSocket::OnSSLHandshakeCompleted, base::Unretained(this)));
162  if (net_result != net::ERR_IO_PENDING)
163    OnSSLHandshakeCompleted(net_result);
164}
165
166void PepperTCPSocket::Read(int32 bytes_to_read) {
167  DCHECK_CURRENTLY_ON(BrowserThread::IO);
168
169  if (!IsConnected() || end_of_file_reached_) {
170    SendReadACKError(PP_ERROR_FAILED);
171    return;
172  }
173
174  if (read_buffer_.get()) {
175    SendReadACKError(PP_ERROR_INPROGRESS);
176    return;
177  }
178
179  if (bytes_to_read <= 0 ||
180      bytes_to_read > ppapi::TCPSocketShared::kMaxReadSize) {
181    SendReadACKError(PP_ERROR_BADARGUMENT);
182    return;
183  }
184
185  read_buffer_ = new net::IOBuffer(bytes_to_read);
186  int net_result = socket_->Read(
187      read_buffer_.get(),
188      bytes_to_read,
189      base::Bind(&PepperTCPSocket::OnReadCompleted, base::Unretained(this)));
190  if (net_result != net::ERR_IO_PENDING)
191    OnReadCompleted(net_result);
192}
193
194void PepperTCPSocket::Write(const std::string& data) {
195  DCHECK_CURRENTLY_ON(BrowserThread::IO);
196
197  if (!IsConnected()) {
198    SendWriteACKError(PP_ERROR_FAILED);
199    return;
200  }
201
202  if (write_buffer_base_.get() || write_buffer_.get()) {
203    SendWriteACKError(PP_ERROR_INPROGRESS);
204    return;
205  }
206
207  size_t data_size = data.size();
208  if (data_size == 0 ||
209      data_size > static_cast<size_t>(ppapi::TCPSocketShared::kMaxWriteSize)) {
210    SendWriteACKError(PP_ERROR_BADARGUMENT);
211    return;
212  }
213
214  write_buffer_base_ = new net::IOBuffer(data_size);
215  memcpy(write_buffer_base_->data(), data.data(), data_size);
216  write_buffer_ =
217      new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
218  DoWrite();
219}
220
221void PepperTCPSocket::SetOption(PP_TCPSocket_Option name,
222                                const ppapi::SocketOptionData& value) {
223  DCHECK_CURRENTLY_ON(BrowserThread::IO);
224
225  if (!IsConnected() || IsSsl()) {
226    SendSetOptionACK(PP_ERROR_FAILED);
227    return;
228  }
229
230  net::TCPClientSocket* tcp_socket =
231      static_cast<net::TCPClientSocket*>(socket_.get());
232  DCHECK(tcp_socket);
233
234  switch (name) {
235    case PP_TCPSOCKET_OPTION_NO_DELAY: {
236      bool boolean_value = false;
237      if (!value.GetBool(&boolean_value)) {
238        SendSetOptionACK(PP_ERROR_BADARGUMENT);
239        return;
240      }
241
242      SendSetOptionACK(tcp_socket->SetNoDelay(boolean_value) ? PP_OK
243                                                             : PP_ERROR_FAILED);
244      return;
245    }
246    case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
247    case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
248      int32_t integer_value = 0;
249      if (!value.GetInt32(&integer_value) || integer_value <= 0) {
250        SendSetOptionACK(PP_ERROR_BADARGUMENT);
251        return;
252      }
253
254      int net_result = net::OK;
255      if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
256        if (integer_value > ppapi::TCPSocketShared::kMaxSendBufferSize) {
257          SendSetOptionACK(PP_ERROR_BADARGUMENT);
258          return;
259        }
260        net_result = tcp_socket->SetSendBufferSize(integer_value);
261      } else {
262        if (integer_value > ppapi::TCPSocketShared::kMaxReceiveBufferSize) {
263          SendSetOptionACK(PP_ERROR_BADARGUMENT);
264          return;
265        }
266        net_result = tcp_socket->SetReceiveBufferSize(integer_value);
267      }
268      // TODO(wtc): Add error mapping.
269      SendSetOptionACK((net_result == net::OK) ? PP_OK : PP_ERROR_FAILED);
270      return;
271    }
272    default: {
273      NOTREACHED();
274      SendSetOptionACK(PP_ERROR_BADARGUMENT);
275      return;
276    }
277  }
278}
279
280void PepperTCPSocket::StartConnect(const net::AddressList& addresses) {
281  DCHECK(connection_state_ == CONNECT_IN_PROGRESS);
282
283  socket_.reset(
284      new net::TCPClientSocket(addresses, NULL, net::NetLog::Source()));
285  int net_result = socket_->Connect(
286      base::Bind(&PepperTCPSocket::OnConnectCompleted, base::Unretained(this)));
287  if (net_result != net::ERR_IO_PENDING)
288    OnConnectCompleted(net_result);
289}
290
291void PepperTCPSocket::SendConnectACKError(int32_t error) {
292  manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK(
293      routing_id_,
294      plugin_dispatcher_id_,
295      socket_id_,
296      error,
297      NetAddressPrivateImpl::kInvalidNetAddress,
298      NetAddressPrivateImpl::kInvalidNetAddress));
299}
300
301// static
302bool PepperTCPSocket::GetCertificateFields(
303    const net::X509Certificate& cert,
304    ppapi::PPB_X509Certificate_Fields* fields) {
305  const net::CertPrincipal& issuer = cert.issuer();
306  fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COMMON_NAME,
307                   new base::StringValue(issuer.common_name));
308  fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_LOCALITY_NAME,
309                   new base::StringValue(issuer.locality_name));
310  fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
311                   new base::StringValue(issuer.state_or_province_name));
312  fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
313                   new base::StringValue(issuer.country_name));
314  fields->SetField(
315      PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
316      new base::StringValue(JoinString(issuer.organization_names, '\n')));
317  fields->SetField(
318      PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
319      new base::StringValue(JoinString(issuer.organization_unit_names, '\n')));
320
321  const net::CertPrincipal& subject = cert.subject();
322  fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COMMON_NAME,
323                   new base::StringValue(subject.common_name));
324  fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_LOCALITY_NAME,
325                   new base::StringValue(subject.locality_name));
326  fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
327                   new base::StringValue(subject.state_or_province_name));
328  fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
329                   new base::StringValue(subject.country_name));
330  fields->SetField(
331      PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
332      new base::StringValue(JoinString(subject.organization_names, '\n')));
333  fields->SetField(
334      PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
335      new base::StringValue(JoinString(subject.organization_unit_names, '\n')));
336
337  const std::string& serial_number = cert.serial_number();
338  fields->SetField(PP_X509CERTIFICATE_PRIVATE_SERIAL_NUMBER,
339                   base::BinaryValue::CreateWithCopiedBuffer(
340                       serial_number.data(), serial_number.length()));
341  fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
342                   new base::FundamentalValue(cert.valid_start().ToDoubleT()));
343  fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_AFTER,
344                   new base::FundamentalValue(cert.valid_expiry().ToDoubleT()));
345  std::string der;
346  net::X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der);
347  fields->SetField(
348      PP_X509CERTIFICATE_PRIVATE_RAW,
349      base::BinaryValue::CreateWithCopiedBuffer(der.data(), der.length()));
350  return true;
351}
352
353// static
354bool PepperTCPSocket::GetCertificateFields(
355    const char* der,
356    uint32_t length,
357    ppapi::PPB_X509Certificate_Fields* fields) {
358  scoped_refptr<net::X509Certificate> cert =
359      net::X509Certificate::CreateFromBytes(der, length);
360  if (!cert.get())
361    return false;
362  return GetCertificateFields(*cert.get(), fields);
363}
364
365void PepperTCPSocket::SendReadACKError(int32_t error) {
366  manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK(
367      routing_id_, plugin_dispatcher_id_, socket_id_, error, std::string()));
368}
369
370void PepperTCPSocket::SendWriteACKError(int32_t error) {
371  DCHECK_GT(0, error);
372  manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK(
373      routing_id_, plugin_dispatcher_id_, socket_id_, error));
374}
375
376void PepperTCPSocket::SendSSLHandshakeACK(bool succeeded) {
377  ppapi::PPB_X509Certificate_Fields certificate_fields;
378  if (succeeded) {
379    // Our socket is guaranteed to be an SSL socket if we get here.
380    net::SSLClientSocket* ssl_socket =
381        static_cast<net::SSLClientSocket*>(socket_.get());
382    net::SSLInfo ssl_info;
383    ssl_socket->GetSSLInfo(&ssl_info);
384    if (ssl_info.cert.get())
385      GetCertificateFields(*ssl_info.cert.get(), &certificate_fields);
386  }
387  manager_->Send(
388      new PpapiMsg_PPBTCPSocket_SSLHandshakeACK(routing_id_,
389                                                plugin_dispatcher_id_,
390                                                socket_id_,
391                                                succeeded,
392                                                certificate_fields));
393}
394
395void PepperTCPSocket::SendSetOptionACK(int32_t result) {
396  manager_->Send(new PpapiMsg_PPBTCPSocket_SetOptionACK(
397      routing_id_, plugin_dispatcher_id_, socket_id_, result));
398}
399
400void PepperTCPSocket::OnResolveCompleted(int net_result) {
401  DCHECK(connection_state_ == CONNECT_IN_PROGRESS);
402
403  if (net_result != net::OK) {
404    SendConnectACKError(NetErrorToPepperError(net_result));
405    connection_state_ = BEFORE_CONNECT;
406    return;
407  }
408
409  StartConnect(address_list_);
410}
411
412void PepperTCPSocket::OnConnectCompleted(int net_result) {
413  DCHECK(connection_state_ == CONNECT_IN_PROGRESS && socket_.get());
414
415  int32_t pp_result = NetErrorToPepperError(net_result);
416  do {
417    if (pp_result != PP_OK)
418      break;
419
420    net::IPEndPoint ip_end_point_local;
421    net::IPEndPoint ip_end_point_remote;
422    pp_result =
423        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
424    if (pp_result != PP_OK)
425      break;
426    pp_result =
427        NetErrorToPepperError(socket_->GetPeerAddress(&ip_end_point_remote));
428    if (pp_result != PP_OK)
429      break;
430
431    PP_NetAddress_Private local_addr =
432        NetAddressPrivateImpl::kInvalidNetAddress;
433    PP_NetAddress_Private remote_addr =
434        NetAddressPrivateImpl::kInvalidNetAddress;
435    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
436            ip_end_point_local.address(),
437            ip_end_point_local.port(),
438            &local_addr) ||
439        !NetAddressPrivateImpl::IPEndPointToNetAddress(
440            ip_end_point_remote.address(),
441            ip_end_point_remote.port(),
442            &remote_addr)) {
443      pp_result = PP_ERROR_ADDRESS_INVALID;
444      break;
445    }
446
447    manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK(routing_id_,
448                                                        plugin_dispatcher_id_,
449                                                        socket_id_,
450                                                        PP_OK,
451                                                        local_addr,
452                                                        remote_addr));
453    connection_state_ = CONNECTED;
454    return;
455  } while (false);
456
457  SendConnectACKError(pp_result);
458  connection_state_ = BEFORE_CONNECT;
459}
460
461void PepperTCPSocket::OnSSLHandshakeCompleted(int net_result) {
462  DCHECK(connection_state_ == SSL_HANDSHAKE_IN_PROGRESS);
463
464  bool succeeded = net_result == net::OK;
465  SendSSLHandshakeACK(succeeded);
466  connection_state_ = succeeded ? SSL_CONNECTED : SSL_HANDSHAKE_FAILED;
467}
468
469void PepperTCPSocket::OnReadCompleted(int net_result) {
470  DCHECK(read_buffer_.get());
471
472  if (net_result > 0) {
473    manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK(
474        routing_id_,
475        plugin_dispatcher_id_,
476        socket_id_,
477        PP_OK,
478        std::string(read_buffer_->data(), net_result)));
479  } else if (net_result == 0) {
480    end_of_file_reached_ = true;
481    manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK(
482        routing_id_, plugin_dispatcher_id_, socket_id_, PP_OK, std::string()));
483  } else {
484    SendReadACKError(NetErrorToPepperError(net_result));
485  }
486  read_buffer_ = NULL;
487}
488
489void PepperTCPSocket::OnWriteCompleted(int net_result) {
490  DCHECK(write_buffer_base_.get());
491  DCHECK(write_buffer_.get());
492
493  // Note: For partial writes of 0 bytes, don't continue writing to avoid a
494  // likely infinite loop.
495  if (net_result > 0) {
496    write_buffer_->DidConsume(net_result);
497    if (write_buffer_->BytesRemaining() > 0) {
498      DoWrite();
499      return;
500    }
501  }
502
503  if (net_result >= 0) {
504    manager_->Send(
505        new PpapiMsg_PPBTCPSocket_WriteACK(routing_id_,
506                                           plugin_dispatcher_id_,
507                                           socket_id_,
508                                           write_buffer_->BytesConsumed()));
509  } else {
510    SendWriteACKError(NetErrorToPepperError(net_result));
511  }
512
513  write_buffer_ = NULL;
514  write_buffer_base_ = NULL;
515}
516
517bool PepperTCPSocket::IsConnected() const {
518  return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
519}
520
521bool PepperTCPSocket::IsSsl() const {
522  return connection_state_ == SSL_HANDSHAKE_IN_PROGRESS ||
523         connection_state_ == SSL_CONNECTED ||
524         connection_state_ == SSL_HANDSHAKE_FAILED;
525}
526
527void PepperTCPSocket::DoWrite() {
528  DCHECK(write_buffer_base_.get());
529  DCHECK(write_buffer_.get());
530  DCHECK_GT(write_buffer_->BytesRemaining(), 0);
531
532  int net_result = socket_->Write(
533      write_buffer_.get(),
534      write_buffer_->BytesRemaining(),
535      base::Bind(&PepperTCPSocket::OnWriteCompleted, base::Unretained(this)));
536  if (net_result != net::ERR_IO_PENDING)
537    OnWriteCompleted(net_result);
538}
539
540}  // namespace content
541