| Index: net/tools/flip_server/sm_connection.cc
|
| diff --git a/net/tools/flip_server/sm_connection.cc b/net/tools/flip_server/sm_connection.cc
|
| deleted file mode 100644
|
| index fb2d6ccb5e687690326128f4558717ff8e090ec4..0000000000000000000000000000000000000000
|
| --- a/net/tools/flip_server/sm_connection.cc
|
| +++ /dev/null
|
| @@ -1,657 +0,0 @@
|
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/tools/flip_server/sm_connection.h"
|
| -
|
| -#include <errno.h>
|
| -#include <netinet/tcp.h>
|
| -#include <sys/socket.h>
|
| -#include <unistd.h>
|
| -
|
| -#include <algorithm>
|
| -#include <list>
|
| -#include <string>
|
| -
|
| -#include "net/tools/flip_server/constants.h"
|
| -#include "net/tools/flip_server/flip_config.h"
|
| -#include "net/tools/flip_server/http_interface.h"
|
| -#include "net/tools/flip_server/spdy_interface.h"
|
| -#include "net/tools/flip_server/spdy_ssl.h"
|
| -#include "net/tools/flip_server/streamer_interface.h"
|
| -#include "net/tools/flip_server/tcp_socket_util.h"
|
| -
|
| -namespace net {
|
| -
|
| -// static
|
| -bool SMConnection::force_spdy_ = false;
|
| -
|
| -DataFrame::~DataFrame() {
|
| - if (delete_when_done)
|
| - delete[] data;
|
| -}
|
| -
|
| -SMConnection::SMConnection(EpollServer* epoll_server,
|
| - SSLState* ssl_state,
|
| - MemoryCache* memory_cache,
|
| - FlipAcceptor* acceptor,
|
| - std::string log_prefix)
|
| - : last_read_time_(0),
|
| - fd_(-1),
|
| - events_(0),
|
| - registered_in_epoll_server_(false),
|
| - initialized_(false),
|
| - protocol_detected_(false),
|
| - connection_complete_(false),
|
| - connection_pool_(NULL),
|
| - epoll_server_(epoll_server),
|
| - ssl_state_(ssl_state),
|
| - memory_cache_(memory_cache),
|
| - acceptor_(acceptor),
|
| - read_buffer_(kSpdySegmentSize * 40),
|
| - sm_spdy_interface_(NULL),
|
| - sm_http_interface_(NULL),
|
| - sm_streamer_interface_(NULL),
|
| - sm_interface_(NULL),
|
| - log_prefix_(log_prefix),
|
| - max_bytes_sent_per_dowrite_(4096),
|
| - ssl_(NULL) {}
|
| -
|
| -SMConnection::~SMConnection() {
|
| - if (initialized())
|
| - Reset();
|
| -}
|
| -
|
| -EpollServer* SMConnection::epoll_server() { return epoll_server_; }
|
| -
|
| -void SMConnection::ReadyToSend() {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Setting ready to send: EPOLLIN | EPOLLOUT";
|
| - epoll_server_->SetFDReady(fd_, EPOLLIN | EPOLLOUT);
|
| -}
|
| -
|
| -void SMConnection::EnqueueDataFrame(DataFrame* df) {
|
| - output_list_.push_back(df);
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "EnqueueDataFrame: "
|
| - << "size = " << df->size << ": Setting FD ready.";
|
| - ReadyToSend();
|
| -}
|
| -
|
| -void SMConnection::InitSMConnection(SMConnectionPoolInterface* connection_pool,
|
| - SMInterface* sm_interface,
|
| - EpollServer* epoll_server,
|
| - int fd,
|
| - std::string server_ip,
|
| - std::string server_port,
|
| - std::string remote_ip,
|
| - bool use_ssl) {
|
| - if (initialized_) {
|
| - LOG(FATAL) << "Attempted to initialize already initialized server";
|
| - return;
|
| - }
|
| -
|
| - client_ip_ = remote_ip;
|
| -
|
| - if (fd == -1) {
|
| - // If fd == -1, then we are initializing a new connection that will
|
| - // connect to the backend.
|
| - //
|
| - // ret: -1 == error
|
| - // 0 == connection in progress
|
| - // 1 == connection complete
|
| - // TODO(kelindsay): is_numeric_host_address value needs to be detected
|
| - server_ip_ = server_ip;
|
| - server_port_ = server_port;
|
| - int ret = CreateTCPClientSocket(
|
| - server_ip, server_port, true, acceptor_->disable_nagle_, &fd_);
|
| -
|
| - if (ret < 0) {
|
| - LOG(ERROR) << "-1 Could not create connected socket";
|
| - return;
|
| - } else if (ret == 1) {
|
| - DCHECK_NE(-1, fd_);
|
| - connection_complete_ = true;
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Connection complete to: " << server_ip_ << ":" << server_port_
|
| - << " ";
|
| - }
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Connecting to server: " << server_ip_ << ":" << server_port_
|
| - << " ";
|
| - } else {
|
| - // If fd != -1 then we are initializing a connection that has just been
|
| - // accepted from the listen socket.
|
| - connection_complete_ = true;
|
| - if (epoll_server_ && registered_in_epoll_server_ && fd_ != -1) {
|
| - epoll_server_->UnregisterFD(fd_);
|
| - }
|
| - if (fd_ != -1) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Closing pre-existing fd";
|
| - close(fd_);
|
| - fd_ = -1;
|
| - }
|
| -
|
| - fd_ = fd;
|
| - }
|
| -
|
| - registered_in_epoll_server_ = false;
|
| - // Set the last read time here as the idle checker will start from
|
| - // now.
|
| - last_read_time_ = time(NULL);
|
| - initialized_ = true;
|
| -
|
| - connection_pool_ = connection_pool;
|
| - epoll_server_ = epoll_server;
|
| -
|
| - if (sm_interface) {
|
| - sm_interface_ = sm_interface;
|
| - protocol_detected_ = true;
|
| - }
|
| -
|
| - read_buffer_.Clear();
|
| -
|
| - epoll_server_->RegisterFD(fd_, this, EPOLLIN | EPOLLOUT | EPOLLET);
|
| -
|
| - if (use_ssl) {
|
| - ssl_ = CreateSSLContext(ssl_state_->ssl_ctx);
|
| - SSL_set_fd(ssl_, fd_);
|
| - PrintSslError();
|
| - }
|
| -}
|
| -
|
| -void SMConnection::CorkSocket() {
|
| - int state = 1;
|
| - int rv = setsockopt(fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
|
| - if (rv < 0)
|
| - VLOG(1) << "setsockopt(CORK): " << errno;
|
| -}
|
| -
|
| -void SMConnection::UncorkSocket() {
|
| - int state = 0;
|
| - int rv = setsockopt(fd_, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
|
| - if (rv < 0)
|
| - VLOG(1) << "setsockopt(CORK): " << errno;
|
| -}
|
| -
|
| -int SMConnection::Send(const char* data, int len, int flags) {
|
| - int rv = 0;
|
| - CorkSocket();
|
| - if (ssl_) {
|
| - ssize_t bytes_written = 0;
|
| - // Write smallish chunks to SSL so that we don't have large
|
| - // multi-packet TLS records to receive before being able to handle
|
| - // the data. We don't have to be too careful here, because our data
|
| - // frames are already getting chunked appropriately, and those are
|
| - // the most likely "big" frames.
|
| - while (len > 0) {
|
| - const int kMaxTLSRecordSize = 1500;
|
| - const char* ptr = &(data[bytes_written]);
|
| - int chunksize = std::min(len, kMaxTLSRecordSize);
|
| - rv = SSL_write(ssl_, ptr, chunksize);
|
| - VLOG(2) << "SSLWrite(" << chunksize << " bytes): " << rv;
|
| - if (rv <= 0) {
|
| - switch (SSL_get_error(ssl_, rv)) {
|
| - case SSL_ERROR_WANT_READ:
|
| - case SSL_ERROR_WANT_WRITE:
|
| - case SSL_ERROR_WANT_ACCEPT:
|
| - case SSL_ERROR_WANT_CONNECT:
|
| - rv = -2;
|
| - break;
|
| - default:
|
| - PrintSslError();
|
| - break;
|
| - }
|
| - break;
|
| - }
|
| - bytes_written += rv;
|
| - len -= rv;
|
| - if (rv != chunksize)
|
| - break; // If we couldn't write everything, we're implicitly stalled
|
| - }
|
| - // If we wrote some data, return that count. Otherwise
|
| - // return the stall error.
|
| - if (bytes_written > 0)
|
| - rv = bytes_written;
|
| - } else {
|
| - rv = send(fd_, data, len, flags);
|
| - }
|
| - if (!(flags & MSG_MORE))
|
| - UncorkSocket();
|
| - return rv;
|
| -}
|
| -
|
| -void SMConnection::OnRegistration(EpollServer* eps, int fd, int event_mask) {
|
| - registered_in_epoll_server_ = true;
|
| -}
|
| -
|
| -void SMConnection::OnEvent(int fd, EpollEvent* event) {
|
| - events_ |= event->in_events;
|
| - HandleEvents();
|
| - if (events_) {
|
| - event->out_ready_mask = events_;
|
| - events_ = 0;
|
| - }
|
| -}
|
| -
|
| -void SMConnection::OnUnregistration(int fd, bool replaced) {
|
| - registered_in_epoll_server_ = false;
|
| -}
|
| -
|
| -void SMConnection::OnShutdown(EpollServer* eps, int fd) {
|
| - Cleanup("OnShutdown");
|
| - return;
|
| -}
|
| -
|
| -void SMConnection::Cleanup(const char* cleanup) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Cleanup: " << cleanup;
|
| - if (!initialized_)
|
| - return;
|
| - Reset();
|
| - if (connection_pool_)
|
| - connection_pool_->SMConnectionDone(this);
|
| - if (sm_interface_)
|
| - sm_interface_->ResetForNewConnection();
|
| - last_read_time_ = 0;
|
| -}
|
| -
|
| -void SMConnection::HandleEvents() {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Received: " << EpollServer::EventMaskToString(events_).c_str();
|
| -
|
| - if (events_ & EPOLLIN) {
|
| - if (!DoRead())
|
| - goto handle_close_or_error;
|
| - }
|
| -
|
| - if (events_ & EPOLLOUT) {
|
| - // Check if we have connected or not
|
| - if (connection_complete_ == false) {
|
| - int sock_error;
|
| - socklen_t sock_error_len = sizeof(sock_error);
|
| - int ret =
|
| - getsockopt(fd_, SOL_SOCKET, SO_ERROR, &sock_error, &sock_error_len);
|
| - if (ret != 0) {
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "getsockopt error: " << errno << ": " << strerror(errno);
|
| - goto handle_close_or_error;
|
| - }
|
| - if (sock_error == 0) {
|
| - connection_complete_ = true;
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Connection complete to " << server_ip_ << ":"
|
| - << server_port_ << " ";
|
| - } else if (sock_error == EINPROGRESS) {
|
| - return;
|
| - } else {
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "error connecting to server";
|
| - goto handle_close_or_error;
|
| - }
|
| - }
|
| - if (!DoWrite())
|
| - goto handle_close_or_error;
|
| - }
|
| -
|
| - if (events_ & (EPOLLHUP | EPOLLERR)) {
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "!!! Got HUP or ERR";
|
| - goto handle_close_or_error;
|
| - }
|
| - return;
|
| -
|
| - handle_close_or_error:
|
| - Cleanup("HandleEvents");
|
| -}
|
| -
|
| -// Decide if SPDY was negotiated.
|
| -bool SMConnection::WasSpdyNegotiated() {
|
| - if (force_spdy())
|
| - return true;
|
| -
|
| - // If this is an SSL connection, check if NPN specifies SPDY.
|
| - if (ssl_) {
|
| - const unsigned char* npn_proto;
|
| - unsigned int npn_proto_len;
|
| - SSL_get0_next_proto_negotiated(ssl_, &npn_proto, &npn_proto_len);
|
| - if (npn_proto_len > 0) {
|
| - std::string npn_proto_str((const char*)npn_proto, npn_proto_len);
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "NPN protocol detected: " << npn_proto_str;
|
| - if (!strncmp(reinterpret_cast<const char*>(npn_proto),
|
| - "spdy/3",
|
| - npn_proto_len)) {
|
| - return true;
|
| - }
|
| - if (!strncmp(reinterpret_cast<const char*>(npn_proto),
|
| - "spdy/4a2",
|
| - npn_proto_len)) {
|
| - return true;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -bool SMConnection::SetupProtocolInterfaces() {
|
| - DCHECK(!protocol_detected_);
|
| - protocol_detected_ = true;
|
| -
|
| - bool spdy_negotiated = WasSpdyNegotiated();
|
| - bool using_ssl = ssl_ != NULL;
|
| -
|
| - if (using_ssl)
|
| - VLOG(1) << (SSL_session_reused(ssl_) ? "Resumed" : "Renegotiated")
|
| - << " SSL Session.";
|
| -
|
| - if (acceptor_->spdy_only_ && !spdy_negotiated) {
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "SPDY proxy only, closing HTTPS connection.";
|
| - return false;
|
| - }
|
| -
|
| - switch (acceptor_->flip_handler_type_) {
|
| - case FLIP_HANDLER_HTTP_SERVER: {
|
| - DCHECK(!spdy_negotiated);
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << (sm_http_interface_ ? "Creating" : "Reusing")
|
| - << " HTTP interface.";
|
| - if (!sm_http_interface_)
|
| - sm_http_interface_ = new HttpSM(this, NULL, memory_cache_, acceptor_);
|
| - sm_interface_ = sm_http_interface_;
|
| - break;
|
| - }
|
| - case FLIP_HANDLER_PROXY: {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << (sm_streamer_interface_ ? "Creating" : "Reusing")
|
| - << " PROXY Streamer interface.";
|
| - if (!sm_streamer_interface_) {
|
| - sm_streamer_interface_ =
|
| - new StreamerSM(this, NULL, epoll_server_, acceptor_);
|
| - sm_streamer_interface_->set_is_request();
|
| - }
|
| - sm_interface_ = sm_streamer_interface_;
|
| - // If spdy is not negotiated, the streamer interface will proxy all
|
| - // data to the origin server.
|
| - if (!spdy_negotiated)
|
| - break;
|
| - }
|
| - // Otherwise fall through into the case below.
|
| - case FLIP_HANDLER_SPDY_SERVER: {
|
| - DCHECK(spdy_negotiated);
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << (sm_spdy_interface_ ? "Creating" : "Reusing")
|
| - << " SPDY interface.";
|
| - if (sm_spdy_interface_)
|
| - sm_spdy_interface_->CreateFramer();
|
| - else
|
| - sm_spdy_interface_ =
|
| - new SpdySM(this, NULL, epoll_server_, memory_cache_, acceptor_);
|
| - sm_interface_ = sm_spdy_interface_;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - CorkSocket();
|
| - if (!sm_interface_->PostAcceptHook())
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool SMConnection::DoRead() {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "DoRead()";
|
| - while (!read_buffer_.Full()) {
|
| - char* bytes;
|
| - int size;
|
| - if (fd_ == -1) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "DoRead(): fd_ == -1. Invalid FD. Returning false";
|
| - return false;
|
| - }
|
| - read_buffer_.GetWritablePtr(&bytes, &size);
|
| - ssize_t bytes_read = 0;
|
| - if (ssl_) {
|
| - bytes_read = SSL_read(ssl_, bytes, size);
|
| - if (bytes_read < 0) {
|
| - int err = SSL_get_error(ssl_, bytes_read);
|
| - switch (err) {
|
| - case SSL_ERROR_WANT_READ:
|
| - case SSL_ERROR_WANT_WRITE:
|
| - case SSL_ERROR_WANT_ACCEPT:
|
| - case SSL_ERROR_WANT_CONNECT:
|
| - events_ &= ~EPOLLIN;
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "DoRead: SSL WANT_XXX: " << err;
|
| - goto done;
|
| - default:
|
| - PrintSslError();
|
| - goto error_or_close;
|
| - }
|
| - }
|
| - } else {
|
| - bytes_read = recv(fd_, bytes, size, MSG_DONTWAIT);
|
| - }
|
| - int stored_errno = errno;
|
| - if (bytes_read == -1) {
|
| - switch (stored_errno) {
|
| - case EAGAIN:
|
| - events_ &= ~EPOLLIN;
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Got EAGAIN while reading";
|
| - goto done;
|
| - case EINTR:
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Got EINTR while reading";
|
| - continue;
|
| - default:
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "While calling recv, got error: "
|
| - << (ssl_ ? "(ssl error)" : strerror(stored_errno));
|
| - goto error_or_close;
|
| - }
|
| - } else if (bytes_read > 0) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "read " << bytes_read
|
| - << " bytes";
|
| - last_read_time_ = time(NULL);
|
| - // If the protocol hasn't been detected yet, set up the handlers
|
| - // we'll need.
|
| - if (!protocol_detected_) {
|
| - if (!SetupProtocolInterfaces()) {
|
| - LOG(ERROR) << "Error setting up protocol interfaces.";
|
| - goto error_or_close;
|
| - }
|
| - }
|
| - read_buffer_.AdvanceWritablePtr(bytes_read);
|
| - if (!DoConsumeReadData())
|
| - goto error_or_close;
|
| - continue;
|
| - } else { // bytes_read == 0
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "0 bytes read with recv call.";
|
| - }
|
| - goto error_or_close;
|
| - }
|
| - done:
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "DoRead done!";
|
| - return true;
|
| -
|
| - error_or_close:
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "DoRead(): error_or_close. "
|
| - << "Cleaning up, then returning false";
|
| - Cleanup("DoRead");
|
| - return false;
|
| -}
|
| -
|
| -bool SMConnection::DoConsumeReadData() {
|
| - char* bytes;
|
| - int size;
|
| - read_buffer_.GetReadablePtr(&bytes, &size);
|
| - while (size != 0) {
|
| - size_t bytes_consumed = sm_interface_->ProcessReadInput(bytes, size);
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "consumed "
|
| - << bytes_consumed << " bytes";
|
| - if (bytes_consumed == 0) {
|
| - break;
|
| - }
|
| - read_buffer_.AdvanceReadablePtr(bytes_consumed);
|
| - if (sm_interface_->MessageFullyRead()) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "HandleRequestFullyRead: Setting EPOLLOUT";
|
| - HandleResponseFullyRead();
|
| - events_ |= EPOLLOUT;
|
| - } else if (sm_interface_->Error()) {
|
| - LOG(ERROR) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Framer error detected: Setting EPOLLOUT: "
|
| - << sm_interface_->ErrorAsString();
|
| - // this causes everything to be closed/cleaned up.
|
| - events_ |= EPOLLOUT;
|
| - return false;
|
| - }
|
| - read_buffer_.GetReadablePtr(&bytes, &size);
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void SMConnection::HandleResponseFullyRead() { sm_interface_->Cleanup(); }
|
| -
|
| -bool SMConnection::DoWrite() {
|
| - size_t bytes_sent = 0;
|
| - int flags = MSG_NOSIGNAL | MSG_DONTWAIT;
|
| - if (fd_ == -1) {
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "DoWrite: fd == -1. Returning false.";
|
| - return false;
|
| - }
|
| - if (output_list_.empty()) {
|
| - VLOG(2) << log_prefix_ << "DoWrite: Output list empty.";
|
| - if (sm_interface_) {
|
| - sm_interface_->GetOutput();
|
| - }
|
| - if (output_list_.empty()) {
|
| - events_ &= ~EPOLLOUT;
|
| - }
|
| - }
|
| - while (!output_list_.empty()) {
|
| - VLOG(2) << log_prefix_
|
| - << "DoWrite: Items in output list: " << output_list_.size();
|
| - if (bytes_sent >= max_bytes_sent_per_dowrite_) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << " byte sent >= max bytes sent per write: Setting EPOLLOUT: "
|
| - << bytes_sent;
|
| - events_ |= EPOLLOUT;
|
| - break;
|
| - }
|
| - if (sm_interface_ && output_list_.size() < 2) {
|
| - sm_interface_->GetOutput();
|
| - }
|
| - DataFrame* data_frame = output_list_.front();
|
| - const char* bytes = data_frame->data;
|
| - int size = data_frame->size;
|
| - bytes += data_frame->index;
|
| - size -= data_frame->index;
|
| - DCHECK_GE(size, 0);
|
| - if (size <= 0) {
|
| - output_list_.pop_front();
|
| - delete data_frame;
|
| - continue;
|
| - }
|
| -
|
| - flags = MSG_NOSIGNAL | MSG_DONTWAIT;
|
| - // Look for a queue size > 1 because |this| frame is remains on the list
|
| - // until it has finished sending.
|
| - if (output_list_.size() > 1) {
|
| - VLOG(2) << log_prefix_ << "Outlist size: " << output_list_.size()
|
| - << ": Adding MSG_MORE flag";
|
| - flags |= MSG_MORE;
|
| - }
|
| - VLOG(2) << log_prefix_ << "Attempting to send " << size << " bytes.";
|
| - ssize_t bytes_written = Send(bytes, size, flags);
|
| - int stored_errno = errno;
|
| - if (bytes_written == -1) {
|
| - switch (stored_errno) {
|
| - case EAGAIN:
|
| - events_ &= ~EPOLLOUT;
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Got EAGAIN while writing";
|
| - goto done;
|
| - case EINTR:
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Got EINTR while writing";
|
| - continue;
|
| - default:
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "While calling send, got error: " << stored_errno << ": "
|
| - << (ssl_ ? "" : strerror(stored_errno));
|
| - goto error_or_close;
|
| - }
|
| - } else if (bytes_written > 0) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "Wrote: " << bytes_written << " bytes";
|
| - data_frame->index += bytes_written;
|
| - bytes_sent += bytes_written;
|
| - continue;
|
| - } else if (bytes_written == -2) {
|
| - // -2 handles SSL_ERROR_WANT_* errors
|
| - events_ &= ~EPOLLOUT;
|
| - goto done;
|
| - }
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "0 bytes written with send call.";
|
| - goto error_or_close;
|
| - }
|
| - done:
|
| - UncorkSocket();
|
| - return true;
|
| -
|
| - error_or_close:
|
| - VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
|
| - << "DoWrite: error_or_close. Returning false "
|
| - << "after cleaning up";
|
| - Cleanup("DoWrite");
|
| - UncorkSocket();
|
| - return false;
|
| -}
|
| -
|
| -void SMConnection::Reset() {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Resetting";
|
| - if (ssl_) {
|
| - SSL_shutdown(ssl_);
|
| - PrintSslError();
|
| - SSL_free(ssl_);
|
| - PrintSslError();
|
| - ssl_ = NULL;
|
| - }
|
| - if (registered_in_epoll_server_) {
|
| - epoll_server_->UnregisterFD(fd_);
|
| - registered_in_epoll_server_ = false;
|
| - }
|
| - if (fd_ >= 0) {
|
| - VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Closing connection";
|
| - close(fd_);
|
| - fd_ = -1;
|
| - }
|
| - read_buffer_.Clear();
|
| - initialized_ = false;
|
| - protocol_detected_ = false;
|
| - events_ = 0;
|
| - for (std::list<DataFrame*>::iterator i = output_list_.begin();
|
| - i != output_list_.end();
|
| - ++i) {
|
| - delete *i;
|
| - }
|
| - output_list_.clear();
|
| -}
|
| -
|
| -// static
|
| -SMConnection* SMConnection::NewSMConnection(EpollServer* epoll_server,
|
| - SSLState* ssl_state,
|
| - MemoryCache* memory_cache,
|
| - FlipAcceptor* acceptor,
|
| - std::string log_prefix) {
|
| - return new SMConnection(
|
| - epoll_server, ssl_state, memory_cache, acceptor, log_prefix);
|
| -}
|
| -
|
| -} // namespace net
|
|
|