| OLD | NEW |
| (Empty) |
| 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/flip_server/flip_config.h" | |
| 9 #include "net/tools/flip_server/sm_connection.h" | |
| 10 #include "net/tools/flip_server/spdy_util.h" | |
| 11 #include "net/tools/flip_server/url_utilities.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 } | |
| 36 | |
| 37 void HttpSM::ProcessBodyData(const char* input, size_t size) { | |
| 38 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) { | |
| 39 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process Body Data: stream " | |
| 40 << stream_id_ << ": size " << size; | |
| 41 sm_spdy_interface_->SendDataFrame(stream_id_, input, size, 0, false); | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 void HttpSM::ProcessHeaders(const BalsaHeaders& headers) { | |
| 46 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) { | |
| 47 std::string host = | |
| 48 UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string()); | |
| 49 std::string method = headers.request_method().as_string(); | |
| 50 VLOG(1) << ACCEPTOR_CLIENT_IDENT | |
| 51 << "Received Request: " << headers.request_uri().as_string() << " " | |
| 52 << method; | |
| 53 std::string filename = | |
| 54 EncodeURL(headers.request_uri().as_string(), 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_ << ":" << connection_->server_port_ | |
| 60 << " "; | |
| 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) { HandleError(); } | |
| 76 | |
| 77 void HttpSM::HandleChunkingError(BalsaFrame* framer) { HandleError(); } | |
| 78 | |
| 79 void HttpSM::HandleBodyError(BalsaFrame* framer) { HandleError(); } | |
| 80 | |
| 81 void HttpSM::HandleError() { | |
| 82 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected"; | |
| 83 } | |
| 84 | |
| 85 void HttpSM::AddToOutputOrder(const MemCacheIter& mci) { | |
| 86 output_ordering_.AddToOutputOrder(mci); | |
| 87 } | |
| 88 | |
| 89 void HttpSM::InitSMInterface(SMInterface* sm_spdy_interface, | |
| 90 int32_t server_idx) { | |
| 91 sm_spdy_interface_ = sm_spdy_interface; | |
| 92 server_idx_ = server_idx; | |
| 93 } | |
| 94 | |
| 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 | |
| 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 | |
| 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 | |
| 134 bool HttpSM::MessageFullyRead() const { | |
| 135 return http_framer_->MessageFullyRead(); | |
| 136 } | |
| 137 | |
| 138 void HttpSM::SetStreamID(uint32_t stream_id) { | |
| 139 stream_id_ = stream_id; | |
| 140 } | |
| 141 | |
| 142 bool HttpSM::Error() const { return http_framer_->Error(); } | |
| 143 | |
| 144 const char* HttpSM::ErrorAsString() const { | |
| 145 return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode()); | |
| 146 } | |
| 147 | |
| 148 void HttpSM::Reset() { | |
| 149 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream " << stream_id_; | |
| 150 http_framer_->Reset(); | |
| 151 } | |
| 152 | |
| 153 void HttpSM::ResetForNewConnection() { | |
| 154 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) { | |
| 155 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing " | |
| 156 << "to: " << connection_->server_ip_ << ":" | |
| 157 << connection_->server_port_ << " "; | |
| 158 } | |
| 159 // Message has not been fully read, either it is incomplete or the | |
| 160 // server is closing the connection to signal message end. | |
| 161 if (!MessageFullyRead()) { | |
| 162 VLOG(2) << "HTTP response closed before end of file detected. " | |
| 163 << "Sending EOF to spdy."; | |
| 164 sm_spdy_interface_->SendEOF(stream_id_); | |
| 165 } | |
| 166 output_ordering_.Reset(); | |
| 167 http_framer_->Reset(); | |
| 168 if (sm_spdy_interface_) { | |
| 169 sm_spdy_interface_->ResetForNewInterface(server_idx_); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 void HttpSM::Cleanup() { | |
| 174 if (!(acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER)) { | |
| 175 VLOG(2) << "HttpSM Request Fully Read; stream_id: " << stream_id_; | |
| 176 connection_->Cleanup("request complete"); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 int HttpSM::PostAcceptHook() { return 1; } | |
| 181 | |
| 182 void HttpSM::NewStream(uint32_t stream_id, | |
| 183 uint32_t priority, | |
| 184 const std::string& filename) { | |
| 185 MemCacheIter mci; | |
| 186 mci.stream_id = stream_id; | |
| 187 mci.priority = priority; | |
| 188 if (!memory_cache_->AssignFileData(filename, &mci)) { | |
| 189 // error creating new stream. | |
| 190 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound"; | |
| 191 SendErrorNotFound(stream_id); | |
| 192 } else { | |
| 193 AddToOutputOrder(mci); | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 void HttpSM::SendEOF(uint32_t stream_id) { | |
| 198 SendEOFImpl(stream_id); | |
| 199 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) { | |
| 200 sm_spdy_interface_->ResetForNewInterface(server_idx_); | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 void HttpSM::SendErrorNotFound(uint32_t stream_id) { | |
| 205 SendErrorNotFoundImpl(stream_id); | |
| 206 } | |
| 207 | |
| 208 size_t HttpSM::SendSynStream(uint32_t stream_id, const BalsaHeaders& headers) { | |
| 209 return 0; | |
| 210 } | |
| 211 | |
| 212 size_t HttpSM::SendSynReply(uint32_t stream_id, const BalsaHeaders& headers) { | |
| 213 return SendSynReplyImpl(stream_id, headers); | |
| 214 } | |
| 215 | |
| 216 void HttpSM::SendDataFrame(uint32_t stream_id, | |
| 217 const char* data, | |
| 218 int64_t len, | |
| 219 uint32_t flags, | |
| 220 bool compress) { | |
| 221 SendDataFrameImpl(stream_id, data, len, flags, compress); | |
| 222 } | |
| 223 | |
| 224 void HttpSM::SendEOFImpl(uint32_t stream_id) { | |
| 225 DataFrame* df = new DataFrame; | |
| 226 df->data = "0\r\n\r\n"; | |
| 227 df->size = 5; | |
| 228 df->delete_when_done = false; | |
| 229 EnqueueDataFrame(df); | |
| 230 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) { | |
| 231 Reset(); | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 void HttpSM::SendErrorNotFoundImpl(uint32_t stream_id) { | |
| 236 BalsaHeaders my_headers; | |
| 237 my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found"); | |
| 238 my_headers.RemoveAllOfHeader("content-length"); | |
| 239 my_headers.AppendHeader("transfer-encoding", "chunked"); | |
| 240 SendSynReplyImpl(stream_id, my_headers); | |
| 241 SendDataFrame(stream_id, "page not found", 14, 0, false); | |
| 242 SendEOFImpl(stream_id); | |
| 243 output_ordering_.RemoveStreamId(stream_id); | |
| 244 } | |
| 245 | |
| 246 size_t HttpSM::SendSynReplyImpl(uint32_t stream_id, | |
| 247 const BalsaHeaders& headers) { | |
| 248 SimpleBuffer sb; | |
| 249 headers.WriteHeaderAndEndingToBuffer(&sb); | |
| 250 DataFrame* df = new DataFrame; | |
| 251 df->size = sb.ReadableBytes(); | |
| 252 char* buffer = new char[df->size]; | |
| 253 df->data = buffer; | |
| 254 df->delete_when_done = true; | |
| 255 sb.Read(buffer, df->size); | |
| 256 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header " | |
| 257 << stream_id_; | |
| 258 size_t df_size = df->size; | |
| 259 EnqueueDataFrame(df); | |
| 260 return df_size; | |
| 261 } | |
| 262 | |
| 263 size_t HttpSM::SendSynStreamImpl(uint32_t stream_id, | |
| 264 const BalsaHeaders& headers) { | |
| 265 SimpleBuffer sb; | |
| 266 headers.WriteHeaderAndEndingToBuffer(&sb); | |
| 267 DataFrame* df = new DataFrame; | |
| 268 df->size = sb.ReadableBytes(); | |
| 269 char* buffer = new char[df->size]; | |
| 270 df->data = buffer; | |
| 271 df->delete_when_done = true; | |
| 272 sb.Read(buffer, df->size); | |
| 273 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header " | |
| 274 << stream_id_; | |
| 275 size_t df_size = df->size; | |
| 276 EnqueueDataFrame(df); | |
| 277 return df_size; | |
| 278 } | |
| 279 | |
| 280 void HttpSM::SendDataFrameImpl(uint32_t stream_id, | |
| 281 const char* data, | |
| 282 int64_t len, | |
| 283 uint32_t flags, | |
| 284 bool compress) { | |
| 285 char chunk_buf[128]; | |
| 286 snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len); | |
| 287 std::string chunk_description(chunk_buf); | |
| 288 DataFrame* df = new DataFrame; | |
| 289 df->size = chunk_description.size() + len + 2; | |
| 290 char* buffer = new char[df->size]; | |
| 291 df->data = buffer; | |
| 292 df->delete_when_done = true; | |
| 293 memcpy(buffer, chunk_description.data(), chunk_description.size()); | |
| 294 memcpy(buffer + chunk_description.size(), data, len); | |
| 295 memcpy(buffer + chunk_description.size() + len, "\r\n", 2); | |
| 296 EnqueueDataFrame(df); | |
| 297 } | |
| 298 | |
| 299 void HttpSM::EnqueueDataFrame(DataFrame* df) { | |
| 300 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Enqueue data frame: stream " | |
| 301 << stream_id_; | |
| 302 connection_->EnqueueDataFrame(df); | |
| 303 } | |
| 304 | |
| 305 void HttpSM::GetOutput() { | |
| 306 MemCacheIter* mci = output_ordering_.GetIter(); | |
| 307 if (mci == NULL) { | |
| 308 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput: nothing to " | |
| 309 << "output!?: stream " << stream_id_; | |
| 310 return; | |
| 311 } | |
| 312 if (!mci->transformed_header) { | |
| 313 mci->bytes_sent = | |
| 314 SendSynReply(mci->stream_id, *(mci->file_data->headers())); | |
| 315 mci->transformed_header = true; | |
| 316 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed " | |
| 317 << "header stream_id: [" << mci->stream_id << "]"; | |
| 318 return; | |
| 319 } | |
| 320 if (mci->body_bytes_consumed >= mci->file_data->body().size()) { | |
| 321 SendEOF(mci->stream_id); | |
| 322 output_ordering_.RemoveStreamId(mci->stream_id); | |
| 323 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: [" | |
| 324 << mci->stream_id << "]"; | |
| 325 return; | |
| 326 } | |
| 327 size_t num_to_write = | |
| 328 mci->file_data->body().size() - mci->body_bytes_consumed; | |
| 329 if (num_to_write > mci->max_segment_size) | |
| 330 num_to_write = mci->max_segment_size; | |
| 331 | |
| 332 SendDataFrame(mci->stream_id, | |
| 333 mci->file_data->body().data() + mci->body_bytes_consumed, | |
| 334 num_to_write, | |
| 335 0, | |
| 336 true); | |
| 337 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame[" | |
| 338 << mci->stream_id << "]: " << num_to_write; | |
| 339 mci->body_bytes_consumed += num_to_write; | |
| 340 mci->bytes_sent += num_to_write; | |
| 341 } | |
| 342 | |
| 343 } // namespace net | |
| OLD | NEW |