1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/tools/flip_server/http_interface.h"
6
7 #include "net/tools/dump_cache/url_utilities.h"
8 #include "net/tools/flip_server/balsa_frame.h"
9 #include "net/tools/flip_server/flip_config.h"
10 #include "net/tools/flip_server/sm_connection.h"
11 #include "net/tools/flip_server/spdy_util.h"
12
13 namespace net {
14
HttpSM(SMConnection * connection,SMInterface * sm_spdy_interface,EpollServer * epoll_server,MemoryCache * memory_cache,FlipAcceptor * acceptor)15 HttpSM::HttpSM(SMConnection* connection,
16 SMInterface* sm_spdy_interface,
17 EpollServer* epoll_server,
18 MemoryCache* memory_cache,
19 FlipAcceptor* acceptor)
20 : seq_num_(0),
21 http_framer_(new BalsaFrame),
22 stream_id_(0),
23 server_idx_(-1),
24 connection_(connection),
25 sm_spdy_interface_(sm_spdy_interface),
26 output_list_(connection->output_list()),
27 output_ordering_(connection),
28 memory_cache_(connection->memory_cache()),
29 acceptor_(acceptor) {
30 http_framer_->set_balsa_visitor(this);
31 http_framer_->set_balsa_headers(&headers_);
32 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY)
33 http_framer_->set_is_request(false);
34 }
~HttpSM()35 HttpSM::~HttpSM() {
36 Reset();
37 delete http_framer_;
38 }
39
ProcessBodyData(const char * input,size_t size)40 void HttpSM::ProcessBodyData(const char *input, size_t size) {
41 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
42 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process Body Data: stream "
43 << stream_id_ << ": size " << size;
44 sm_spdy_interface_->SendDataFrame(stream_id_, input, size, 0, false);
45 }
46 }
47
ProcessHeaders(const BalsaHeaders & headers)48 void HttpSM::ProcessHeaders(const BalsaHeaders& headers) {
49 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
50 std::string host =
51 UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string());
52 std::string method = headers.request_method().as_string();
53 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Received Request: "
54 << headers.request_uri().as_string() << " " << method;
55 std::string filename = EncodeURL(headers.request_uri().as_string(),
56 host, method);
57 NewStream(stream_id_, 0, filename);
58 stream_id_ += 2;
59 } else {
60 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Received Response from "
61 << connection_->server_ip_ << ":"
62 << connection_->server_port_ << " ";
63 sm_spdy_interface_->SendSynReply(stream_id_, headers);
64 }
65 }
66
MessageDone()67 void HttpSM::MessageDone() {
68 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
69 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone. Sending EOF: "
70 << "stream " << stream_id_;
71 sm_spdy_interface_->SendEOF(stream_id_);
72 } else {
73 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone.";
74 }
75 }
76
HandleHeaderError(BalsaFrame * framer)77 void HttpSM::HandleHeaderError(BalsaFrame* framer) {
78 HandleError();
79 }
80
HandleChunkingError(BalsaFrame * framer)81 void HttpSM::HandleChunkingError(BalsaFrame* framer) {
82 HandleError();
83 }
84
HandleBodyError(BalsaFrame * framer)85 void HttpSM::HandleBodyError(BalsaFrame* framer) {
86 HandleError();
87 }
88
HandleError()89 void HttpSM::HandleError() {
90 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
91 }
92
AddToOutputOrder(const MemCacheIter & mci)93 void HttpSM::AddToOutputOrder(const MemCacheIter& mci) {
94 output_ordering_.AddToOutputOrder(mci);
95 }
96
SendOKResponse(uint32 stream_id,std::string * output)97 void HttpSM::SendOKResponse(uint32 stream_id, std::string* output) {
98 SendOKResponseImpl(stream_id, output);
99 }
100
InitSMInterface(SMInterface * sm_spdy_interface,int32 server_idx)101 void HttpSM::InitSMInterface(SMInterface* sm_spdy_interface,
102 int32 server_idx) {
103 sm_spdy_interface_ = sm_spdy_interface;
104 server_idx_ = server_idx;
105 }
106
InitSMConnection(SMConnectionPoolInterface * connection_pool,SMInterface * sm_interface,EpollServer * epoll_server,int fd,std::string server_ip,std::string server_port,std::string remote_ip,bool use_ssl)107 void HttpSM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
108 SMInterface* sm_interface,
109 EpollServer* epoll_server,
110 int fd,
111 std::string server_ip,
112 std::string server_port,
113 std::string remote_ip,
114 bool use_ssl) {
115 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Initializing server "
116 << "connection.";
117 connection_->InitSMConnection(connection_pool,
118 sm_interface,
119 epoll_server,
120 fd,
121 server_ip,
122 server_port,
123 remote_ip,
124 use_ssl);
125 }
126
ProcessReadInput(const char * data,size_t len)127 size_t HttpSM::ProcessReadInput(const char* data, size_t len) {
128 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process read input: stream "
129 << stream_id_;
130 return http_framer_->ProcessInput(data, len);
131 }
132
ProcessWriteInput(const char * data,size_t len)133 size_t HttpSM::ProcessWriteInput(const char* data, size_t len) {
134 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process write input: size "
135 << len << ": stream " << stream_id_;
136 char * dataPtr = new char[len];
137 memcpy(dataPtr, data, len);
138 DataFrame* data_frame = new DataFrame;
139 data_frame->data = (const char *)dataPtr;
140 data_frame->size = len;
141 data_frame->delete_when_done = true;
142 connection_->EnqueueDataFrame(data_frame);
143 return len;
144 }
145
MessageFullyRead() const146 bool HttpSM::MessageFullyRead() const {
147 return http_framer_->MessageFullyRead();
148 }
149
SetStreamID(uint32 stream_id)150 void HttpSM::SetStreamID(uint32 stream_id) {
151 stream_id_ = stream_id;
152 }
153
Error() const154 bool HttpSM::Error() const {
155 return http_framer_->Error();
156 }
157
ErrorAsString() const158 const char* HttpSM::ErrorAsString() const {
159 return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode());
160 }
161
Reset()162 void HttpSM::Reset() {
163 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream "
164 << stream_id_;
165 http_framer_->Reset();
166 }
167
ResetForNewConnection()168 void HttpSM::ResetForNewConnection() {
169 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
170 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
171 << "to: " << connection_->server_ip_ << ":"
172 << connection_->server_port_ << " ";
173 }
174 // Message has not been fully read, either it is incomplete or the
175 // server is closing the connection to signal message end.
176 if (!MessageFullyRead()) {
177 VLOG(2) << "HTTP response closed before end of file detected. "
178 << "Sending EOF to spdy.";
179 sm_spdy_interface_->SendEOF(stream_id_);
180 }
181 seq_num_ = 0;
182 output_ordering_.Reset();
183 http_framer_->Reset();
184 if (sm_spdy_interface_) {
185 sm_spdy_interface_->ResetForNewInterface(server_idx_);
186 }
187 }
188
Cleanup()189 void HttpSM::Cleanup() {
190 if (!(acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER)) {
191 VLOG(2) << "HttpSM Request Fully Read; stream_id: " << stream_id_;
192 connection_->Cleanup("request complete");
193 }
194 }
195
PostAcceptHook()196 int HttpSM::PostAcceptHook() {
197 return 1;
198 }
199
NewStream(uint32 stream_id,uint32 priority,const std::string & filename)200 void HttpSM::NewStream(uint32 stream_id, uint32 priority,
201 const std::string& filename) {
202 MemCacheIter mci;
203 mci.stream_id = stream_id;
204 mci.priority = priority;
205 if (!memory_cache_->AssignFileData(filename, &mci)) {
206 // error creating new stream.
207 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound";
208 SendErrorNotFound(stream_id);
209 } else {
210 AddToOutputOrder(mci);
211 }
212 }
213
SendEOF(uint32 stream_id)214 void HttpSM::SendEOF(uint32 stream_id) {
215 SendEOFImpl(stream_id);
216 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
217 sm_spdy_interface_->ResetForNewInterface(server_idx_);
218 }
219 }
220
SendErrorNotFound(uint32 stream_id)221 void HttpSM::SendErrorNotFound(uint32 stream_id) {
222 SendErrorNotFoundImpl(stream_id);
223 }
224
SendSynStream(uint32 stream_id,const BalsaHeaders & headers)225 size_t HttpSM::SendSynStream(uint32 stream_id, const BalsaHeaders& headers) {
226 return 0;
227 }
228
SendSynReply(uint32 stream_id,const BalsaHeaders & headers)229 size_t HttpSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
230 return SendSynReplyImpl(stream_id, headers);
231 }
232
SendDataFrame(uint32 stream_id,const char * data,int64 len,uint32 flags,bool compress)233 void HttpSM::SendDataFrame(uint32 stream_id, const char* data, int64 len,
234 uint32 flags, bool compress) {
235 SendDataFrameImpl(stream_id, data, len, flags, compress);
236 }
237
SendEOFImpl(uint32 stream_id)238 void HttpSM::SendEOFImpl(uint32 stream_id) {
239 DataFrame* df = new DataFrame;
240 df->data = "0\r\n\r\n";
241 df->size = 5;
242 df->delete_when_done = false;
243 EnqueueDataFrame(df);
244 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
245 Reset();
246 }
247 }
248
SendErrorNotFoundImpl(uint32 stream_id)249 void HttpSM::SendErrorNotFoundImpl(uint32 stream_id) {
250 BalsaHeaders my_headers;
251 my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found");
252 my_headers.RemoveAllOfHeader("content-length");
253 my_headers.AppendHeader("transfer-encoding", "chunked");
254 SendSynReplyImpl(stream_id, my_headers);
255 SendDataFrame(stream_id, "page not found", 14, 0, false);
256 SendEOFImpl(stream_id);
257 output_ordering_.RemoveStreamId(stream_id);
258 }
259
SendOKResponseImpl(uint32 stream_id,std::string * output)260 void HttpSM::SendOKResponseImpl(uint32 stream_id, std::string* output) {
261 BalsaHeaders my_headers;
262 my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
263 my_headers.RemoveAllOfHeader("content-length");
264 my_headers.AppendHeader("transfer-encoding", "chunked");
265 SendSynReplyImpl(stream_id, my_headers);
266 SendDataFrame(stream_id, output->c_str(), output->size(), 0, false);
267 SendEOFImpl(stream_id);
268 output_ordering_.RemoveStreamId(stream_id);
269 }
270
SendSynReplyImpl(uint32 stream_id,const BalsaHeaders & headers)271 size_t HttpSM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
272 SimpleBuffer sb;
273 headers.WriteHeaderAndEndingToBuffer(&sb);
274 DataFrame* df = new DataFrame;
275 df->size = sb.ReadableBytes();
276 char* buffer = new char[df->size];
277 df->data = buffer;
278 df->delete_when_done = true;
279 sb.Read(buffer, df->size);
280 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
281 << stream_id_;
282 size_t df_size = df->size;
283 EnqueueDataFrame(df);
284 return df_size;
285 }
286
SendSynStreamImpl(uint32 stream_id,const BalsaHeaders & headers)287 size_t HttpSM::SendSynStreamImpl(uint32 stream_id,
288 const BalsaHeaders& headers) {
289 SimpleBuffer sb;
290 headers.WriteHeaderAndEndingToBuffer(&sb);
291 DataFrame* df = new DataFrame;
292 df->size = sb.ReadableBytes();
293 char* buffer = new char[df->size];
294 df->data = buffer;
295 df->delete_when_done = true;
296 sb.Read(buffer, df->size);
297 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
298 << stream_id_;
299 size_t df_size = df->size;
300 EnqueueDataFrame(df);
301 return df_size;
302 }
303
SendDataFrameImpl(uint32 stream_id,const char * data,int64 len,uint32 flags,bool compress)304 void HttpSM::SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
305 uint32 flags, bool compress) {
306 char chunk_buf[128];
307 snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len);
308 std::string chunk_description(chunk_buf);
309 DataFrame* df = new DataFrame;
310 df->size = chunk_description.size() + len + 2;
311 char* buffer = new char[df->size];
312 df->data = buffer;
313 df->delete_when_done = true;
314 memcpy(buffer, chunk_description.data(), chunk_description.size());
315 memcpy(buffer + chunk_description.size(), data, len);
316 memcpy(buffer + chunk_description.size() + len, "\r\n", 2);
317 EnqueueDataFrame(df);
318 }
319
EnqueueDataFrame(DataFrame * df)320 void HttpSM::EnqueueDataFrame(DataFrame* df) {
321 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Enqueue data frame: stream "
322 << stream_id_;
323 connection_->EnqueueDataFrame(df);
324 }
325
GetOutput()326 void HttpSM::GetOutput() {
327 MemCacheIter* mci = output_ordering_.GetIter();
328 if (mci == NULL) {
329 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput: nothing to "
330 << "output!?: stream " << stream_id_;
331 return;
332 }
333 if (!mci->transformed_header) {
334 mci->bytes_sent = SendSynReply(mci->stream_id,
335 *(mci->file_data->headers));
336 mci->transformed_header = true;
337 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
338 << "header stream_id: [" << mci->stream_id << "]";
339 return;
340 }
341 if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
342 SendEOF(mci->stream_id);
343 output_ordering_.RemoveStreamId(mci->stream_id);
344 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: ["
345 << mci->stream_id << "]";
346 return;
347 }
348 size_t num_to_write =
349 mci->file_data->body.size() - mci->body_bytes_consumed;
350 if (num_to_write > mci->max_segment_size)
351 num_to_write = mci->max_segment_size;
352
353 SendDataFrame(mci->stream_id,
354 mci->file_data->body.data() + mci->body_bytes_consumed,
355 num_to_write, 0, true);
356 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
357 << mci->stream_id << "]: " << num_to_write;
358 mci->body_bytes_consumed += num_to_write;
359 mci->bytes_sent += num_to_write;
360 }
361
362 } // namespace net
363
364