• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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