1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/sm_connection.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <errno.h>
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <netinet/tcp.h>
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <sys/socket.h>
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <list>
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <string>
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/constants.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/flip_config.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/http_interface.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/spdy_interface.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/spdy_ssl.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/streamer_interface.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net {
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SMConnection::force_spdy_ = false;
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
26dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSMConnection::SMConnection(EpollServer* epoll_server,
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           SSLState* ssl_state,
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           MemoryCache* memory_cache,
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           FlipAcceptor* acceptor,
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                           std::string log_prefix)
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : last_read_time_(0),
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      fd_(-1),
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      events_(0),
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      registered_in_epoll_server_(false),
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      initialized_(false),
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      protocol_detected_(false),
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_complete_(false),
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_pool_(NULL),
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      epoll_server_(epoll_server),
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ssl_state_(ssl_state),
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      memory_cache_(memory_cache),
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      acceptor_(acceptor),
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      read_buffer_(kSpdySegmentSize * 40),
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_spdy_interface_(NULL),
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_http_interface_(NULL),
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_streamer_interface_(NULL),
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_interface_(NULL),
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      log_prefix_(log_prefix),
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      max_bytes_sent_per_dowrite_(4096),
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ssl_(NULL) {
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
53dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSMConnection::~SMConnection() {
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (initialized())
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Reset();
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
58dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenEpollServer* SMConnection::epoll_server() {
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return epoll_server_;
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::ReadyToSend() {
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "Setting ready to send: EPOLLIN | EPOLLOUT";
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  epoll_server_->SetFDReady(fd_, EPOLLIN | EPOLLOUT);
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::EnqueueDataFrame(DataFrame* df) {
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  output_list_.push_back(df);
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "EnqueueDataFrame: "
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "size = " << df->size << ": Setting FD ready.";
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ReadyToSend();
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::InitSMConnection(SMConnectionPoolInterface* connection_pool,
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    SMInterface* sm_interface,
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    EpollServer* epoll_server,
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    int fd,
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    std::string server_ip,
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    std::string server_port,
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    std::string remote_ip,
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    bool use_ssl) {
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (initialized_) {
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(FATAL) << "Attempted to initialize already initialized server";
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  client_ip_ = remote_ip;
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (fd == -1) {
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If fd == -1, then we are initializing a new connection that will
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // connect to the backend.
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    //
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // ret:  -1 == error
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    //        0 == connection in progress
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    //        1 == connection complete
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // TODO(kelindsay): is_numeric_host_address value needs to be detected
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    server_ip_ = server_ip;
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    server_port_ = server_port;
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int ret = CreateConnectedSocket(&fd_,
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    server_ip,
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    server_port,
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    true,
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    acceptor_->disable_nagle_);
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ret < 0) {
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(ERROR) << "-1 Could not create connected socket";
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return;
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (ret == 1) {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      DCHECK_NE(-1, fd_);
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_complete_ = true;
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << "Connection complete to: " << server_ip_ << ":"
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << server_port_ << " ";
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "Connecting to server: " << server_ip_ << ":"
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << server_port_ << " ";
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If fd != -1 then we are initializing a connection that has just been
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // accepted from the listen socket.
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_complete_ = true;
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (epoll_server_ && registered_in_epoll_server_ && fd_ != -1) {
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      epoll_server_->UnregisterFD(fd_);
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (fd_ != -1) {
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               << "Closing pre-existing fd";
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      close(fd_);
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      fd_ = -1;
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    fd_ = fd;
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  registered_in_epoll_server_ = false;
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Set the last read time here as the idle checker will start from
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // now.
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  last_read_time_ = time(NULL);
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  initialized_ = true;
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  connection_pool_ = connection_pool;
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  epoll_server_ = epoll_server;
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (sm_interface) {
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_interface_ = sm_interface;
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    protocol_detected_ = true;
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  read_buffer_.Clear();
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  epoll_server_->RegisterFD(fd_, this, EPOLLIN | EPOLLOUT | EPOLLET);
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (use_ssl) {
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ssl_ = CreateSSLContext(ssl_state_->ssl_ctx);
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSL_set_fd(ssl_, fd_);
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::CorkSocket() {
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int state = 1;
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int rv = setsockopt(fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv < 0)
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "setsockopt(CORK): " << errno;
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::UncorkSocket() {
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int state = 0;
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int rv = setsockopt(fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv < 0)
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << "setsockopt(CORK): " << errno;
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint SMConnection::Send(const char* data, int len, int flags) {
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int rv = 0;
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CorkSocket();
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (ssl_) {
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ssize_t bytes_written = 0;
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Write smallish chunks to SSL so that we don't have large
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // multi-packet TLS records to receive before being able to handle
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // the data.  We don't have to be too careful here, because our data
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // frames are already getting chunked appropriately, and those are
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // the most likely "big" frames.
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    while (len > 0) {
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      const int kMaxTLSRecordSize = 1500;
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      const char* ptr = &(data[bytes_written]);
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      int chunksize = std::min(len, kMaxTLSRecordSize);
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      rv = SSL_write(ssl_, ptr, chunksize);
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << "SSLWrite(" << chunksize << " bytes): " << rv;
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (rv <= 0) {
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        switch (SSL_get_error(ssl_, rv)) {
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_READ:
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_WRITE:
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_ACCEPT:
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_CONNECT:
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            rv = -2;
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            break;
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          default:
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            PrintSslError();
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            break;
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      bytes_written += rv;
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      len -= rv;
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (rv != chunksize)
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;  // If we couldn't write everything, we're implicitly stalled
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If we wrote some data, return that count.  Otherwise
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // return the stall error.
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (bytes_written > 0)
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      rv = bytes_written;
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    rv = send(fd_, data, len, flags);
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!(flags & MSG_MORE))
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UncorkSocket();
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return rv;
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::OnRegistration(EpollServer* eps, int fd, int event_mask) {
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  registered_in_epoll_server_ = true;
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::OnEvent(int fd, EpollEvent* event) {
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  events_ |= event->in_events;
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HandleEvents();
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events_) {
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    event->out_ready_mask = events_;
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    events_ = 0;
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::OnUnregistration(int fd, bool replaced) {
236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  registered_in_epoll_server_ = false;
237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::OnShutdown(EpollServer* eps, int fd) {
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Cleanup("OnShutdown");
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return;
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::Cleanup(const char* cleanup) {
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Cleanup: " << cleanup;
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!initialized_)
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Reset();
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (connection_pool_)
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_pool_->SMConnectionDone(this);
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (sm_interface_)
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_interface_->ResetForNewConnection();
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  last_read_time_ = 0;
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::HandleEvents() {
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Received: "
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << EpollServer::EventMaskToString(events_).c_str();
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events_ & EPOLLIN) {
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!DoRead())
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      goto handle_close_or_error;
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events_ & EPOLLOUT) {
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Check if we have connected or not
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (connection_complete_ == false) {
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      int sock_error;
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      socklen_t sock_error_len = sizeof(sock_error);
270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      int ret = getsockopt(fd_, SOL_SOCKET, SO_ERROR, &sock_error,
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            &sock_error_len);
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (ret != 0) {
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << "getsockopt error: " << errno << ": " << strerror(errno);
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        goto handle_close_or_error;
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (sock_error == 0) {
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        connection_complete_ = true;
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << "Connection complete to " << server_ip_ << ":"
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << server_port_ << " ";
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else if (sock_error == EINPROGRESS) {
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return;
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << "error connecting to server";
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        goto handle_close_or_error;
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!DoWrite())
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      goto handle_close_or_error;
292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (events_ & (EPOLLHUP | EPOLLERR)) {
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "!!! Got HUP or ERR";
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    goto handle_close_or_error;
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return;
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  handle_close_or_error:
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Cleanup("HandleEvents");
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Decide if SPDY was negotiated.
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SMConnection::WasSpdyNegotiated() {
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (force_spdy())
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return true;
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If this is an SSL connection, check if NPN specifies SPDY.
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (ssl_) {
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const unsigned char *npn_proto;
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    unsigned int npn_proto_len;
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSL_get0_next_proto_negotiated(ssl_, &npn_proto, &npn_proto_len);
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (npn_proto_len > 0) {
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      std::string npn_proto_str((const char *)npn_proto, npn_proto_len);
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << "NPN protocol detected: " << npn_proto_str;
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!strncmp(reinterpret_cast<const char*>(npn_proto),
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                   "spdy/2", npn_proto_len))
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return true;
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return false;
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SMConnection::SetupProtocolInterfaces() {
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!protocol_detected_);
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  protocol_detected_ = true;
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool spdy_negotiated = WasSpdyNegotiated();
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool using_ssl = ssl_ != NULL;
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (using_ssl)
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << (SSL_session_reused(ssl_) ? "Resumed" : "Renegotiated")
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << " SSL Session.";
337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->spdy_only_ && !spdy_negotiated) {
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "SPDY proxy only, closing HTTPS connection.";
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (acceptor_->flip_handler_type_) {
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case FLIP_HANDLER_HTTP_SERVER:
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(!spdy_negotiated);
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << (sm_http_interface_ ? "Creating" : "Reusing")
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << " HTTP interface.";
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (!sm_http_interface_)
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sm_http_interface_ = new HttpSM(this,
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          NULL,
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          epoll_server_,
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          memory_cache_,
356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          acceptor_);
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        sm_interface_ = sm_http_interface_;
358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case FLIP_HANDLER_PROXY:
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << (sm_streamer_interface_ ? "Creating" : "Reusing")
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << " PROXY Streamer interface.";
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (!sm_streamer_interface_) {
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sm_streamer_interface_ = new StreamerSM(this,
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                  NULL,
368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                  epoll_server_,
369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                  acceptor_);
370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sm_streamer_interface_->set_is_request();
371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        sm_interface_ = sm_streamer_interface_;
373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        // If spdy is not negotiated, the streamer interface will proxy all
374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        // data to the origin server.
375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (!spdy_negotiated)
376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          break;
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Otherwise fall through into the case below.
379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case FLIP_HANDLER_SPDY_SERVER:
380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(spdy_negotiated);
382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << (sm_spdy_interface_ ? "Creating" : "Reusing")
384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                << " SPDY interface.";
385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (!sm_spdy_interface_)
386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          sm_spdy_interface_ = new SpdySM(this,
387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          NULL,
388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          epoll_server_,
389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          memory_cache_,
390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          acceptor_);
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        sm_interface_ = sm_spdy_interface_;
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CorkSocket();
397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!sm_interface_->PostAcceptHook())
398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return true;
401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SMConnection::DoRead() {
404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "DoRead()";
405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  while (!read_buffer_.Full()) {
406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    char* bytes;
407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int size;
408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (fd_ == -1) {
409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << "DoRead(): fd_ == -1. Invalid FD. Returning false";
411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    read_buffer_.GetWritablePtr(&bytes, &size);
414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ssize_t bytes_read = 0;
415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ssl_) {
416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      bytes_read = SSL_read(ssl_, bytes, size);
417dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (bytes_read < 0) {
418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        int err = SSL_get_error(ssl_, bytes_read);
419dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        switch (err) {
420dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_READ:
421dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_WRITE:
422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_ACCEPT:
423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          case SSL_ERROR_WANT_CONNECT:
424dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            events_ &= ~EPOLLIN;
425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    << "DoRead: SSL WANT_XXX: " << err;
427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            goto done;
428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          default:
429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            PrintSslError();
430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            goto error_or_close;
431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
433dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {
434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      bytes_read = recv(fd_, bytes, size, MSG_DONTWAIT);
435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int stored_errno = errno;
437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (bytes_read == -1) {
438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switch (stored_errno) {
439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        case EAGAIN:
440dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          events_ &= ~EPOLLIN;
441dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
442dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "Got EAGAIN while reading";
443dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          goto done;
444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        case EINTR:
445dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "Got EINTR while reading";
447dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          continue;
448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        default:
449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "While calling recv, got error: "
451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << (ssl_?"(ssl error)":strerror(stored_errno));
452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          goto error_or_close;
453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (bytes_read > 0) {
455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "read " << bytes_read
456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               << " bytes";
457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      last_read_time_ = time(NULL);
458dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // If the protocol hasn't been detected yet, set up the handlers
459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // we'll need.
460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!protocol_detected_) {
461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (!SetupProtocolInterfaces()) {
462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          LOG(ERROR) << "Error setting up protocol interfaces.";
463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          goto error_or_close;
464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      read_buffer_.AdvanceWritablePtr(bytes_read);
467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!DoConsumeReadData())
468dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        goto error_or_close;
469dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      continue;
470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {  // bytes_read == 0
471dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
472dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << "0 bytes read with recv call.";
473dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
474dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    goto error_or_close;
475dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
476dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen done:
477dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "DoRead done!";
478dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return true;
479dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
480dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  error_or_close:
481dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "DoRead(): error_or_close. "
483dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "Cleaning up, then returning false";
484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Cleanup("DoRead");
485dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return false;
486dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SMConnection::DoConsumeReadData() {
489dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char* bytes;
490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int size;
491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  read_buffer_.GetReadablePtr(&bytes, &size);
492dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  while (size != 0) {
493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    size_t bytes_consumed = sm_interface_->ProcessReadInput(bytes, size);
494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "consumed "
495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << bytes_consumed << " bytes";
496dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (bytes_consumed == 0) {
497dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    read_buffer_.AdvanceReadablePtr(bytes_consumed);
500dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (sm_interface_->MessageFullyRead()) {
501dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << "HandleRequestFullyRead: Setting EPOLLOUT";
503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      HandleResponseFullyRead();
504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      events_ |= EPOLLOUT;
505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (sm_interface_->Error()) {
506dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(ERROR) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
507dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 << "Framer error detected: Setting EPOLLOUT: "
508dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 << sm_interface_->ErrorAsString();
509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // this causes everything to be closed/cleaned up.
510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      events_ |= EPOLLOUT;
511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return false;
512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
513dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    read_buffer_.GetReadablePtr(&bytes, &size);
514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
515dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return true;
516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::HandleResponseFullyRead() {
519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sm_interface_->Cleanup();
520dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
521dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
522dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SMConnection::DoWrite() {
523dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t bytes_sent = 0;
524dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int flags = MSG_NOSIGNAL | MSG_DONTWAIT;
525dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (fd_ == -1) {
526dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
527dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "DoWrite: fd == -1. Returning false.";
528dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
529dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
530dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (output_list_.empty()) {
531dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << log_prefix_ << "DoWrite: Output list empty.";
532dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (sm_interface_) {
533dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_interface_->GetOutput();
534dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
535dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (output_list_.empty()) {
536dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      events_ &= ~EPOLLOUT;
537dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
538dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
539dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  while (!output_list_.empty()) {
540dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << log_prefix_ << "DoWrite: Items in output list: "
541dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << output_list_.size();
542dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (bytes_sent >= max_bytes_sent_per_dowrite_) {
543dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
544dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << " byte sent >= max bytes sent per write: Setting EPOLLOUT: "
545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << bytes_sent;
546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      events_ |= EPOLLOUT;
547dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (sm_interface_ && output_list_.size() < 2) {
550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_interface_->GetOutput();
551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DataFrame* data_frame = output_list_.front();
553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const char*  bytes = data_frame->data;
554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int size = data_frame->size;
555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bytes += data_frame->index;
556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    size -= data_frame->index;
557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK_GE(size, 0);
558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (size <= 0) {
559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      output_list_.pop_front();
560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      delete data_frame;
561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      continue;
562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    flags = MSG_NOSIGNAL | MSG_DONTWAIT;
565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Look for a queue size > 1 because |this| frame is remains on the list
566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // until it has finished sending.
567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (output_list_.size() > 1) {
568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << "Outlist size: " << output_list_.size()
569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << ": Adding MSG_MORE flag";
570dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      flags |= MSG_MORE;
571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
572dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << log_prefix_ << "Attempting to send " << size << " bytes.";
573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ssize_t bytes_written = Send(bytes, size, flags);
574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int stored_errno = errno;
575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (bytes_written == -1) {
576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switch (stored_errno) {
577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        case EAGAIN:
578dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          events_ &= ~EPOLLOUT;
579dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "Got EAGAIN while writing";
581dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          goto done;
582dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        case EINTR:
583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
584dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "Got EINTR while writing";
585dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          continue;
586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        default:
587dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
588dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "While calling send, got error: " << stored_errno
589dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << ": " << (ssl_?"":strerror(stored_errno));
590dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          goto error_or_close;
591dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (bytes_written > 0) {
593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Wrote: "
594dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              << bytes_written << " bytes";
595dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      data_frame->index += bytes_written;
596dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      bytes_sent += bytes_written;
597dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      continue;
598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (bytes_written == -2) {
599dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // -2 handles SSL_ERROR_WANT_* errors
600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      events_ &= ~EPOLLOUT;
601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      goto done;
602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "0 bytes written with send call.";
605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    goto error_or_close;
606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen done:
608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UncorkSocket();
609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return true;
610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen error_or_close:
612dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
613dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "DoWrite: error_or_close. Returning false "
614dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "after cleaning up";
615dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Cleanup("DoWrite");
616dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UncorkSocket();
617dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return false;
618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SMConnection::Reset() {
621dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Resetting";
622dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (ssl_) {
623dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSL_shutdown(ssl_);
624dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
625dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSL_free(ssl_);
626dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PrintSslError();
627dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ssl_ = NULL;
628dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
629dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (registered_in_epoll_server_) {
630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    epoll_server_->UnregisterFD(fd_);
631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    registered_in_epoll_server_ = false;
632dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
633dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (fd_ >= 0) {
634dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Closing connection";
635dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    close(fd_);
636dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    fd_ = -1;
637dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
638dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  read_buffer_.Clear();
639dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  initialized_ = false;
640dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  protocol_detected_ = false;
641dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  events_ = 0;
642dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (std::list<DataFrame*>::iterator i =
643dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       output_list_.begin();
644dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       i != output_list_.end();
645dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       ++i) {
646dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    delete *i;
647dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
648dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  output_list_.clear();
649dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
650dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
651dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
652dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSMConnection* SMConnection::NewSMConnection(EpollServer* epoll_server,
653dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                            SSLState *ssl_state,
654dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                            MemoryCache* memory_cache,
655dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                            FlipAcceptor *acceptor,
656dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                            std::string log_prefix) {
657dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return new SMConnection(epoll_server, ssl_state, memory_cache,
658dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                          acceptor, log_prefix);
659dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace net
662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
664