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