| 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/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 | |
| 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 | |
| 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 | |
| 76 void HttpSM::HandleHeaderError(BalsaFrame* framer) { HandleError(); } | |
| 77 | |
| 78 void HttpSM::HandleChunkingError(BalsaFrame* framer) { HandleError(); } | |
| 79 | |
| 80 void HttpSM::HandleBodyError(BalsaFrame* framer) { HandleError(); } | |
| 81 | |
| 82 void HttpSM::HandleError() { | |
| 83 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected"; | |
| 84 } | |
| 85 | |
| 86 void HttpSM::AddToOutputOrder(const MemCacheIter& mci) { | |
| 87 output_ordering_.AddToOutputOrder(mci); | |
| 88 } | |
| 89 | |
| 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 | |
| 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 stream_id) { stream_id_ = stream_id; } | |
| 139 | |
| 140 bool HttpSM::Error() const { return http_framer_->Error(); } | |
| 141 | |
| 142 const char* HttpSM::ErrorAsString() const { | |
| 143 return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode()); | |
| 144 } | |
| 145 | |
| 146 void HttpSM::Reset() { | |
| 147 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream " << stream_id_; | |
| 148 http_framer_->Reset(); | |
| 149 } | |
| 150 | |
| 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 | |
| 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 | |
| 178 int HttpSM::PostAcceptHook() { return 1; } | |
| 179 | |
| 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 | |
| 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 | |
| 202 void HttpSM::SendErrorNotFound(uint32 stream_id) { | |
| 203 SendErrorNotFoundImpl(stream_id); | |
| 204 } | |
| 205 | |
| 206 size_t HttpSM::SendSynStream(uint32 stream_id, const BalsaHeaders& headers) { | |
| 207 return 0; | |
| 208 } | |
| 209 | |
| 210 size_t HttpSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) { | |
| 211 return SendSynReplyImpl(stream_id, headers); | |
| 212 } | |
| 213 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| OLD | NEW |