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