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