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