flip_in_mem_edsm_server.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <dirent.h> 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <linux/tcp.h> // For TCP_NODELAY 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/socket.h> 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/types.h> 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unistd.h> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <openssl/err.h> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <openssl/ssl.h> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <deque> 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <iostream> 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <limits> 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector> 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <list> 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/simple_thread.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h" 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/lock.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_frame_builder.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_framer.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_protocol.h" 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/balsa_enums.h" 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/balsa_frame.h" 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/balsa_headers.h" 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/balsa_visitor_interface.h" 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/buffer_interface.h" 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/create_listener.h" 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/epoll_server.h" 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/other_defines.h" 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/ring_buffer.h" 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/simple_buffer.h" 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/split.h" 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/url_to_filename_encoder.h" 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/url_utilities.h" 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::cerr; 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing std::deque; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::list; 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing std::map; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::ostream; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing std::pair; 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing std::string; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing std::vector; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If set to true, then the server will act as an SSL server for both 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HTTP and SPDY); 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_use_ssl = true; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The name of the cert .pem file); 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring FLAGS_ssl_cert_name = "cert.pem"; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The name of the key .pem file); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring FLAGS_ssl_key_name = "key.pem"; 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The number of responses given before the server closes the 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// connection); 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 FLAGS_response_count_until_close = 1000*1000; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If true, then disables the nagle algorithm); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_no_nagle = true; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The number of times that accept() will be called when the 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// alarm goes off when the accept_using_alarm flag is set to true. 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If set to 0, accept() will be performed until the accept queue 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is completely drained and the accept() call returns an error); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 FLAGS_accepts_per_wake = 0; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The port on which the spdy server listens); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint32 FLAGS_spdy_port = 10040; 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The port on which the http server listens); 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 FLAGS_port = 16002; 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The size of the TCP accept backlog); 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 FLAGS_accept_backlog_size = 1024; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The directory where cache locates); 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring FLAGS_cache_base_dir = "."; 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If true, then encode url to filename); 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_need_to_encode_url = true; 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If set to false a single socket will be used. If set to true 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// then a new socket will be created for each accept thread. 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note that this only works with kernels that support 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SO_REUSEPORT); 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_reuseport = false; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The amount of time the server delays before sending back the 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// reply); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdouble FLAGS_server_think_time_in_s = 0; 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Does the server send X-Subresource headers); 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_use_xsub = false; 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Does the server send X-Associated-Content headers); 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_use_xac = false; 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Does the server advance cwnd by sending no-op packets); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_use_cwnd_opener = false; 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Does the server compress data frames); 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FLAGS_use_compression = false; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::StringPiece; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::SimpleThread; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// using base::Lock; // heh, this isn't in base namespace?! 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// using base::AutoLock; // ditto! 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::BalsaFrame; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::BalsaFrameEnums; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::BalsaHeaders; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::BalsaHeadersEnums; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::BalsaVisitorInterface; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::EpollAlarmCallbackInterface; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::EpollCallbackInterface; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::EpollEvent; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::EpollServer; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::RingBuffer; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::SimpleBuffer; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::SplitStringPieceToVector; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing net::UrlUtilities; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::CONTROL_FLAG_NONE; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::DATA_FLAG_COMPRESSED; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::DATA_FLAG_FIN; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::RST_STREAM; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SYN_REPLY; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SYN_STREAM; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyControlFrame; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyDataFlags; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyDataFrame; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyRstStreamControlFrame; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFrame; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFrameBuilder; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFramer; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyFramerVisitorInterface; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyHeaderBlock; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdyStreamId; 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdySynReplyControlFrame; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing spdy::SpdySynStreamControlFrame; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PrintSslError() { 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char buf[128]; // this buffer must be at least 120 chars long. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int error_num = ERR_get_error(); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (error_num != 0) { 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(INFO)<< ERR_error_string(error_num, buf); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_num = ERR_get_error(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Creates a socket with domain, type and protocol parameters. 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Assigns the return value of socket() to *fd. 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns errno if an error occurs, else returns zero. 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint CreateSocket(int domain, int type, int protocol, int *fd) { 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(fd != NULL); 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *fd = ::socket(domain, type, protocol); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (*fd == -1) ? errno : 0; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Sets an FD to be nonblocking. 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SetNonBlocking(int fd) { 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(fd >= 0); 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fcntl_return = fcntl(fd, F_GETFL, 0); 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK_NE(fcntl_return, -1) 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "error doing fcntl(fd, F_GETFL, 0) fd: " << fd 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " errno=" << errno; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fcntl_return & O_NONBLOCK) 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fcntl_return = fcntl(fd, F_SETFL, fcntl_return | O_NONBLOCK); 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK_NE(fcntl_return, -1) 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "error doing fcntl(fd, F_SETFL, fcntl_return) fd: " << fd 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " errno=" << errno; 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Encode the URL. 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring EncodeURL(string uri, string host, string method) { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!FLAGS_need_to_encode_url) { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mbelshe): if uri is fully qualified, need to strip protocol/host. 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string(method + "_" + uri); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string filename; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (uri[0] == '/') { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // uri is not fully qualified. 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch filename = net::UrlToFilenameEncoder::Encode( 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://" + host + uri, method + "_/"); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch filename = net::UrlToFilenameEncoder::Encode(uri, method + "_/"); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return filename; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct GlobalSSLState { 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_METHOD* ssl_method; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_CTX* ssl_ctx; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottGlobalSSLState* global_ssl_state = NULL; 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SSL stuff 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid spdy_init_ssl(GlobalSSLState* state) { 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_library_init(); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_load_error_strings(); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state->ssl_method = SSLv23_method(); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott state->ssl_ctx = SSL_CTX_new(state->ssl_method); 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!state->ssl_ctx) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Unable to create SSL context"; 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Disable SSLv2 support. 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SSL_CTX_set_options(state->ssl_ctx, SSL_OP_NO_SSLv2); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (SSL_CTX_use_certificate_file(state->ssl_ctx, 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FLAGS_ssl_cert_name.c_str(), 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_FILETYPE_PEM) <= 0) { 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Unable to use cert.pem as SSL cert."; 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (SSL_CTX_use_PrivateKey_file(state->ssl_ctx, 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FLAGS_ssl_key_name.c_str(), 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_FILETYPE_PEM) <= 0) { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Unable to use key.pem as SSL key."; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!SSL_CTX_check_private_key(state->ssl_ctx)) { 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "The cert.pem and key.pem files don't match"; 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSSL* spdy_new_ssl(SSL_CTX* ssl_ctx) { 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL* ssl = SSL_new(ssl_ctx); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_set_accept_state(ssl); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ssl; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kMSS = 1460; 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kInitialDataSendersThreshold = (2 * kMSS) - SpdyFrame::size(); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kNormalSegmentSize = (2 * kMSS) - SpdyFrame::size(); 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass DataFrame { 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* data; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t size; 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool delete_when_done; 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t index; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame() : data(NULL), size(0), delete_when_done(false), index(0) {} 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void MaybeDelete() { 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delete_when_done) { 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete[] data; 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass StoreBodyAndHeadersVisitor: public BalsaVisitorInterface { 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders headers; 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string body; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool error_; 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessBodyInput(const char *input, size_t size) {} 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessBodyData(const char *input, size_t size) { 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott body.append(input, size); 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessHeaderInput(const char *input, size_t size) {} 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessTrailerInput(const char *input, size_t size) {} 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessHeaders(const BalsaHeaders& headers) { 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // nothing to do here-- we're assuming that the BalsaFrame has 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // been handed our headers. 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessRequestFirstLine(const char* line_input, 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t line_length, 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* method_input, 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t method_length, 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* request_uri_input, 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t request_uri_length, 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* version_input, 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t version_length) {} 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessResponseFirstLine(const char *line_input, 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t line_length, 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *version_input, 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t version_length, 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *status_input, 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t status_length, 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *reason_input, 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t reason_length) {} 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessChunkLength(size_t chunk_length) {} 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessChunkExtensions(const char *input, size_t size) {} 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HeaderDone() {} 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void MessageDone() {} 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleHeaderError(BalsaFrame* framer) { HandleError(); } 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleHeaderWarning(BalsaFrame* framer) { HandleError(); } 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleChunkingError(BalsaFrame* framer) { HandleError(); } 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleBodyError(BalsaFrame* framer) { HandleError(); } 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void HandleError() { error_ = true; } 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct FileData { 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void CopyFrom(const FileData& file_data) { 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers = new BalsaHeaders; 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers->CopyFrom(*(file_data.headers)); 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott filename = file_data.filename; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott related_files = file_data.related_files; 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott body = file_data.body; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData(BalsaHeaders* h, const string& b) : headers(h), body(b) {} 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData() {} 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders* headers; 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string filename; 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector< pair<int, string> > related_files; // priority, filename 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string body; 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MemCacheIter { 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter() : 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_data(NULL), 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority(0), 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transformed_header(false), 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott body_bytes_consumed(0), 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott stream_id(0), 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott max_segment_size(kInitialDataSendersThreshold), 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent(0) {} 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit MemCacheIter(FileData* fd) : 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_data(fd), 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority(0), 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transformed_header(false), 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott body_bytes_consumed(0), 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott stream_id(0), 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott max_segment_size(kInitialDataSendersThreshold), 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent(0) {} 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData* file_data; 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int priority; 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool transformed_header; 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t body_bytes_consumed; 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 stream_id; 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 max_segment_size; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t bytes_sent; 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MemoryCache { 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef map<string, FileData> Files; 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Files files_; 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string cwd_; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void CloneFrom(const MemoryCache& mc) { 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (Files::const_iterator i = mc.files_.begin(); 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i != mc.files_.end(); 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i) { 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Files::iterator out_i = 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott files_.insert(make_pair(i->first, FileData())).first; 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott out_i->second.CopyFrom(i->second); 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cwd_ = mc.cwd_; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void AddFiles() { 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << "Adding files!"; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott deque<string> paths; 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cwd_ = FLAGS_cache_base_dir; 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott paths.push_back(cwd_ + "/GET_"); 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DIR* current_dir = NULL; 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!paths.empty()) { 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (current_dir == NULL && !paths.empty()) { 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string current_dir_name = paths.front(); 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Attempting to open dir: \"" << current_dir_name << "\""; 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_dir = opendir(current_dir_name.c_str()); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott paths.pop_front(); 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (current_dir == NULL) { 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott perror("Unable to open directory. "); 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_dir_name.clear(); 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (current_dir) { 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Succeeded opening"; 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (struct dirent* dir_data = readdir(current_dir); 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dir_data != NULL; 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dir_data = readdir(current_dir)) { 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string current_entry_name = 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_dir_name + "/" + dir_data->d_name; 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dir_data->d_type == DT_REG) { 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Found file: " << current_entry_name; 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReadAndStoreFileContents(current_entry_name.c_str()); 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (dir_data->d_type == DT_DIR) { 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Found subdir: " << current_entry_name; 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (string(dir_data->d_name) != "." && 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string(dir_data->d_name) != "..") { 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Adding to search path: " << current_entry_name; 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott paths.push_front(current_entry_name); 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Oops, no data left. Closing dir."; 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott closedir(current_dir); 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott current_dir = NULL; 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ReadToString(const char* filename, string* output) { 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->clear(); 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd = open(filename, 0, "r"); 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd == -1) 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buffer[4096]; 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssize_t read_status = read(fd, buffer, sizeof(buffer)); 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (read_status > 0) { 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->append(buffer, static_cast<size_t>(read_status)); 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_status = read(fd, buffer, sizeof(buffer)); 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (read_status <= 0 && errno == EINTR); 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(fd); 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ReadAndStoreFileContents(const char* filename) { 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StoreBodyAndHeadersVisitor visitor; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaFrame framer; 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer.set_balsa_visitor(&visitor); 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer.set_balsa_headers(&(visitor.headers)); 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string filename_contents; 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReadToString(filename, &filename_contents); 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ugly hack to make everything look like 1.1. 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (filename_contents.find("HTTP/1.0") == 0) 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott filename_contents[7] = '1'; 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t pos = 0; 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t old_pos = 0; 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (true) { 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott old_pos = pos; 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pos += framer.ProcessInput(filename_contents.data() + pos, 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott filename_contents.size() - pos); 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (framer.Error() || pos == old_pos) { 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Unable to make forward progress, or error" 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " framing file: " << filename; 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (framer.Error()) { 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << "********************************************ERROR!"; 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (framer.MessageFullyRead()) { 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If no Content-Length or Transfer-Encoding was captured in the 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // file, then the rest of the data is the body. Many of the captures 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // from within Chrome don't have content-lengths. 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!visitor.body.length()) 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.body = filename_contents.substr(pos); 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.RemoveAllOfHeader("content-length"); 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.RemoveAllOfHeader("transfer-encoding"); 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.RemoveAllOfHeader("connection"); 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.AppendHeader("transfer-encoding", "chunked"); 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.AppendHeader("connection", "keep-alive"); 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Experiment with changing headers for forcing use of cached 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // versions of content. 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe) REMOVE ME 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if 0 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mbelshe) append current date. 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.RemoveAllOfHeader("date"); 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (visitor.headers.HasHeader("expires")) { 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.RemoveAllOfHeader("expires"); 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott visitor.headers.AppendHeader("expires", 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "Fri, 30 Aug, 2019 12:00:00 GMT"); 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders* headers = new BalsaHeaders; 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers->CopyFrom(visitor.headers); 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string filename_stripped = string(filename).substr(cwd_.size() + 1); 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LOG(INFO) << "Adding file (" << visitor.body.length() << " bytes): " 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// << filename_stripped; 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott files_[filename_stripped] = FileData(); 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData& fd = files_[filename_stripped]; 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd = FileData(headers, visitor.body); 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd.filename = string(filename_stripped, 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott filename_stripped.find_first_of('/')); 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (headers->HasHeader("X-Associated-Content")) { 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string content = headers->GetHeader("X-Associated-Content").as_string(); 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector<StringPiece> urls_and_priorities; 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SplitStringPieceToVector(content, "||", &urls_and_priorities, true); 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Examining X-Associated-Content header"; 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (unsigned int i = 0; i < urls_and_priorities.size(); ++i) { 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const StringPiece& url_and_priority_pair = urls_and_priorities[i]; 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector<StringPiece> url_and_priority; 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SplitStringPieceToVector(url_and_priority_pair, "??", 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &url_and_priority, true); 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (url_and_priority.size() >= 2) { 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string priority_string(url_and_priority[0].data(), 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_and_priority[0].size()); 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string filename_string(url_and_priority[1].data(), 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott url_and_priority[1].size()); 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch long priority; 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* last_eaten_char; 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority = strtol(priority_string.c_str(), &last_eaten_char, 0); 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (last_eaten_char == 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority_string.c_str() + priority_string.size()) { 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pair<int, string> entry(priority, filename_string); 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Adding associated content: " << filename_string; 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd.related_files.push_back(entry); 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Called at runtime to update learned headers 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |url| is a url which contains a referrer header. 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |referrer| is the referring URL 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Adds an X-Subresource or X-Associated-Content to |referer| for |url| 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void UpdateHeaders(string referrer, string file_url) { 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!FLAGS_use_xac && !FLAGS_use_xsub) 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string referrer_host_path = 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::UrlToFilenameEncoder::Encode(referrer, "GET_/"); 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData* fd1 = GetFileData(string("GET_") + file_url); 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!fd1) { 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Updating headers for unknown url: " << file_url; 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string url = fd1->headers->GetHeader("X-Original-Url").as_string(); 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string content_type = fd1->headers->GetHeader("Content-Type").as_string(); 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_type.length() == 0) { 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Skipping subresource with unknown content-type"; 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now, lets see if this is the same host or not 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool same_host = (UrlUtilities::GetUrlHost(referrer) == 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UrlUtilities::GetUrlHost(url)); 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is a hacked algorithm for figuring out what priority 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to use with pushed content. 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int priority = 4; 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_type.find("css") != string::npos) 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority = 1; 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (content_type.find("cript") != string::npos) 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority = 1; 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (content_type.find("html") != string::npos) 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority = 2; 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Attempting update for " << referrer_host_path; 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData* fd2 = GetFileData(referrer_host_path); 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd2 != NULL) { 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If they are on the same host, we'll use X-Associated-Content 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string header_name; 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string new_value; 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string delimiter; 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool related_files = false; 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (same_host && FLAGS_use_xac) { 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_name = "X-Associated-Content"; 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char pri_ch = priority + '0'; 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_value = pri_ch + string("??") + url; 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delimiter = "||"; 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott related_files = true; 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!FLAGS_use_xsub) 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_name = "X-Subresource"; 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_value = content_type + "!!" + url; 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delimiter = "!!"; 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd2->headers->HasNonEmptyHeader(header_name)) { 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string existing_header = 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd2->headers->GetHeader(header_name).as_string(); 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (existing_header.find(url) != string::npos) 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; // header already recorded 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't let these lists grow too long for low pri stuff. 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe) We need better algorithms for this. 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (existing_header.length() > 256 && priority > 2) 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_value = existing_header + delimiter + new_value; 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << "Recording " << header_name << " for " << new_value; 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd2->headers->ReplaceOrAppendHeader(header_name, new_value); 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add it to the related files so that it will actually get sent out. 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (related_files) { 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pair<int, string> entry(4, file_url); 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd2->related_files.push_back(entry); 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Failed to update headers:"; 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "FAIL url: " << url; 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "FAIL ref: " << referrer_host_path; 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileData* GetFileData(const string& filename) { 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Files::iterator fi = files_.end(); 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (filename.compare(filename.length() - 5, 5, ".html", 5) == 0) { 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string new_filename(filename.data(), filename.size() - 5); 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_filename += ".http"; 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fi = files_.find(new_filename); 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fi == files_.end()) 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fi = files_.find(filename); 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fi == files_.end()) { 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return &(fi->second); 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool AssignFileData(const string& filename, MemCacheIter* mci) { 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data = GetFileData(filename); 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci->file_data == NULL) { 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Could not find file data for " << filename; 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass NotifierInterface { 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~NotifierInterface() {} 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void Notify() = 0; 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SMInterface { 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual size_t ProcessInput(const char* data, size_t len) = 0; 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool MessageFullyRead() const = 0; 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool Error() const = 0; 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual const char* ErrorAsString() const = 0; 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void Reset() = 0; 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ResetForNewConnection() = 0; 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void PostAcceptHook() = 0; 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void NewStream(uint32 stream_id, uint32 priority, 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string& filename) = 0; 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void SendEOF(uint32 stream_id) = 0; 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void SendErrorNotFound(uint32 stream_id) = 0; 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual size_t SendSynStream(uint32 stream_id, 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const BalsaHeaders& headers) = 0; 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual size_t SendSynReply(uint32 stream_id, 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const BalsaHeaders& headers) = 0; 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void SendDataFrame(uint32 stream_id, const char* data, int64 len, 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 flags, bool compress) = 0; 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void GetOutput() = 0; 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~SMInterface() {} 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SMServerConnection; 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef SMInterface*(SMInterfaceFactory)(SMServerConnection*); 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef list<DataFrame> OutputList; 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SMServerConnection; 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SMServerConnectionPoolInterface { 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~SMServerConnectionPoolInterface() {} 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SMServerConnections will use this: 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void SMServerConnectionDone(SMServerConnection* connection) = 0; 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SMServerConnection: public EpollCallbackInterface, 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public NotifierInterface { 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection(SMInterfaceFactory* sm_interface_factory, 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache, 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server) : 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_(-1), 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_(0), 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_in_epoll_server_(false), 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott initialized_(false), 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_pool_(NULL), 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_(epoll_server), 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_(4096*10), 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory_cache_(memory_cache), 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_(sm_interface_factory(this)), 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch max_bytes_sent_per_dowrite_(4096), 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_(NULL) {} 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd_; 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int events_; 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool registered_in_epoll_server_; 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool initialized_; 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnectionPoolInterface* connection_pool_; 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server_; 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RingBuffer read_buffer_; 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputList output_list_; 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache_; 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMInterface* sm_interface_; 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t max_bytes_sent_per_dowrite_; 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL* ssl_; 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server() { return epoll_server_; } 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputList* output_list() { return &output_list_; } 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache() { return memory_cache_; } 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ReadyToSend() { 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->SetFDReady(fd_, EPOLLIN | EPOLLOUT); 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void EnqueueDataFrame(const DataFrame& df) { 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_list_.push_back(df); 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "EnqueueDataFrame. Setting FD ready."; 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReadyToSend(); 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~SMServerConnection() { 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (initialized()) { 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Reset(); 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static SMServerConnection* NewSMServerConnection(SMInterfaceFactory* smif, 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache, 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server) { 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return new SMServerConnection(smif, memory_cache, epoll_server); 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool initialized() const { return initialized_; } 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void InitSMServerConnection(SMServerConnectionPoolInterface* connection_pool, 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server, 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd) { 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (initialized_) { 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Attempted to initialize already initialized server"; 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (epoll_server_ && registered_in_epoll_server_ && fd_ != -1) { 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->UnregisterFD(fd_); 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd_ != -1) { 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Closing pre-existing fd"; 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(fd_); 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_ = -1; 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_ = fd; 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_in_epoll_server_ = false; 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott initialized_ = true; 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_pool_ = connection_pool; 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_ = epoll_server; 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_->Reset(); 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.Clear(); 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->RegisterFD(fd_, this, EPOLLIN | EPOLLOUT | EPOLLET); 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (global_ssl_state) { 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ssl_ = spdy_new_ssl(global_ssl_state->ssl_ctx); 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_set_fd(ssl_, fd_); 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_->PostAcceptHook(); 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int Send(const char* bytes, int len, int flags) { 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return send(fd_, bytes, len, flags); 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the following are from the EpollCallbackInterface 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnRegistration(EpollServer* eps, int fd, int event_mask) { 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_in_epoll_server_ = true; 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnModification(int fd, int event_mask) { } 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnEvent(int fd, EpollEvent* event) { 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ |= event->in_events; 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleEvents(); 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (events_) { 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event->out_ready_mask = events_; 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ = 0; 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnUnregistration(int fd, bool replaced) { 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_in_epoll_server_ = false; 858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnShutdown(EpollServer* eps, int fd) { 860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cleanup("OnShutdown"); 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void HandleEvents() { 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Received: " << EpollServer::EventMaskToString(events_); 867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (events_ & EPOLLIN) { 868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!DoRead()) 869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto handle_close_or_error; 870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (events_ & EPOLLOUT) { 873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!DoWrite()) 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto handle_close_or_error; 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (events_ & (EPOLLHUP | EPOLLERR)) { 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "!!!! Got HUP or ERR"; 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto handle_close_or_error; 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handle_close_or_error: 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cleanup("HandleEvents"); 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool DoRead() { 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "DoRead()"; 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd_ == -1) { 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "DoRead(): fd_ == -1. Invalid FD. Returning false"; 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!read_buffer_.Full()) { 894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* bytes; 895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int size; 896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.GetWritablePtr(&bytes, &size); 897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssize_t bytes_read = 0; 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_) { 899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_read = SSL_read(ssl_, bytes, size); 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_read = recv(fd_, bytes, size, MSG_DONTWAIT); 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int stored_errno = errno; 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_read == -1) { 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (stored_errno) { 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case EAGAIN: 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ &= ~EPOLLIN; 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Got EAGAIN while reading"; 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto done; 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case EINTR: 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Got EINTR while reading"; 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "While calling recv, got error: " << stored_errno 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " " << strerror(stored_errno); 917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto error_or_close; 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (bytes_read > 0) { 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Read: " << bytes_read << " bytes from fd: " << fd_; 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.AdvanceWritablePtr(bytes_read); 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!DoConsumeReadData()) { 923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto error_or_close; 924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { // bytes_read == 0 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "0 bytes read with recv call."; 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto error_or_close; 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott done: 932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott error_or_close: 935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "DoRead(): error_or_close. Cleaning up, then returning false"; 936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cleanup("DoRead"); 937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool DoConsumeReadData() { 941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* bytes; 942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int size; 943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.GetReadablePtr(&bytes, &size); 944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (size != 0) { 945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t bytes_consumed = sm_interface_->ProcessInput(bytes, size); 946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "consumed: " << bytes_consumed << " from socket fd: " << fd_; 947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_consumed == 0) { 948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.AdvanceReadablePtr(bytes_consumed); 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (sm_interface_->MessageFullyRead()) { 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "HandleRequestFullyRead"; 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleRequestFullyRead(); 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_->Reset(); 955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ |= EPOLLOUT; 956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (sm_interface_->Error()) { 957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Framer error detected: " 958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << sm_interface_->ErrorAsString(); 959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // this causes everything to be closed/cleaned up. 960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ |= EPOLLOUT; 961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.GetReadablePtr(&bytes, &size); 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void WriteResponse() { 969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // this happens asynchronously from separate threads 970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // feeding files into the output buffer. 971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void HandleRequestFullyRead() { 974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Notify() { 977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool DoWrite() { 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t bytes_sent = 0; 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags = MSG_NOSIGNAL | MSG_DONTWAIT; 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd_ == -1) { 983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "DoWrite: fd == -1. Returning false."; 984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (output_list_.empty()) { 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_->GetOutput(); 988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (output_list_.empty()) 989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ &= ~EPOLLOUT; 990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!output_list_.empty()) { 992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_sent >= max_bytes_sent_per_dowrite_) { 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ |= EPOLLOUT; 994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (output_list_.size() < 2) { 997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_->GetOutput(); 998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame& data_frame = output_list_.front(); 1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* bytes = data_frame.data; 1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int size = data_frame.size; 1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes += data_frame.index; 1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size -= data_frame.index; 1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(size, 0); 1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (size <= 0) { 1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_frame.MaybeDelete(); 1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_list_.pop_front(); 1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags = MSG_NOSIGNAL | MSG_DONTWAIT; 1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (output_list_.size() > 1) { 1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags |= MSG_MORE; 1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssize_t bytes_written = 0; 1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_) { 1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_written = SSL_write(ssl_, bytes, size); 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_written = send(fd_, bytes, size, flags); 1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int stored_errno = errno; 1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_written == -1) { 1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (stored_errno) { 1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case EAGAIN: 1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ &= ~EPOLLOUT; 1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << " Got EAGAIN while writing"; 1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto done; 1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case EINTR: 1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << " Got EINTR while writing"; 1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "While calling send, got error: " << stored_errno 1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " " << strerror(stored_errno); 1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto error_or_close; 1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (bytes_written > 0) { 1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Wrote: " << bytes_written << " bytes to socket fd: " 1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << fd_; 1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_frame.index += bytes_written; 1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent += bytes_written; 1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "0 bytes written to socket " << fd_ << " with send call."; 1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott goto error_or_close; 1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott done: 1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott error_or_close: 1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "DoWrite: error_or_close. Returning false after cleaning up"; 1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cleanup("DoWrite"); 1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend ostream& operator<<(ostream& os, const SMServerConnection& c) { 1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott os << &c << "\n"; 1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return os; 1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Reset() { 1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Resetting"; 1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_) { 1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_shutdown(ssl_); 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSL_free(ssl_); 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrintSslError(); 1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (registered_in_epoll_server_) { 1070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->UnregisterFD(fd_); 1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_in_epoll_server_ = false; 1072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd_ >= 0) { 1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Closing connection"; 1075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(fd_); 1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_ = -1; 1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_->ResetForNewConnection(); 1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_buffer_.Clear(); 1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott initialized_ = false; 1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_ = 0; 1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_list_.clear(); 1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Cleanup(const char* cleanup) { 1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Cleaning up: " << cleanup; 1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!initialized_) { 1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Reset(); 1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_pool_->SMServerConnectionDone(this); 1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass OutputOrdering { 1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef list<MemCacheIter> PriorityRing; 1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef map<uint32, PriorityRing> PriorityMap; 1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct PriorityMapPointer { 1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMapPointer(): ring(NULL), alarm_enabled(false) {} 1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityRing* ring; 1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityRing::iterator it; 1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool alarm_enabled; 1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer::AlarmRegToken alarm_token; 1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef map<uint32, PriorityMapPointer> StreamIdToPriorityMap; 1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StreamIdToPriorityMap stream_ids_; 1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMap priority_map_; 1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityRing first_data_senders_; 1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 first_data_senders_threshold_; // when you've passed this, you're no 1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // longer a first_data_sender... 1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* connection_; 1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server_; 1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit OutputOrdering(SMServerConnection* connection) : 1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_threshold_(kInitialDataSendersThreshold), 1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_(connection), 1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_(connection->epoll_server()) { 1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Reset() { 1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!stream_ids_.empty()) { 1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StreamIdToPriorityMap::iterator sitpmi = stream_ids_.begin(); 1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMapPointer& pmp = sitpmi->second; 1130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pmp.alarm_enabled) { 1131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->UnregisterAlarm(pmp.alarm_token); 1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott stream_ids_.erase(sitpmi); 1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority_map_.clear(); 1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_.clear(); 1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool ExistsInPriorityMaps(uint32 stream_id) { 1140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id); 1141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return sitpmi != stream_ids_.end(); 1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct BeginOutputtingAlarm : public EpollAlarmCallbackInterface { 1145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BeginOutputtingAlarm(OutputOrdering* oo, 1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputOrdering::PriorityMapPointer* pmp, 1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const MemCacheIter& mci) : 1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_(oo), pmp_(pmp), mci_(mci), epoll_server_(NULL) {} 1150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 OnAlarm() { 1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnUnregistration(); 1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_->MoveToActive(pmp_, mci_); 1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "ON ALARM! Should now start to output..."; 1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete this; 1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnRegistration(const EpollServer::AlarmRegToken& tok, 1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* eps) { 1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_ = eps; 1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmp_->alarm_token = tok; 1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmp_->alarm_enabled = true; 1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnUnregistration() { 1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmp_->alarm_enabled = false; 1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnShutdown(EpollServer* eps) { 1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnUnregistration(); 1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~BeginOutputtingAlarm() { 1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (epoll_server_ && pmp_->alarm_enabled) 1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->UnregisterAlarm(pmp_->alarm_token); 1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputOrdering* output_ordering_; 1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputOrdering::PriorityMapPointer* pmp_; 1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter mci_; 1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* epoll_server_; 1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void MoveToActive(PriorityMapPointer* pmp, MemCacheIter mci) { 1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) <<"Moving to active!"; 1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_.push_back(mci); 1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmp->ring = &first_data_senders_; 1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmp->it = first_data_senders_.end(); 1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --pmp->it; 1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_->ReadyToSend(); 1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void AddToOutputOrder(const MemCacheIter& mci) { 1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ExistsInPriorityMaps(mci.stream_id)) 1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "OOps, already was inserted here?!"; 1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double think_time_in_s = FLAGS_server_think_time_in_s; 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string x_server_latency = 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mci.file_data->headers->GetHeader("X-Server-Latency").as_string(); 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (x_server_latency.size() != 0) { 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char* endp; 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp); 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (endp != x_server_latency.c_str() + x_server_latency.size()) { 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Unable to understand X-Server-Latency of: " 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << x_server_latency << " for resource: " << mci.file_data->filename; 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch think_time_in_s = tmp_think_time_in_s; 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StreamIdToPriorityMap::iterator sitpmi; 1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sitpmi = stream_ids_.insert( 1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pair<uint32, PriorityMapPointer>(mci.stream_id, 1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMapPointer())).first; 1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMapPointer& pmp = sitpmi->second; 1212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BeginOutputtingAlarm* boa = new BeginOutputtingAlarm(this, &pmp, mci); 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VLOG(2) << "Server think time: " << think_time_in_s; 1215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->RegisterAlarmApproximateDelta( 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch think_time_in_s * 1000000, boa); 1217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SpliceToPriorityRing(PriorityRing::iterator pri) { 1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter& mci = *pri; 1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMap::iterator pmi = priority_map_.find(mci.priority); 1222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pmi == priority_map_.end()) { 1223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmi = priority_map_.insert( 1224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pair<uint32, PriorityRing>(mci.priority, PriorityRing())).first; 1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmi->second.splice(pmi->second.end(), 1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_, 1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pri); 1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(mci.stream_id); 1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sitpmi->second.ring = &(pmi->second); 1232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter* GetIter() { 1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!first_data_senders_.empty()) { 1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter& mci = first_data_senders_.front(); 1237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci.bytes_sent >= first_data_senders_threshold_) { 1238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SpliceToPriorityRing(first_data_senders_.begin()); 1239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_.splice(first_data_senders_.end(), 1241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_, 1242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_data_senders_.begin()); 1243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.max_segment_size = kInitialDataSendersThreshold; 1244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return &mci; 1245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!priority_map_.empty()) { 1248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityRing& first_ring = priority_map_.begin()->second; 1249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (first_ring.empty()) { 1250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott priority_map_.erase(priority_map_.begin()); 1251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 1252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter& mci = first_ring.front(); 1254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_ring.splice(first_ring.end(), 1255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_ring, 1256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_ring.begin()); 1257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.max_segment_size = kNormalSegmentSize; 1258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return &mci; 1259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 1261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void RemoveStreamId(uint32 stream_id) { 1264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id); 1265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (sitpmi == stream_ids_.end()) 1266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PriorityMapPointer& pmp = sitpmi->second; 1268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pmp.alarm_enabled) { 1269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_->UnregisterAlarm(pmp.alarm_token); 1270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pmp.ring->erase(pmp.it); 1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott stream_ids_.erase(sitpmi); 1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 1277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 1279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdySM : public SpdyFramerVisitorInterface, public SMInterface { 1281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint64 seq_num_; 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer* framer_; 1284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* connection_; 1286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputList* output_list_; 1287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputOrdering output_ordering_; 1288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache_; 1289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 next_outgoing_stream_id_; 1290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit SpdySM(SMServerConnection* connection) : 1292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott seq_num_(0), 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_(new SpdyFramer), 1294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_(connection), 1295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_list_(connection->output_list()), 1296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_(connection), 1297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory_cache_(connection->memory_cache()), 1298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_outgoing_stream_id_(2) { 1299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->set_visitor(this); 1300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnError(SpdyFramer* framer) { 1303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* do nothing with this right now */ 1304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnControl(const SpdyControlFrame* frame) { 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock headers; 1308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool parsed_headers = false; 1309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (frame->type()) { 1310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SYN_STREAM: 1311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdySynStreamControlFrame* syn_stream = 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const SpdySynStreamControlFrame*>(frame); 1314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_headers = framer_->ParseHeaderBlock(frame, &headers); 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VLOG(2) << "OnSyn(" << syn_stream->stream_id() << ")"; 1316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "headers parsed?: " << (parsed_headers? "yes": "no"); 1317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_headers) { 1318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "# headers: " << headers.size(); 1319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (SpdyHeaderBlock::iterator i = headers.begin(); 1321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i != headers.end(); 1322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i) { 1323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << i->first << ": " << i->second; 1324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator method = headers.find("method"); 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator url = headers.find("url"); 1328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (url == headers.end() || method == headers.end()) { 1329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "didn't find method or url or method. Not creating stream"; 1330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator referer = headers.find("referer"); 1334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (referer != headers.end() && method->second == "GET") { 1335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory_cache_->UpdateHeaders(referer->second, url->second); 1336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string uri = UrlUtilities::GetUrlPath(url->second); 1338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string host = UrlUtilities::GetUrlHost(url->second); 1339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string filename = EncodeURL(uri, host, method->second); 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewStream(syn_stream->stream_id(), 1342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const SpdySynStreamControlFrame*>(frame)-> 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch priority(), 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch filename); 1345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SYN_REPLY: 1349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_headers = framer_->ParseHeaderBlock(frame, &headers); 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VLOG(2) << "OnSynReply(" 1351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << reinterpret_cast<const SpdySynReplyControlFrame*>( 1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame)->stream_id() << ")"; 1353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case RST_STREAM: 1355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdyRstStreamControlFrame* rst_stream = 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const SpdyRstStreamControlFrame*>(frame); 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VLOG(2) << "OnRst(" << rst_stream->stream_id() << ")"; 1359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output_ordering_.RemoveStreamId(rst_stream ->stream_id()); 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 1364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(DFATAL) << "Unknown control frame type"; 1365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnStreamFrameData( 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyStreamId stream_id, 1369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* data, size_t len) { 1370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "StreamData(" << stream_id << ", [" << len << "])"; 1371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* do nothing with this right now */ 1372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnLameDuck() { 1374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* do nothing with this right now */ 1375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~SpdySM() { 1379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Reset(); 1380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t ProcessInput(const char* data, size_t len) { 1382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return framer_->ProcessInput(data, len); 1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool MessageFullyRead() const { 1386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return framer_->MessageFullyRead(); 1387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool Error() const { 1390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return framer_->HasError(); 1391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* ErrorAsString() const { 1394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SpdyFramer::ErrorCodeToString(framer_->error_code()); 1395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Reset() {} 1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ResetForNewConnection() { 1399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // seq_num is not cleared, intentionally. 1400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete framer_; 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_ = new SpdyFramer; 1402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->set_visitor(this); 1403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.Reset(); 1404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_outgoing_stream_id_ = 2; 1405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Send a couple of NOOP packets to force opening of cwnd. 1408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void PostAcceptHook() { 1409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!FLAGS_use_cwnd_opener) 1410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We send 2 because that is the initial cwnd, and also because 1413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we have to in order to get an ACK back from the client due to 1414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // delayed ACK. 1415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int kPkts = 2; 1416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Sending NOP FRAMES"; 1418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyControlFrame> frame(SpdyFramer::CreateNopFrame()); 1420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < kPkts; ++i) { 1421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* bytes = frame->data(); 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t size = SpdyFrame::size(); 1423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssize_t bytes_written = connection_->Send(bytes, size, MSG_DONTWAIT); 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (static_cast<size_t>(bytes_written) != size) { 1425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Trouble sending Nop packet! (" << errno << ")"; 1426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (errno == EAGAIN) 1427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void AddAssociatedContent(FileData* file_data) { 1433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (unsigned int i = 0; i < file_data->related_files.size(); ++i) { 1434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pair<int, string>& related_file = file_data->related_files[i]; 1435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter mci; 1436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string filename = "GET_"; 1437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott filename += related_file.second; 1438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!memory_cache_->AssignFileData(filename, &mci)) { 1439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Unable to find associated content for: " << filename; 1440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 1441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(1) << "Adding associated content: " << filename; 1443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.stream_id = next_outgoing_stream_id_; 1444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_outgoing_stream_id_ += 2; 1445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.priority = related_file.first; 1446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToOutputOrder(mci); 1447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void NewStream(uint32 stream_id, uint32 priority, const string& filename) { 1451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter mci; 1452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.stream_id = stream_id; 1453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.priority = priority; 1454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!memory_cache_->AssignFileData(filename, &mci)) { 1455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // error creating new stream. 1456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Sending ErrorNotFound"; 1457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendErrorNotFound(stream_id); 1458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToOutputOrder(mci); 1460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (FLAGS_use_xac) { 1461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddAssociatedContent(mci.file_data); 1462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void AddToOutputOrder(const MemCacheIter& mci) { 1467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.AddToOutputOrder(mci); 1468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendEOF(uint32 stream_id) { 1471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendEOFImpl(stream_id); 1472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendErrorNotFound(uint32 stream_id) { 1475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendErrorNotFoundImpl(stream_id); 1476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendOKResponse(uint32 stream_id, string* output) { 1479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendOKResponseImpl(stream_id, output); 1480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynStream(uint32 stream_id, const BalsaHeaders& headers) { 1483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return SendSynStreamImpl(stream_id, headers); 1484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynReply(uint32 stream_id, const BalsaHeaders& headers) { 1487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return SendSynReplyImpl(stream_id, headers); 1488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendDataFrame(uint32 stream_id, const char* data, int64 len, 1491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 flags, bool compress) { 1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFlags spdy_flags = static_cast<SpdyDataFlags>(flags); 1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SendDataFrameImpl(stream_id, data, len, spdy_flags, compress); 1494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFramer* spdy_framer() { return framer_; } 1497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendEOFImpl(uint32 stream_id) { 1500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame(stream_id, NULL, 0, DATA_FLAG_FIN, false); 1501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Sending EOF: " << stream_id; 1502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott KillStream(stream_id); 1503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendErrorNotFoundImpl(uint32 stream_id) { 1506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders my_headers; 1507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found"); 1508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendSynReplyImpl(stream_id, my_headers); 1509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame(stream_id, "wtf?", 4, DATA_FLAG_FIN, false); 1510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.RemoveStreamId(stream_id); 1511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendOKResponseImpl(uint32 stream_id, string* output) { 1514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders my_headers; 1515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); 1516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendSynReplyImpl(stream_id, my_headers); 1517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame( 1518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott stream_id, output->c_str(), output->size(), DATA_FLAG_FIN, false); 1519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.RemoveStreamId(stream_id); 1520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void KillStream(uint32 stream_id) { 1523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.RemoveStreamId(stream_id); 1524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) { 1527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (BalsaHeaders::const_header_lines_iterator hi = 1528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.header_lines_begin(); 1529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hi != headers.header_lines_end(); 1530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++hi) { 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock::iterator fhi = dest.find(hi->first.as_string()); 1532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fhi == dest.end()) { 1533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dest[hi->first.as_string()] = hi->second.as_string(); 1534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dest[hi->first.as_string()] = ( 1536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string(fhi->second.data(), fhi->second.size()) + "," + 1537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string(hi->second.data(), hi->second.size())); 1538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // These headers have no value 1542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dest.erase("X-Associated-Content"); // TODO(mbelshe): case-sensitive 1543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dest.erase("X-Original-Url"); // TODO(mbelshe): case-sensitive 1544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) { 1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock block; 1548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["method"] = headers.request_method().as_string(); 1549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!headers.HasHeader("status")) 1550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["status"] = headers.response_code().as_string(); 1551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!headers.HasHeader("version")) 1552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["version"] =headers.response_version().as_string(); 1553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (headers.HasHeader("X-Original-Url")) { 1554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string original_url = headers.GetHeader("X-Original-Url").as_string(); 1555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["path"] = UrlUtilities::GetUrlPath(original_url); 1556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["path"] = headers.request_uri().as_string(); 1558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CopyHeaders(block, headers); 1560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySynStreamControlFrame* fsrcf = 1562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch framer_->CreateSynStream(stream_id, 0, 0, CONTROL_FLAG_NONE, true, 1563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &block); 1564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df.size = fsrcf->length() + SpdyFrame::size(); 1566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t df_size = df.size; 1567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = fsrcf->data(); 1568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = true; 1569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Sending SynStreamheader " << stream_id; 1572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return df_size; 1573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) { 1576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyHeaderBlock block; 1577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CopyHeaders(block, headers); 1578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["status"] = headers.response_code().as_string() + " " + 1579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.response_reason_phrase().as_string(); 1580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block["version"] = headers.response_version().as_string(); 1581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySynReplyControlFrame* fsrcf = 1583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->CreateSynReply(stream_id, CONTROL_FLAG_NONE, true, &block); 1584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df.size = fsrcf->length() + SpdyFrame::size(); 1586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t df_size = df.size; 1587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = fsrcf->data(); 1588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = true; 1589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Sending SynReplyheader " << stream_id; 1592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return df_size; 1593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len, 1596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFlags flags, bool compress) { 1597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Force compression off if disabled via command line. 1598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!FLAGS_use_compression) 1599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_COMPRESSED); 1600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(mbelshe): We can't compress here - before going into the 1602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // priority queue. Compression needs to be done 1603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // with late binding. 1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* fdf = framer_->CreateDataFrame(stream_id, data, len, 1605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags); 1606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch df.size = fdf->length() + SpdyFrame::size(); 1608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = fdf->data(); 1609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = true; 1610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Sending data frame" << stream_id << " [" << len << "]" 1613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " shrunk to " << fdf->length(); 1614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void EnqueueDataFrame(const DataFrame& df) { 1617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_->EnqueueDataFrame(df); 1618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void GetOutput() { 1621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (output_list_->size() < 2) { 1622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter* mci = output_ordering_.GetIter(); 1623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci == NULL) { 1624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput: nothing to output!?"; 1625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!mci->transformed_header) { 1628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->transformed_header = true; 1629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput transformed header stream_id: [" 1630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << mci->stream_id << "]"; 1631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((mci->stream_id % 2) == 0) { 1632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // this is a server initiated stream. 1633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ideally, we'd do a 'syn-push' here, instead of a syn-reply. 1634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders headers; 1635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.CopyFrom(*(mci->file_data->headers)); 1636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.ReplaceOrAppendHeader("status", "200"); 1637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.ReplaceOrAppendHeader("version", "http/1.1"); 1638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.SetRequestFirstlineFromStringPieces("PUSH", 1639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data->filename, 1640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ""); 1641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->bytes_sent = SendSynStream(mci->stream_id, headers); 1642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders headers; 1644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.CopyFrom(*(mci->file_data->headers)); 1645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->bytes_sent = SendSynReply(mci->stream_id, headers); 1646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci->body_bytes_consumed >= mci->file_data->body.size()) { 1650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput remove_stream_id: [" << mci->stream_id << "]"; 1651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendEOF(mci->stream_id); 1652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t num_to_write = 1655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data->body.size() - mci->body_bytes_consumed; 1656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (num_to_write > mci->max_segment_size) 1657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_to_write = mci->max_segment_size; 1658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool should_compress = false; 1660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!mci->file_data->headers->HasHeader("content-encoding")) { 1661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci->file_data->headers->HasHeader("content-type")) { 1662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string content_type = 1663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data->headers->GetHeader("content-type").as_string(); 1664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_type.find("image") == content_type.npos) 1665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott should_compress = true; 1666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame(mci->stream_id, 1670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data->body.data() + mci->body_bytes_consumed, 1671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_to_write, 0, should_compress); 1672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput SendDataFrame[" << mci->stream_id 1673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "]: " << num_to_write; 1674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->body_bytes_consumed += num_to_write; 1675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->bytes_sent += num_to_write; 1676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 1679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 1681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HTTPSM : public BalsaVisitorInterface, public SMInterface { 1683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint64 seq_num_; 1685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaFrame* framer_; 1686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders headers_; 1687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 stream_id_; 1688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* connection_; 1690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputList* output_list_; 1691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutputOrdering output_ordering_; 1692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache_; 1693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit HTTPSM(SMServerConnection* connection) : 1695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott seq_num_(0), 1696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_(new BalsaFrame), 1697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott stream_id_(1), 1698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_(connection), 1699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_list_(connection->output_list()), 1700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_(connection), 1701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory_cache_(connection->memory_cache()) { 1702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->set_balsa_visitor(this); 1703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->set_balsa_headers(&headers_); 1704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef map<string, uint32> ClientTokenMap; 1707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessBodyInput(const char *input, size_t size) { 1709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessBodyData(const char *input, size_t size) { 1711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ignoring this. 1712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessHeaderInput(const char *input, size_t size) { 1714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessTrailerInput(const char *input, size_t size) {} 1716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessHeaders(const BalsaHeaders& headers) { 1717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Got new request!"; 1718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string host = UrlUtilities::GetUrlHost( 1719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch headers.GetHeader("Host").as_string()); 1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string method = headers.request_method().as_string(); 1721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string filename = EncodeURL(headers.request_uri().as_string(), host, 1722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method); 1723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewStream(stream_id_, 0, filename); 1724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_id_ += 2; 1725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessRequestFirstLine(const char* line_input, 1727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t line_length, 1728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* method_input, 1729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t method_length, 1730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* request_uri_input, 1731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t request_uri_length, 1732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* version_input, 1733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t version_length) {} 1734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessResponseFirstLine(const char *line_input, 1735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t line_length, 1736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *version_input, 1737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t version_length, 1738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *status_input, 1739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t status_length, 1740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char *reason_input, 1741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t reason_length) {} 1742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessChunkLength(size_t chunk_length) {} 1743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void ProcessChunkExtensions(const char *input, size_t size) {} 1744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HeaderDone() {} 1745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void MessageDone() { 1746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "MessageDone!"; 1747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleHeaderError(BalsaFrame* framer) { 1749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleError(); 1750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleHeaderWarning(BalsaFrame* framer) {} 1752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleChunkingError(BalsaFrame* framer) { 1753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleError(); 1754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void HandleBodyError(BalsaFrame* framer) { 1756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleError(); 1757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void HandleError() { 1760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Error detected"; 1761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~HTTPSM() { 1765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Reset(); 1766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t ProcessInput(const char* data, size_t len) { 1768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return framer_->ProcessInput(data, len); 1769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool MessageFullyRead() const { 1772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return framer_->MessageFullyRead(); 1773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool Error() const { 1776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return framer_->Error(); 1777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* ErrorAsString() const { 1780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return BalsaFrameEnums::ErrorCodeToString(framer_->ErrorCode()); 1781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Reset() { 1784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->Reset(); 1785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ResetForNewConnection() { 1788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott seq_num_ = 0; 1789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.Reset(); 1790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott framer_->Reset(); 1791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void PostAcceptHook() { 1794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void NewStream(uint32 stream_id, uint32 priority, const string& filename) { 1797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter mci; 1798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.stream_id = stream_id; 1799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci.priority = priority; 1800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!memory_cache_->AssignFileData(filename, &mci)) { 1801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendErrorNotFound(stream_id); 1802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToOutputOrder(mci); 1804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void AddToOutputOrder(const MemCacheIter& mci) { 1808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.AddToOutputOrder(mci); 1809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendEOF(uint32 stream_id) { 1812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendEOFImpl(stream_id); 1813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendErrorNotFound(uint32 stream_id) { 1816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendErrorNotFoundImpl(stream_id); 1817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendOKResponse(uint32 stream_id, string* output) { 1820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendOKResponseImpl(stream_id, output); 1821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynStream(uint32 stream_id, const BalsaHeaders& headers) { 1824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 1825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynReply(uint32 stream_id, const BalsaHeaders& headers) { 1828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return SendSynReplyImpl(stream_id, headers); 1829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendDataFrame(uint32 stream_id, const char* data, int64 len, 1832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 flags, bool compress) { 1833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrameImpl(stream_id, data, len, flags, compress); 1834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BalsaFrame* spdy_framer() { return framer_; } 1837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 1839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendEOFImpl(uint32 stream_id) { 1840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = "0\r\n\r\n"; 1842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.size = 5; 1843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = false; 1844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendErrorNotFoundImpl(uint32 stream_id) { 1848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders my_headers; 1849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found"); 1850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott my_headers.RemoveAllOfHeader("content-length"); 1851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch my_headers.AppendHeader("transfer-encoding", "chunked"); 1852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendSynReplyImpl(stream_id, my_headers); 1853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame(stream_id, "wtf?", 4, 0, false); 1854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendEOFImpl(stream_id); 1855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.RemoveStreamId(stream_id); 1856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendOKResponseImpl(uint32 stream_id, string* output) { 1859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders my_headers; 1860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); 1861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott my_headers.RemoveAllOfHeader("content-length"); 1862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch my_headers.AppendHeader("transfer-encoding", "chunked"); 1863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendSynReplyImpl(stream_id, my_headers); 1864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame(stream_id, output->c_str(), output->size(), 0, false); 1865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendEOFImpl(stream_id); 1866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.RemoveStreamId(stream_id); 1867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) { 1870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SimpleBuffer sb; 1871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.WriteHeaderAndEndingToBuffer(&sb); 1872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.size = sb.ReadableBytes(); 1874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* buffer = new char[df.size]; 1875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = buffer; 1876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = true; 1877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sb.Read(buffer, df.size); 1878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "******************Sending HTTP Reply header " << stream_id; 1879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t df_size = df.size; 1880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return df_size; 1882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) { 1885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SimpleBuffer sb; 1886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.WriteHeaderAndEndingToBuffer(&sb); 1887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.size = sb.ReadableBytes(); 1889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* buffer = new char[df.size]; 1890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = buffer; 1891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = true; 1892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sb.Read(buffer, df.size); 1893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "******************Sending HTTP Reply header " << stream_id; 1894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t df_size = df.size; 1895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return df_size; 1897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len, 1900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint32 flags, bool compress) { 1901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char chunk_buf[128]; 1902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len); 1903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string chunk_description(chunk_buf); 1904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DataFrame df; 1905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.size = chunk_description.size() + len + 2; 1906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* buffer = new char[df.size]; 1907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.data = buffer; 1908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott df.delete_when_done = true; 1909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(buffer, chunk_description.data(), chunk_description.size()); 1910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(buffer + chunk_description.size(), data, len); 1911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(buffer + chunk_description.size() + len, "\r\n", 2); 1912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnqueueDataFrame(df); 1913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void EnqueueDataFrame(const DataFrame& df) { 1916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott connection_->EnqueueDataFrame(df); 1917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void GetOutput() { 1920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemCacheIter* mci = output_ordering_.GetIter(); 1921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci == NULL) { 1922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput: nothing to output!?"; 1923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!mci->transformed_header) { 1926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->bytes_sent = SendSynReply(mci->stream_id, 1927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *(mci->file_data->headers)); 1928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->transformed_header = true; 1929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput transformed header stream_id: [" 1930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << mci->stream_id << "]"; 1931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (mci->body_bytes_consumed >= mci->file_data->body.size()) { 1934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendEOF(mci->stream_id); 1935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output_ordering_.RemoveStreamId(mci->stream_id); 1936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput remove_stream_id: [" << mci->stream_id << "]"; 1937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t num_to_write = 1940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data->body.size() - mci->body_bytes_consumed; 1941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (num_to_write > mci->max_segment_size) 1942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_to_write = mci->max_segment_size; 1943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SendDataFrame(mci->stream_id, 1944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->file_data->body.data() + mci->body_bytes_consumed, 1945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott num_to_write, 0, true); 1946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "GetOutput SendDataFrame[" << mci->stream_id 1947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "]: " << num_to_write; 1948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->body_bytes_consumed += num_to_write; 1949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mci->bytes_sent += num_to_write; 1950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 1952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 1954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Notification { 1956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit Notification(bool value) : value_(value) {} 1958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Notify() { 1960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock al(lock_); 1961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value_ = true; 1962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool HasBeenNotified() { 1964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AutoLock al(lock_); 1965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return value_; 1966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool value_; 1968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Lock lock_; 1969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 1970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 1972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SMAcceptorThread : public SimpleThread, 1974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public EpollCallbackInterface, 1975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public SMServerConnectionPoolInterface { 1976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer epoll_server_; 1977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int listen_fd_; 1978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int accepts_per_wake_; 1979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector<SMServerConnection*> unused_server_connections_; 1981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector<SMServerConnection*> tmp_unused_server_connections_; 1982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector<SMServerConnection*> allocated_server_connections_; 1983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Notification quitting_; 1984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMInterfaceFactory* sm_interface_factory_; 1985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache_; 1986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 1987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMAcceptorThread(int listen_fd, 1989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int accepts_per_wake, 1990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMInterfaceFactory* smif, 1991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache* memory_cache) : 1992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SimpleThread("SMAcceptorThread"), 1993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott listen_fd_(listen_fd), 1994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott accepts_per_wake_(accepts_per_wake), 1995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott quitting_(false), 1996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_interface_factory_(smif), 1997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory_cache_(memory_cache) { 1998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~SMAcceptorThread() { 2001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (vector<SMServerConnection*>::iterator i = 2002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott allocated_server_connections_.begin(); 2003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i != allocated_server_connections_.end(); 2004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i) { 2005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete *i; 2006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* NewConnection() { 2010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* server = 2011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection::NewSMServerConnection(sm_interface_factory_, 2012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memory_cache_, 2013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &epoll_server_); 2014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott allocated_server_connections_.push_back(server); 2015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << "Making new server: " << server; 2016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return server; 2017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* FindOrMakeNewSMServerConnection() { 2020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (unused_server_connections_.empty()) { 2021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NewConnection(); 2022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* retval = unused_server_connections_.back(); 2024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unused_server_connections_.pop_back(); 2025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return retval; 2026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void InitWorker() { 2030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_.RegisterFD(listen_fd_, this, EPOLLIN | EPOLLET); 2031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void HandleConnection(int client_fd) { 2034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SMServerConnection* server_connection = FindOrMakeNewSMServerConnection(); 2035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (server_connection == NULL) { 2036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Closing " << client_fd; 2037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(client_fd); 2038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 2039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott server_connection->InitSMServerConnection(this, 2041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &epoll_server_, 2042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott client_fd); 2043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void AcceptFromListenFD() { 2046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (accepts_per_wake_ > 0) { 2047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < accepts_per_wake_; ++i) { 2048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct sockaddr address; 2049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socklen_t socklen = sizeof(address); 2050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd = accept(listen_fd_, &address, &socklen); 2051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd == -1) { 2052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "accept fail(" << listen_fd_ << "): " << errno; 2053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 2054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "********************Accepted fd: " << fd << "\n\n\n"; 2056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleConnection(fd); 2057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 2059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (true) { 2060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct sockaddr address; 2061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socklen_t socklen = sizeof(address); 2062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd = accept(listen_fd_, &address, &socklen); 2063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd == -1) { 2064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "accept fail(" << listen_fd_ << "): " << errno; 2065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 2066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "********************Accepted fd: " << fd << "\n\n\n"; 2068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleConnection(fd); 2069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // EpollCallbackInteface virtual functions. 2074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnRegistration(EpollServer* eps, int fd, int event_mask) { } 2075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnModification(int fd, int event_mask) { } 2076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnEvent(int fd, EpollEvent* event) { 2077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event->in_events | EPOLLIN) { 2078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Accepting based upon epoll events"; 2079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AcceptFromListenFD(); 2080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnUnregistration(int fd, bool replaced) { } 2083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnShutdown(EpollServer* eps, int fd) { } 2084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Quit() { 2086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott quitting_.Notify(); 2087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Run() { 2090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (!quitting_.HasBeenNotified()) { 2091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_.set_timeout_in_us(10 * 1000); // 10 ms 2092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott epoll_server_.WaitForEventsAndExecuteCallbacks(); 2093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unused_server_connections_.insert(unused_server_connections_.end(), 2094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_unused_server_connections_.begin(), 2095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_unused_server_connections_.end()); 2096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_unused_server_connections_.clear(); 2097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SMServerConnections will use this: 2101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void SMServerConnectionDone(SMServerConnection* sc) { 2102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << "Done with server connection: " << sc; 2103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_unused_server_connections_.push_back(sc); 2104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 2106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 2108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2109c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSMInterface* NewSpdySM(SMServerConnection* connection) { 2110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new SpdySM(connection); 2111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSMInterface* NewHTTPSM(SMServerConnection* connection) { 2114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return new HTTPSM(connection); 2115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 2118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint CreateListeningSocket(int port, int backlog_size, 2120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool reuseport, bool no_nagle) { 2121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int listening_socket = 0; 2122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char port_buf[256]; 2123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott snprintf(port_buf, sizeof(port_buf), "%d", port); 2124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cerr <<" Attempting to listen on port: " << port_buf << "\n"; 2125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cerr <<" input port: " << port << "\n"; 2126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::CreateListeningSocket("", 2127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott port_buf, 2128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true, 2129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backlog_size, 2130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &listening_socket, 2131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true, 2132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reuseport, 2133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &cerr); 2134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetNonBlocking(listening_socket); 2135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (no_nagle) { 2136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // set SO_REUSEADDR on the listening socket. 2137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int on = 1; 2138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rc; 2139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rc = setsockopt(listening_socket, IPPROTO_TCP, TCP_NODELAY, 2140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<char*>(&on), sizeof(on)); 2141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rc < 0) { 2142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(listening_socket); 2143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "setsockopt() failed fd=" << listening_socket << "\n"; 2144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return listening_socket; 2147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 2150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GotQuitFromStdin() { 2152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make stdin nonblocking. Yes this is done each time. Oh well. 2153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fcntl(0, F_SETFL, O_NONBLOCK); 2154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char c; 2155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string maybequit; 2156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (read(0, &c, 1) > 0) { 2157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott maybequit += c; 2158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (maybequit.size()) { 2160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "scanning string: \"" << maybequit << "\""; 2161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (maybequit.size() > 1 && 2163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (maybequit.c_str()[0] == 'q' || 2164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott maybequit.c_str()[0] == 'Q')); 2165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 2169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* BoolToStr(bool b) { 2171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (b) 2172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return "true"; 2173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return "false"; 2174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 2177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint main(int argc, char**argv) { 2179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool use_ssl = FLAGS_use_ssl; 2180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int response_count_until_close = FLAGS_response_count_until_close; 2181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int spdy_port = FLAGS_spdy_port; 2182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int port = FLAGS_port; 2183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int backlog_size = FLAGS_accept_backlog_size; 2184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool reuseport = FLAGS_reuseport; 2185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool no_nagle = FLAGS_no_nagle; 2186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott double server_think_time_in_s = FLAGS_server_think_time_in_s; 2187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int accepts_per_wake = FLAGS_accepts_per_wake; 2188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int num_threads = 1; 2189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MemoryCache spdy_memory_cache; 2192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_memory_cache.AddFiles(); 2193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemoryCache http_memory_cache; 2195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch http_memory_cache.CloneFrom(spdy_memory_cache); 2196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << 2198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "Starting up with the following state: \n" 2199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " use_ssl: " << use_ssl << "\n" 2200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " response_count_until_close: " << response_count_until_close << "\n" 2201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " port: " << port << "\n" 2202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch " spdy_port: " << spdy_port << "\n" 2203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " backlog_size: " << backlog_size << "\n" 2204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " reuseport: " << BoolToStr(reuseport) << "\n" 2205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " no_nagle: " << BoolToStr(no_nagle) << "\n" 2206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " server_think_time_in_s: " << server_think_time_in_s << "\n" 2207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " accepts_per_wake: " << accepts_per_wake << "\n" 2208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " num_threads: " << num_threads << "\n" 2209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " use_xsub: " << BoolToStr(FLAGS_use_xsub) << "\n" 2210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " use_xac: " << BoolToStr(FLAGS_use_xac) << "\n"; 2211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (use_ssl) { 2213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott global_ssl_state = new GlobalSSLState; 2214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_init_ssl(global_ssl_state); 2215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 2216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott global_ssl_state = NULL; 2217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer epoll_server; 2219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott vector<SMAcceptorThread*> sm_worker_threads_; 2220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 2222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // spdy 2223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int listen_fd = -1; 2224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (reuseport || listen_fd == -1) { 2226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch listen_fd = CreateListeningSocket(spdy_port, backlog_size, 2227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reuseport, no_nagle); 2228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (listen_fd < 0) { 2229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(FATAL) << "Unable to open listening socket on spdy_port: " 2230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << spdy_port; 2231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 2232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(INFO) << "Listening for spdy on port: " << spdy_port; 2233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_.push_back( 2236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new SMAcceptorThread(listen_fd, 2237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott accepts_per_wake, 2238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &NewSpdySM, 2239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &spdy_memory_cache)); 2240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that spdy_memory_cache is not threadsafe, it is merely 2241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // thread compatible. Thus, if ever we are to spawn multiple threads, 2242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we either must make the MemoryCache threadsafe, or use 2243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a separate MemoryCache for each thread. 2244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 2245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The latter is what is currently being done as we spawn 2246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // two threads (one for spdy, one for http). 2247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_.back()->InitWorker(); 2248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_.back()->Start(); 2249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 2252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // http 2253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int listen_fd = -1; 2254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (reuseport || listen_fd == -1) { 2255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott listen_fd = CreateListeningSocket(port, backlog_size, 2256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reuseport, no_nagle); 2257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (listen_fd < 0) { 2258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Unable to open listening socket on port: " << port; 2259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 2260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << "Listening for HTTP on port: " << port; 2261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_.push_back( 2264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new SMAcceptorThread(listen_fd, 2265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott accepts_per_wake, 2266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &NewHTTPSM, 2267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &http_memory_cache)); 2268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that spdy_memory_cache is not threadsafe, it is merely 2269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // thread compatible. Thus, if ever we are to spawn multiple threads, 2270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we either must make the MemoryCache threadsafe, or use 2271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a separate MemoryCache for each thread. 2272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 2273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The latter is what is currently being done as we spawn 2274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // two threads (one for spdy, one for http). 2275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_.back()->InitWorker(); 2276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_.back()->Start(); 2277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (true) { 2280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (GotQuitFromStdin()) { 2281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) { 2282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_[i]->Quit(); 2283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) { 2285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sm_worker_threads_[i]->Join(); 2286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 2288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott usleep(1000*10); // 10 ms 2290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 2291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 2292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2294