| Index: chrome/browser/sync/notifier/communicator/ssl_socket_adapter.cc
|
| ===================================================================
|
| --- chrome/browser/sync/notifier/communicator/ssl_socket_adapter.cc (revision 46353)
|
| +++ chrome/browser/sync/notifier/communicator/ssl_socket_adapter.cc (working copy)
|
| @@ -1,389 +0,0 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/sync/notifier/communicator/ssl_socket_adapter.h"
|
| -
|
| -#include "base/compiler_specific.h"
|
| -#include "base/message_loop.h"
|
| -#include "net/base/address_list.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/base/ssl_config_service.h"
|
| -#include "net/base/sys_addrinfo.h"
|
| -#include "net/socket/client_socket_factory.h"
|
| -#include "net/url_request/url_request_context.h"
|
| -
|
| -namespace notifier {
|
| -
|
| -namespace {
|
| -
|
| -// Convert values from <errno.h> to values from "net/base/net_errors.h"
|
| -int MapPosixError(int err) {
|
| - // There are numerous posix error codes, but these are the ones we thus far
|
| - // find interesting.
|
| - switch (err) {
|
| - case EAGAIN:
|
| -#if EWOULDBLOCK != EAGAIN
|
| - case EWOULDBLOCK:
|
| -#endif
|
| - return net::ERR_IO_PENDING;
|
| - case ENETDOWN:
|
| - return net::ERR_INTERNET_DISCONNECTED;
|
| - case ETIMEDOUT:
|
| - return net::ERR_TIMED_OUT;
|
| - case ECONNRESET:
|
| - case ENETRESET: // Related to keep-alive
|
| - return net::ERR_CONNECTION_RESET;
|
| - case ECONNABORTED:
|
| - return net::ERR_CONNECTION_ABORTED;
|
| - case ECONNREFUSED:
|
| - return net::ERR_CONNECTION_REFUSED;
|
| - case EHOSTUNREACH:
|
| - case ENETUNREACH:
|
| - return net::ERR_ADDRESS_UNREACHABLE;
|
| - case EADDRNOTAVAIL:
|
| - return net::ERR_ADDRESS_INVALID;
|
| - case 0:
|
| - return net::OK;
|
| - default:
|
| - LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
|
| - return net::ERR_FAILED;
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -SSLSocketAdapter* SSLSocketAdapter::Create(AsyncSocket* socket) {
|
| - return new SSLSocketAdapter(socket);
|
| -}
|
| -
|
| -SSLSocketAdapter::SSLSocketAdapter(AsyncSocket* socket)
|
| - : SSLAdapter(socket),
|
| - ignore_bad_cert_(false),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(
|
| - connected_callback_(this, &SSLSocketAdapter::OnConnected)),
|
| - ALLOW_THIS_IN_INITIALIZER_LIST(
|
| - io_callback_(this, &SSLSocketAdapter::OnIO)),
|
| - ssl_connected_(false),
|
| - state_(STATE_NONE) {
|
| - transport_socket_ = new TransportSocket(socket, this);
|
| -}
|
| -
|
| -int SSLSocketAdapter::StartSSL(const char* hostname, bool restartable) {
|
| - DCHECK(!restartable);
|
| - hostname_ = hostname;
|
| -
|
| - if (socket_->GetState() != Socket::CS_CONNECTED) {
|
| - state_ = STATE_SSL_WAIT;
|
| - return 0;
|
| - } else {
|
| - return BeginSSL();
|
| - }
|
| -}
|
| -
|
| -int SSLSocketAdapter::BeginSSL() {
|
| - if (!MessageLoop::current()) {
|
| - // Certificate verification is done via the Chrome message loop.
|
| - // Without this check, if we don't have a chrome message loop the
|
| - // SSL connection just hangs silently.
|
| - LOG(DFATAL) << "Chrome message loop (needed by SSL certificate "
|
| - << "verification) does not exist";
|
| - return net::ERR_UNEXPECTED;
|
| - }
|
| -
|
| - // SSLConfigService is not thread-safe, and the default values for SSLConfig
|
| - // are correct for us, so we don't use the config service to initialize this
|
| - // object.
|
| - net::SSLConfig ssl_config;
|
| - transport_socket_->set_addr(talk_base::SocketAddress(hostname_.c_str()));
|
| - ssl_socket_.reset(
|
| - net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
|
| - transport_socket_, hostname_.c_str(), ssl_config));
|
| -
|
| - int result = ssl_socket_->Connect(&connected_callback_);
|
| -
|
| - if (result == net::ERR_IO_PENDING || result == net::OK) {
|
| - return 0;
|
| - } else {
|
| - LOG(ERROR) << "Could not start SSL: " << net::ErrorToString(result);
|
| - return result;
|
| - }
|
| -}
|
| -
|
| -int SSLSocketAdapter::Send(const void* buf, size_t len) {
|
| - if (!ssl_connected_) {
|
| - return AsyncSocketAdapter::Send(buf, len);
|
| - } else {
|
| - scoped_refptr<net::IOBuffer> transport_buf = new net::IOBuffer(len);
|
| - memcpy(transport_buf->data(), buf, len);
|
| -
|
| - int result = ssl_socket_->Write(transport_buf, len, NULL);
|
| - if (result == net::ERR_IO_PENDING) {
|
| - SetError(EWOULDBLOCK);
|
| - }
|
| - transport_buf = NULL;
|
| - return result;
|
| - }
|
| -}
|
| -
|
| -int SSLSocketAdapter::Recv(void* buf, size_t len) {
|
| - if (!ssl_connected_) {
|
| - return AsyncSocketAdapter::Recv(buf, len);
|
| - }
|
| -
|
| - switch (state_) {
|
| - case STATE_NONE: {
|
| - transport_buf_ = new net::IOBuffer(len);
|
| - int result = ssl_socket_->Read(transport_buf_, len, &io_callback_);
|
| - if (result >= 0) {
|
| - memcpy(buf, transport_buf_->data(), len);
|
| - }
|
| -
|
| - if (result == net::ERR_IO_PENDING) {
|
| - state_ = STATE_READ;
|
| - SetError(EWOULDBLOCK);
|
| - } else {
|
| - if (result < 0) {
|
| - SetError(result);
|
| - LOG(INFO) << "Socket error " << result;
|
| - }
|
| - transport_buf_ = NULL;
|
| - }
|
| - return result;
|
| - }
|
| - case STATE_READ_COMPLETE:
|
| - memcpy(buf, transport_buf_->data(), len);
|
| - transport_buf_ = NULL;
|
| - state_ = STATE_NONE;
|
| - return data_transferred_;
|
| -
|
| - case STATE_READ:
|
| - case STATE_WRITE:
|
| - case STATE_WRITE_COMPLETE:
|
| - case STATE_SSL_WAIT:
|
| - SetError(EWOULDBLOCK);
|
| - return -1;
|
| -
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| - return -1;
|
| -}
|
| -
|
| -void SSLSocketAdapter::OnConnected(int result) {
|
| - if (result == net::OK) {
|
| - ssl_connected_ = true;
|
| - OnConnectEvent(this);
|
| - } else {
|
| - LOG(WARNING) << "OnConnected failed with error " << result;
|
| - }
|
| -}
|
| -
|
| -void SSLSocketAdapter::OnIO(int result) {
|
| - switch (state_) {
|
| - case STATE_READ:
|
| - state_ = STATE_READ_COMPLETE;
|
| - data_transferred_ = result;
|
| - AsyncSocketAdapter::OnReadEvent(this);
|
| - break;
|
| - case STATE_WRITE:
|
| - state_ = STATE_WRITE_COMPLETE;
|
| - data_transferred_ = result;
|
| - AsyncSocketAdapter::OnWriteEvent(this);
|
| - break;
|
| - case STATE_NONE:
|
| - case STATE_READ_COMPLETE:
|
| - case STATE_WRITE_COMPLETE:
|
| - case STATE_SSL_WAIT:
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void SSLSocketAdapter::OnReadEvent(talk_base::AsyncSocket* socket) {
|
| - if (!transport_socket_->OnReadEvent(socket))
|
| - AsyncSocketAdapter::OnReadEvent(socket);
|
| -}
|
| -
|
| -void SSLSocketAdapter::OnWriteEvent(talk_base::AsyncSocket* socket) {
|
| - if (!transport_socket_->OnWriteEvent(socket))
|
| - AsyncSocketAdapter::OnWriteEvent(socket);
|
| -}
|
| -
|
| -void SSLSocketAdapter::OnConnectEvent(talk_base::AsyncSocket* socket) {
|
| - if (state_ != STATE_SSL_WAIT) {
|
| - AsyncSocketAdapter::OnConnectEvent(socket);
|
| - } else {
|
| - state_ = STATE_NONE;
|
| - int result = BeginSSL();
|
| - if (0 != result) {
|
| - // TODO(zork): Handle this case gracefully.
|
| - LOG(WARNING) << "BeginSSL() failed with " << result;
|
| - }
|
| - }
|
| -}
|
| -
|
| -TransportSocket::TransportSocket(talk_base::AsyncSocket* socket,
|
| - SSLSocketAdapter *ssl_adapter)
|
| - : connect_callback_(NULL),
|
| - read_callback_(NULL),
|
| - write_callback_(NULL),
|
| - read_buffer_len_(0),
|
| - write_buffer_len_(0),
|
| - socket_(socket) {
|
| - socket_->SignalConnectEvent.connect(this, &TransportSocket::OnConnectEvent);
|
| -}
|
| -
|
| -int TransportSocket::Connect(net::CompletionCallback* callback) {
|
| - connect_callback_ = callback;
|
| - return socket_->Connect(addr_);
|
| -}
|
| -
|
| -void TransportSocket::Disconnect() {
|
| - socket_->Close();
|
| -}
|
| -
|
| -bool TransportSocket::IsConnected() const {
|
| - return (socket_->GetState() == talk_base::Socket::CS_CONNECTED);
|
| -}
|
| -
|
| -bool TransportSocket::IsConnectedAndIdle() const {
|
| - // Not implemented.
|
| - NOTREACHED();
|
| - return false;
|
| -}
|
| -
|
| -int TransportSocket::GetPeerAddress(net::AddressList* address) const {
|
| - talk_base::SocketAddress socket_address = socket_->GetRemoteAddress();
|
| -
|
| - // libjingle supports only IPv4 addresses.
|
| - sockaddr_in ipv4addr;
|
| - socket_address.ToSockAddr(&ipv4addr);
|
| -
|
| - struct addrinfo ai;
|
| - memset(&ai, 0, sizeof(ai));
|
| - ai.ai_family = ipv4addr.sin_family;
|
| - ai.ai_socktype = SOCK_STREAM;
|
| - ai.ai_protocol = IPPROTO_TCP;
|
| - ai.ai_addr = reinterpret_cast<struct sockaddr*>(&ipv4addr);
|
| - ai.ai_addrlen = sizeof(ipv4addr);
|
| -
|
| - address->Copy(&ai, false);
|
| - return net::OK;
|
| -}
|
| -
|
| -int TransportSocket::Read(net::IOBuffer* buf, int buf_len,
|
| - net::CompletionCallback* callback) {
|
| - DCHECK(buf);
|
| - DCHECK(!read_callback_);
|
| - DCHECK(!read_buffer_.get());
|
| - int result = socket_->Recv(buf->data(), buf_len);
|
| - if (result < 0) {
|
| - result = MapPosixError(socket_->GetError());
|
| - if (result == net::ERR_IO_PENDING) {
|
| - read_callback_ = callback;
|
| - read_buffer_ = buf;
|
| - read_buffer_len_ = buf_len;
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -int TransportSocket::Write(net::IOBuffer* buf, int buf_len,
|
| - net::CompletionCallback* callback) {
|
| - DCHECK(buf);
|
| - DCHECK(!write_callback_);
|
| - DCHECK(!write_buffer_.get());
|
| - int result = socket_->Send(buf->data(), buf_len);
|
| - if (result < 0) {
|
| - result = MapPosixError(socket_->GetError());
|
| - if (result == net::ERR_IO_PENDING) {
|
| - write_callback_ = callback;
|
| - write_buffer_ = buf;
|
| - write_buffer_len_ = buf_len;
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -bool TransportSocket::SetReceiveBufferSize(int32 size) {
|
| - // Not implemented.
|
| - return false;
|
| -}
|
| -
|
| -bool TransportSocket::SetSendBufferSize(int32 size) {
|
| - // Not implemented.
|
| - return false;
|
| -}
|
| -
|
| -void TransportSocket::OnConnectEvent(talk_base::AsyncSocket * socket) {
|
| - if (connect_callback_) {
|
| - net::CompletionCallback *callback = connect_callback_;
|
| - connect_callback_ = NULL;
|
| - callback->RunWithParams(Tuple1<int>(MapPosixError(socket_->GetError())));
|
| - } else {
|
| - LOG(WARNING) << "OnConnectEvent called with no callback.";
|
| - }
|
| -}
|
| -
|
| -bool TransportSocket::OnReadEvent(talk_base::AsyncSocket* socket) {
|
| - if (read_callback_) {
|
| - DCHECK(read_buffer_.get());
|
| - net::CompletionCallback* callback = read_callback_;
|
| - scoped_refptr<net::IOBuffer> buffer = read_buffer_;
|
| - int buffer_len = read_buffer_len_;
|
| -
|
| - read_callback_ = NULL;
|
| - read_buffer_ = NULL;
|
| - read_buffer_len_ = 0;
|
| -
|
| - int result = socket_->Recv(buffer->data(), buffer_len);
|
| - if (result < 0) {
|
| - result = MapPosixError(socket_->GetError());
|
| - if (result == net::ERR_IO_PENDING) {
|
| - read_callback_ = callback;
|
| - read_buffer_ = buffer;
|
| - read_buffer_len_ = buffer_len;
|
| - return true;
|
| - }
|
| - }
|
| - callback->RunWithParams(Tuple1<int>(result));
|
| - return true;
|
| - } else {
|
| - LOG(WARNING) << "OnReadEvent called with no callback.";
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -bool TransportSocket::OnWriteEvent(talk_base::AsyncSocket* socket) {
|
| - if (write_callback_) {
|
| - DCHECK(write_buffer_.get());
|
| - net::CompletionCallback* callback = write_callback_;
|
| - scoped_refptr<net::IOBuffer> buffer = write_buffer_;
|
| - int buffer_len = write_buffer_len_;
|
| -
|
| - write_callback_ = NULL;
|
| - write_buffer_ = NULL;
|
| - write_buffer_len_ = 0;
|
| -
|
| - int result = socket_->Send(buffer->data(), buffer_len);
|
| - if (result < 0) {
|
| - result = MapPosixError(socket_->GetError());
|
| - if (result == net::ERR_IO_PENDING) {
|
| - write_callback_ = callback;
|
| - write_buffer_ = buffer;
|
| - write_buffer_len_ = buffer_len;
|
| - return true;
|
| - }
|
| - }
|
| - callback->RunWithParams(Tuple1<int>(result));
|
| - return true;
|
| - } else {
|
| - LOG(WARNING) << "OnWriteEvent called with no callback.";
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -} // namespace notifier
|
|
|