1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include <algorithm> 12 13 #include "webrtc/base/httpcommon-inl.h" 14 15 #include "webrtc/base/asyncsocket.h" 16 #include "webrtc/base/common.h" 17 #include "webrtc/base/httpserver.h" 18 #include "webrtc/base/logging.h" 19 #include "webrtc/base/socketstream.h" 20 #include "webrtc/base/thread.h" 21 22 namespace rtc { 23 24 /////////////////////////////////////////////////////////////////////////////// 25 // HttpServer 26 /////////////////////////////////////////////////////////////////////////////// 27 28 HttpServer::HttpServer() : next_connection_id_(1), closing_(false) { 29 } 30 31 HttpServer::~HttpServer() { 32 if (closing_) { 33 LOG(LS_WARNING) << "HttpServer::CloseAll has not completed"; 34 } 35 for (ConnectionMap::iterator it = connections_.begin(); 36 it != connections_.end(); 37 ++it) { 38 StreamInterface* stream = it->second->EndProcess(); 39 delete stream; 40 delete it->second; 41 } 42 } 43 44 int 45 HttpServer::HandleConnection(StreamInterface* stream) { 46 int connection_id = next_connection_id_++; 47 ASSERT(connection_id != HTTP_INVALID_CONNECTION_ID); 48 Connection* connection = new Connection(connection_id, this); 49 connections_.insert(ConnectionMap::value_type(connection_id, connection)); 50 connection->BeginProcess(stream); 51 return connection_id; 52 } 53 54 void 55 HttpServer::Respond(HttpServerTransaction* transaction) { 56 int connection_id = transaction->connection_id(); 57 if (Connection* connection = Find(connection_id)) { 58 connection->Respond(transaction); 59 } else { 60 delete transaction; 61 // We may be tempted to SignalHttpComplete, but that implies that a 62 // connection still exists. 63 } 64 } 65 66 void 67 HttpServer::Close(int connection_id, bool force) { 68 if (Connection* connection = Find(connection_id)) { 69 connection->InitiateClose(force); 70 } 71 } 72 73 void 74 HttpServer::CloseAll(bool force) { 75 if (connections_.empty()) { 76 SignalCloseAllComplete(this); 77 return; 78 } 79 closing_ = true; 80 std::list<Connection*> connections; 81 for (ConnectionMap::const_iterator it = connections_.begin(); 82 it != connections_.end(); ++it) { 83 connections.push_back(it->second); 84 } 85 for (std::list<Connection*>::const_iterator it = connections.begin(); 86 it != connections.end(); ++it) { 87 (*it)->InitiateClose(force); 88 } 89 } 90 91 HttpServer::Connection* 92 HttpServer::Find(int connection_id) { 93 ConnectionMap::iterator it = connections_.find(connection_id); 94 if (it == connections_.end()) 95 return NULL; 96 return it->second; 97 } 98 99 void 100 HttpServer::Remove(int connection_id) { 101 ConnectionMap::iterator it = connections_.find(connection_id); 102 if (it == connections_.end()) { 103 ASSERT(false); 104 return; 105 } 106 Connection* connection = it->second; 107 connections_.erase(it); 108 SignalConnectionClosed(this, connection_id, connection->EndProcess()); 109 delete connection; 110 if (closing_ && connections_.empty()) { 111 closing_ = false; 112 SignalCloseAllComplete(this); 113 } 114 } 115 116 /////////////////////////////////////////////////////////////////////////////// 117 // HttpServer::Connection 118 /////////////////////////////////////////////////////////////////////////////// 119 120 HttpServer::Connection::Connection(int connection_id, HttpServer* server) 121 : connection_id_(connection_id), server_(server), 122 current_(NULL), signalling_(false), close_(false) { 123 } 124 125 HttpServer::Connection::~Connection() { 126 // It's possible that an object hosted inside this transaction signalled 127 // an event which caused the connection to close. 128 Thread::Current()->Dispose(current_); 129 } 130 131 void 132 HttpServer::Connection::BeginProcess(StreamInterface* stream) { 133 base_.notify(this); 134 base_.attach(stream); 135 current_ = new HttpServerTransaction(connection_id_); 136 if (base_.mode() != HM_CONNECT) 137 base_.recv(¤t_->request); 138 } 139 140 StreamInterface* 141 HttpServer::Connection::EndProcess() { 142 base_.notify(NULL); 143 base_.abort(HE_DISCONNECTED); 144 return base_.detach(); 145 } 146 147 void 148 HttpServer::Connection::Respond(HttpServerTransaction* transaction) { 149 ASSERT(current_ == NULL); 150 current_ = transaction; 151 if (current_->response.begin() == current_->response.end()) { 152 current_->response.set_error(HC_INTERNAL_SERVER_ERROR); 153 } 154 bool keep_alive = HttpShouldKeepAlive(current_->request); 155 current_->response.setHeader(HH_CONNECTION, 156 keep_alive ? "Keep-Alive" : "Close", 157 false); 158 close_ = !HttpShouldKeepAlive(current_->response); 159 base_.send(¤t_->response); 160 } 161 162 void 163 HttpServer::Connection::InitiateClose(bool force) { 164 bool request_in_progress = (HM_SEND == base_.mode()) || (NULL == current_); 165 if (!signalling_ && (force || !request_in_progress)) { 166 server_->Remove(connection_id_); 167 } else { 168 close_ = true; 169 } 170 } 171 172 // 173 // IHttpNotify Implementation 174 // 175 176 HttpError 177 HttpServer::Connection::onHttpHeaderComplete(bool chunked, size_t& data_size) { 178 if (data_size == SIZE_UNKNOWN) { 179 data_size = 0; 180 } 181 ASSERT(current_ != NULL); 182 bool custom_document = false; 183 server_->SignalHttpRequestHeader(server_, current_, &custom_document); 184 if (!custom_document) { 185 current_->request.document.reset(new MemoryStream); 186 } 187 return HE_NONE; 188 } 189 190 void 191 HttpServer::Connection::onHttpComplete(HttpMode mode, HttpError err) { 192 if (mode == HM_SEND) { 193 ASSERT(current_ != NULL); 194 signalling_ = true; 195 server_->SignalHttpRequestComplete(server_, current_, err); 196 signalling_ = false; 197 if (close_) { 198 // Force a close 199 err = HE_DISCONNECTED; 200 } 201 } 202 if (err != HE_NONE) { 203 server_->Remove(connection_id_); 204 } else if (mode == HM_CONNECT) { 205 base_.recv(¤t_->request); 206 } else if (mode == HM_RECV) { 207 ASSERT(current_ != NULL); 208 // TODO: do we need this? 209 //request_.document_->rewind(); 210 HttpServerTransaction* transaction = current_; 211 current_ = NULL; 212 server_->SignalHttpRequest(server_, transaction); 213 } else if (mode == HM_SEND) { 214 Thread::Current()->Dispose(current_->response.document.release()); 215 current_->request.clear(true); 216 current_->response.clear(true); 217 base_.recv(¤t_->request); 218 } else { 219 ASSERT(false); 220 } 221 } 222 223 void 224 HttpServer::Connection::onHttpClosed(HttpError err) { 225 RTC_UNUSED(err); 226 server_->Remove(connection_id_); 227 } 228 229 /////////////////////////////////////////////////////////////////////////////// 230 // HttpListenServer 231 /////////////////////////////////////////////////////////////////////////////// 232 233 HttpListenServer::HttpListenServer() { 234 SignalConnectionClosed.connect(this, &HttpListenServer::OnConnectionClosed); 235 } 236 237 HttpListenServer::~HttpListenServer() { 238 } 239 240 int HttpListenServer::Listen(const SocketAddress& address) { 241 AsyncSocket* sock = 242 Thread::Current()->socketserver()->CreateAsyncSocket(address.family(), 243 SOCK_STREAM); 244 if (!sock) { 245 return SOCKET_ERROR; 246 } 247 listener_.reset(sock); 248 listener_->SignalReadEvent.connect(this, &HttpListenServer::OnReadEvent); 249 if ((listener_->Bind(address) != SOCKET_ERROR) && 250 (listener_->Listen(5) != SOCKET_ERROR)) 251 return 0; 252 return listener_->GetError(); 253 } 254 255 bool HttpListenServer::GetAddress(SocketAddress* address) const { 256 if (!listener_) { 257 return false; 258 } 259 *address = listener_->GetLocalAddress(); 260 return !address->IsNil(); 261 } 262 263 void HttpListenServer::StopListening() { 264 if (listener_) { 265 listener_->Close(); 266 } 267 } 268 269 void HttpListenServer::OnReadEvent(AsyncSocket* socket) { 270 ASSERT(socket == listener_.get()); 271 ASSERT(listener_); 272 AsyncSocket* incoming = listener_->Accept(NULL); 273 if (incoming) { 274 StreamInterface* stream = new SocketStream(incoming); 275 //stream = new LoggingAdapter(stream, LS_VERBOSE, "HttpServer", false); 276 HandleConnection(stream); 277 } 278 } 279 280 void HttpListenServer::OnConnectionClosed(HttpServer* server, 281 int connection_id, 282 StreamInterface* stream) { 283 Thread::Current()->Dispose(stream); 284 } 285 286 /////////////////////////////////////////////////////////////////////////////// 287 288 } // namespace rtc 289