Home | History | Annotate | Download | only in pepper
      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 
     35 using ppapi::host::NetErrorToPepperError;
     36 using ppapi::NetAddressPrivateImpl;
     37 
     38 namespace content {
     39 
     40 PepperTCPSocket::PepperTCPSocket(
     41     PepperMessageFilter* manager,
     42     int32 routing_id,
     43     uint32 plugin_dispatcher_id,
     44     uint32 socket_id,
     45     bool private_api)
     46     : manager_(manager),
     47       routing_id_(routing_id),
     48       plugin_dispatcher_id_(plugin_dispatcher_id),
     49       socket_id_(socket_id),
     50       private_api_(private_api),
     51       connection_state_(BEFORE_CONNECT),
     52       end_of_file_reached_(false) {
     53   DCHECK(manager);
     54 }
     55 
     56 PepperTCPSocket::PepperTCPSocket(
     57     PepperMessageFilter* manager,
     58     int32 routing_id,
     59     uint32 plugin_dispatcher_id,
     60     uint32 socket_id,
     61     net::StreamSocket* socket,
     62     bool private_api)
     63     : manager_(manager),
     64       routing_id_(routing_id),
     65       plugin_dispatcher_id_(plugin_dispatcher_id),
     66       socket_id_(socket_id),
     67       private_api_(private_api),
     68       connection_state_(CONNECTED),
     69       end_of_file_reached_(false),
     70       socket_(socket) {
     71   DCHECK(manager);
     72 }
     73 
     74 PepperTCPSocket::~PepperTCPSocket() {
     75   // Make sure no further callbacks from socket_.
     76   if (socket_)
     77     socket_->Disconnect();
     78 }
     79 
     80 void PepperTCPSocket::Connect(const std::string& host, uint16_t port) {
     81   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     82 
     83   if (connection_state_ != BEFORE_CONNECT) {
     84     SendConnectACKError(PP_ERROR_FAILED);
     85     return;
     86   }
     87 
     88   connection_state_ = CONNECT_IN_PROGRESS;
     89   net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
     90   resolver_.reset(new net::SingleRequestHostResolver(
     91       manager_->GetHostResolver()));
     92   int net_result = resolver_->Resolve(
     93       request_info, &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 
    100 void PepperTCPSocket::ConnectWithNetAddress(
    101     const PP_NetAddress_Private& net_addr) {
    102   DCHECK(BrowserThread::CurrentlyOn(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(net_addr, &address,
    112                                                      &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 
    124 void 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(BrowserThread::CurrentlyOn(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   net::ClientSocketHandle* handle = new net::ClientSocketHandle();
    145   handle->set_socket(socket_.release());
    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_.reset(factory->CreateSSLClientSocket(
    153       handle, 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(
    161       base::Bind(&PepperTCPSocket::OnSSLHandshakeCompleted,
    162                  base::Unretained(this)));
    163   if (net_result != net::ERR_IO_PENDING)
    164     OnSSLHandshakeCompleted(net_result);
    165 }
    166 
    167 void PepperTCPSocket::Read(int32 bytes_to_read) {
    168   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    169 
    170   if (!IsConnected() || end_of_file_reached_) {
    171     SendReadACKError(PP_ERROR_FAILED);
    172     return;
    173   }
    174 
    175   if (read_buffer_.get()) {
    176     SendReadACKError(PP_ERROR_INPROGRESS);
    177     return;
    178   }
    179 
    180   if (bytes_to_read <= 0 ||
    181       bytes_to_read > ppapi::TCPSocketShared::kMaxReadSize) {
    182     SendReadACKError(PP_ERROR_BADARGUMENT);
    183     return;
    184   }
    185 
    186   read_buffer_ = new net::IOBuffer(bytes_to_read);
    187   int net_result = socket_->Read(
    188       read_buffer_.get(),
    189       bytes_to_read,
    190       base::Bind(&PepperTCPSocket::OnReadCompleted, base::Unretained(this)));
    191   if (net_result != net::ERR_IO_PENDING)
    192     OnReadCompleted(net_result);
    193 }
    194 
    195 void PepperTCPSocket::Write(const std::string& data) {
    196   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    197 
    198   if (!IsConnected()) {
    199     SendWriteACKError(PP_ERROR_FAILED);
    200     return;
    201   }
    202 
    203   if (write_buffer_base_.get() || write_buffer_.get()) {
    204     SendWriteACKError(PP_ERROR_INPROGRESS);
    205     return;
    206   }
    207 
    208   size_t data_size = data.size();
    209   if (data_size == 0 ||
    210       data_size > static_cast<size_t>(ppapi::TCPSocketShared::kMaxWriteSize)) {
    211     SendWriteACKError(PP_ERROR_BADARGUMENT);
    212     return;
    213   }
    214 
    215   write_buffer_base_ = new net::IOBuffer(data_size);
    216   memcpy(write_buffer_base_->data(), data.data(), data_size);
    217   write_buffer_ =
    218       new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
    219   DoWrite();
    220 }
    221 
    222 void PepperTCPSocket::SetOption(PP_TCPSocket_Option name,
    223                                 const ppapi::SocketOptionData& value) {
    224   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    225 
    226   if (!IsConnected() || IsSsl()) {
    227     SendSetOptionACK(PP_ERROR_FAILED);
    228     return;
    229   }
    230 
    231   net::TCPClientSocket* tcp_socket =
    232       static_cast<net::TCPClientSocket*>(socket_.get());
    233   DCHECK(tcp_socket);
    234 
    235   switch (name) {
    236     case PP_TCPSOCKET_OPTION_NO_DELAY: {
    237       bool boolean_value = false;
    238       if (!value.GetBool(&boolean_value)) {
    239         SendSetOptionACK(PP_ERROR_BADARGUMENT);
    240         return;
    241       }
    242 
    243       SendSetOptionACK(
    244           tcp_socket->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED);
    245       return;
    246     }
    247     case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
    248     case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
    249       int32_t integer_value = 0;
    250       if (!value.GetInt32(&integer_value) || integer_value <= 0) {
    251         SendSetOptionACK(PP_ERROR_BADARGUMENT);
    252         return;
    253       }
    254 
    255       bool result = false;
    256       if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
    257         if (integer_value > ppapi::TCPSocketShared::kMaxSendBufferSize) {
    258           SendSetOptionACK(PP_ERROR_BADARGUMENT);
    259           return;
    260         }
    261         result = tcp_socket->SetSendBufferSize(integer_value);
    262       } else {
    263         if (integer_value > ppapi::TCPSocketShared::kMaxReceiveBufferSize) {
    264           SendSetOptionACK(PP_ERROR_BADARGUMENT);
    265           return;
    266         }
    267         result = tcp_socket->SetReceiveBufferSize(integer_value);
    268       }
    269       SendSetOptionACK(result ? PP_OK : PP_ERROR_FAILED);
    270       return;
    271     }
    272     default: {
    273       NOTREACHED();
    274       SendSetOptionACK(PP_ERROR_BADARGUMENT);
    275       return;
    276     }
    277   }
    278 }
    279 
    280 void PepperTCPSocket::StartConnect(const net::AddressList& addresses) {
    281   DCHECK(connection_state_ == CONNECT_IN_PROGRESS);
    282 
    283   socket_.reset(new net::TCPClientSocket(addresses, NULL,
    284                                          net::NetLog::Source()));
    285   int net_result = socket_->Connect(
    286       base::Bind(&PepperTCPSocket::OnConnectCompleted,
    287                  base::Unretained(this)));
    288   if (net_result != net::ERR_IO_PENDING)
    289     OnConnectCompleted(net_result);
    290 }
    291 
    292 void PepperTCPSocket::SendConnectACKError(int32_t error) {
    293   manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK(
    294       routing_id_, plugin_dispatcher_id_, socket_id_, error,
    295       NetAddressPrivateImpl::kInvalidNetAddress,
    296       NetAddressPrivateImpl::kInvalidNetAddress));
    297 }
    298 
    299 // static
    300 bool PepperTCPSocket::GetCertificateFields(
    301     const net::X509Certificate& cert,
    302     ppapi::PPB_X509Certificate_Fields* fields) {
    303   const net::CertPrincipal& issuer = cert.issuer();
    304   fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COMMON_NAME,
    305       new base::StringValue(issuer.common_name));
    306   fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_LOCALITY_NAME,
    307       new base::StringValue(issuer.locality_name));
    308   fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_STATE_OR_PROVINCE_NAME,
    309       new base::StringValue(issuer.state_or_province_name));
    310   fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_COUNTRY_NAME,
    311       new base::StringValue(issuer.country_name));
    312   fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_NAME,
    313       new base::StringValue(JoinString(issuer.organization_names, '\n')));
    314   fields->SetField(PP_X509CERTIFICATE_PRIVATE_ISSUER_ORGANIZATION_UNIT_NAME,
    315       new base::StringValue(JoinString(issuer.organization_unit_names, '\n')));
    316 
    317   const net::CertPrincipal& subject = cert.subject();
    318   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COMMON_NAME,
    319       new base::StringValue(subject.common_name));
    320   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_LOCALITY_NAME,
    321       new base::StringValue(subject.locality_name));
    322   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_STATE_OR_PROVINCE_NAME,
    323       new base::StringValue(subject.state_or_province_name));
    324   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_COUNTRY_NAME,
    325       new base::StringValue(subject.country_name));
    326   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_NAME,
    327       new base::StringValue(JoinString(subject.organization_names, '\n')));
    328   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SUBJECT_ORGANIZATION_UNIT_NAME,
    329       new base::StringValue(JoinString(subject.organization_unit_names, '\n')));
    330 
    331   const std::string& serial_number = cert.serial_number();
    332   fields->SetField(PP_X509CERTIFICATE_PRIVATE_SERIAL_NUMBER,
    333       base::BinaryValue::CreateWithCopiedBuffer(serial_number.data(),
    334                                                 serial_number.length()));
    335   fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_BEFORE,
    336       new base::FundamentalValue(cert.valid_start().ToDoubleT()));
    337   fields->SetField(PP_X509CERTIFICATE_PRIVATE_VALIDITY_NOT_AFTER,
    338       new base::FundamentalValue(cert.valid_expiry().ToDoubleT()));
    339   std::string der;
    340   net::X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der);
    341   fields->SetField(PP_X509CERTIFICATE_PRIVATE_RAW,
    342       base::BinaryValue::CreateWithCopiedBuffer(der.data(), der.length()));
    343   return true;
    344 }
    345 
    346 // static
    347 bool PepperTCPSocket::GetCertificateFields(
    348     const char* der,
    349     uint32_t length,
    350     ppapi::PPB_X509Certificate_Fields* fields) {
    351   scoped_refptr<net::X509Certificate> cert =
    352       net::X509Certificate::CreateFromBytes(der, length);
    353   if (!cert.get())
    354     return false;
    355   return GetCertificateFields(*cert.get(), fields);
    356 }
    357 
    358 void PepperTCPSocket::SendReadACKError(int32_t error) {
    359   manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK(
    360     routing_id_, plugin_dispatcher_id_, socket_id_, error, std::string()));
    361 }
    362 
    363 void PepperTCPSocket::SendWriteACKError(int32_t error) {
    364   DCHECK_GT(0, error);
    365   manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK(
    366       routing_id_, plugin_dispatcher_id_, socket_id_, error));
    367 }
    368 
    369 void PepperTCPSocket::SendSSLHandshakeACK(bool succeeded) {
    370   ppapi::PPB_X509Certificate_Fields certificate_fields;
    371   if (succeeded) {
    372     // Our socket is guaranteed to be an SSL socket if we get here.
    373     net::SSLClientSocket* ssl_socket =
    374         static_cast<net::SSLClientSocket*>(socket_.get());
    375     net::SSLInfo ssl_info;
    376     ssl_socket->GetSSLInfo(&ssl_info);
    377     if (ssl_info.cert.get())
    378       GetCertificateFields(*ssl_info.cert.get(), &certificate_fields);
    379   }
    380   manager_->Send(new PpapiMsg_PPBTCPSocket_SSLHandshakeACK(
    381       routing_id_,
    382       plugin_dispatcher_id_,
    383       socket_id_,
    384       succeeded,
    385       certificate_fields));
    386 }
    387 
    388 void PepperTCPSocket::SendSetOptionACK(int32_t result) {
    389   manager_->Send(new PpapiMsg_PPBTCPSocket_SetOptionACK(
    390       routing_id_, plugin_dispatcher_id_, socket_id_, result));
    391 }
    392 
    393 void PepperTCPSocket::OnResolveCompleted(int net_result) {
    394   DCHECK(connection_state_ == CONNECT_IN_PROGRESS);
    395 
    396   if (net_result != net::OK) {
    397     SendConnectACKError(NetErrorToPepperError(net_result));
    398     connection_state_ = BEFORE_CONNECT;
    399     return;
    400   }
    401 
    402   StartConnect(address_list_);
    403 }
    404 
    405 void PepperTCPSocket::OnConnectCompleted(int net_result) {
    406   DCHECK(connection_state_ == CONNECT_IN_PROGRESS && socket_.get());
    407 
    408   int32_t pp_result = NetErrorToPepperError(net_result);
    409   do {
    410     if (pp_result != PP_OK)
    411       break;
    412 
    413     net::IPEndPoint ip_end_point_local;
    414     net::IPEndPoint ip_end_point_remote;
    415     pp_result = NetErrorToPepperError(
    416         socket_->GetLocalAddress(&ip_end_point_local));
    417     if (pp_result != PP_OK)
    418       break;
    419     pp_result = NetErrorToPepperError(
    420         socket_->GetPeerAddress(&ip_end_point_remote));
    421     if (pp_result != PP_OK)
    422       break;
    423 
    424     PP_NetAddress_Private local_addr =
    425         NetAddressPrivateImpl::kInvalidNetAddress;
    426     PP_NetAddress_Private remote_addr =
    427         NetAddressPrivateImpl::kInvalidNetAddress;
    428     if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    429             ip_end_point_local.address(),
    430             ip_end_point_local.port(),
    431             &local_addr) ||
    432         !NetAddressPrivateImpl::IPEndPointToNetAddress(
    433             ip_end_point_remote.address(),
    434             ip_end_point_remote.port(),
    435             &remote_addr)) {
    436       pp_result = PP_ERROR_ADDRESS_INVALID;
    437       break;
    438     }
    439 
    440     manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK(
    441         routing_id_, plugin_dispatcher_id_, socket_id_, PP_OK,
    442         local_addr, remote_addr));
    443     connection_state_ = CONNECTED;
    444     return;
    445   } while (false);
    446 
    447   SendConnectACKError(pp_result);
    448   connection_state_ = BEFORE_CONNECT;
    449 }
    450 
    451 void PepperTCPSocket::OnSSLHandshakeCompleted(int net_result) {
    452   DCHECK(connection_state_ == SSL_HANDSHAKE_IN_PROGRESS);
    453 
    454   bool succeeded = net_result == net::OK;
    455   SendSSLHandshakeACK(succeeded);
    456   connection_state_ = succeeded ? SSL_CONNECTED : SSL_HANDSHAKE_FAILED;
    457 }
    458 
    459 void PepperTCPSocket::OnReadCompleted(int net_result) {
    460   DCHECK(read_buffer_.get());
    461 
    462   if (net_result > 0) {
    463     manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK(
    464         routing_id_, plugin_dispatcher_id_, socket_id_, PP_OK,
    465         std::string(read_buffer_->data(), net_result)));
    466   } else if (net_result == 0) {
    467     end_of_file_reached_ = true;
    468     manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK(
    469         routing_id_, plugin_dispatcher_id_, socket_id_, PP_OK, std::string()));
    470   } else {
    471     SendReadACKError(NetErrorToPepperError(net_result));
    472   }
    473   read_buffer_ = NULL;
    474 }
    475 
    476 void PepperTCPSocket::OnWriteCompleted(int net_result) {
    477   DCHECK(write_buffer_base_.get());
    478   DCHECK(write_buffer_.get());
    479 
    480   // Note: For partial writes of 0 bytes, don't continue writing to avoid a
    481   // likely infinite loop.
    482   if (net_result > 0) {
    483     write_buffer_->DidConsume(net_result);
    484     if (write_buffer_->BytesRemaining() > 0) {
    485       DoWrite();
    486       return;
    487     }
    488   }
    489 
    490   if (net_result >= 0) {
    491     manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK(
    492         routing_id_, plugin_dispatcher_id_, socket_id_,
    493         write_buffer_->BytesConsumed()));
    494   } else {
    495     SendWriteACKError(NetErrorToPepperError(net_result));
    496   }
    497 
    498   write_buffer_ = NULL;
    499   write_buffer_base_ = NULL;
    500 }
    501 
    502 bool PepperTCPSocket::IsConnected() const {
    503   return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
    504 }
    505 
    506 bool PepperTCPSocket::IsSsl() const {
    507  return connection_state_ == SSL_HANDSHAKE_IN_PROGRESS ||
    508      connection_state_ == SSL_CONNECTED ||
    509      connection_state_ == SSL_HANDSHAKE_FAILED;
    510 }
    511 
    512 void PepperTCPSocket::DoWrite() {
    513   DCHECK(write_buffer_base_.get());
    514   DCHECK(write_buffer_.get());
    515   DCHECK_GT(write_buffer_->BytesRemaining(), 0);
    516 
    517   int net_result = socket_->Write(
    518       write_buffer_.get(),
    519       write_buffer_->BytesRemaining(),
    520       base::Bind(&PepperTCPSocket::OnWriteCompleted, base::Unretained(this)));
    521   if (net_result != net::ERR_IO_PENDING)
    522     OnWriteCompleted(net_result);
    523 }
    524 
    525 }  // namespace content
    526