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