📄 httpserver.cc
字号:
#include <algorithm>#include "httpcommon-inl.h"#include "asyncsocket.h"#include "common.h"#include "httpserver.h"#include "logging.h"#include "socketstream.h"namespace utils_base {///////////////////////////////////////////////////////////////////////////////// HttpServer///////////////////////////////////////////////////////////////////////////////HttpServer::HttpServer() : next_connection_id_(1) {}HttpServer::~HttpServer() { for (ConnectionMap::iterator it = connections_.begin(); it != connections_.end(); ++it) { StreamInterface* stream = it->second->EndProcess(); delete stream; delete it->second; }}intHttpServer::HandleConnection(StreamInterface* stream) { int connection_id = next_connection_id_++; ASSERT(connection_id != HTTP_INVALID_CONNECTION_ID); Connection* connection = new Connection(connection_id, this); connections_.insert(ConnectionMap::value_type(connection_id, connection)); connection->BeginProcess(stream); return connection_id;}voidHttpServer::Respond(HttpTransaction* transaction) { int connection_id = transaction->connection_id(); if (Connection* connection = Find(connection_id)) { connection->Respond(transaction); } else { delete transaction; // We may be tempted to SignalHttpComplete, but that implies that a // connection still exists. }}voidHttpServer::Close(int connection_id, bool force) { if (Connection* connection = Find(connection_id)) { connection->InitiateClose(force); }}voidHttpServer::CloseAll(bool force) { std::list<Connection*> connections; for (ConnectionMap::const_iterator it = connections_.begin(); it != connections_.end(); ++it) { connections.push_back(it->second); } for (std::list<Connection*>::const_iterator it = connections.begin(); it != connections.end(); ++it) { (*it)->InitiateClose(force); }}HttpServer::Connection*HttpServer::Find(int connection_id) { ConnectionMap::iterator it = connections_.find(connection_id); if (it == connections_.end()) return NULL; return it->second;}voidHttpServer::Remove(int connection_id) { ConnectionMap::iterator it = connections_.find(connection_id); if (it == connections_.end()) { ASSERT(false); return; } Connection* connection = it->second; connections_.erase(it); SignalConnectionClosed(this, connection_id, connection->EndProcess()); delete connection;}///////////////////////////////////////////////////////////////////////////////// HttpServer::Connection///////////////////////////////////////////////////////////////////////////////HttpServer::Connection::Connection(int connection_id, HttpServer* server) : connection_id_(connection_id), server_(server), current_(NULL), signalling_(false), close_(false) { }HttpServer::Connection::~Connection() { delete current_;}voidHttpServer::Connection::BeginProcess(StreamInterface* stream) { base_.notify(this); base_.attach(stream); current_ = new HttpTransaction(connection_id_); current_->request()->document.reset(new MemoryStream); if (base_.mode() != HM_CONNECT) base_.recv(current_->request());}StreamInterface*HttpServer::Connection::EndProcess() { base_.notify(NULL); base_.abort(HE_DISCONNECTED); return base_.detach();}voidHttpServer::Connection::Respond(HttpTransaction* transaction) { ASSERT(current_ == NULL); current_ = transaction; if (current_->response()->begin() == current_->response()->end()) { current_->response()->set_error(HC_INTERNAL_SERVER_ERROR); } bool keep_alive = HttpShouldKeepAlive(*transaction->request()); current_->response()->setHeader(HH_CONNECTION, keep_alive ? "Keep-Alive" : "Close", false); close_ = !HttpShouldKeepAlive(*transaction->response()); base_.send(current_->response());}voidHttpServer::Connection::InitiateClose(bool force) { if (!signalling_ && (force || (base_.mode() != HM_SEND))) { server_->Remove(connection_id_); } else { close_ = true; }}//// IHttpNotify Implementation// HttpErrorHttpServer::Connection::onHttpHeaderComplete(bool chunked, size_t& data_size) { if (data_size == SIZE_UNKNOWN) { data_size = 0; } return HE_NONE;}voidHttpServer::Connection::onHttpComplete(HttpMode mode, HttpError err) { if (mode == HM_SEND) { ASSERT(current_ != NULL); signalling_ = true; server_->SignalHttpRequestComplete(server_, current_, err); signalling_ = false; if (close_) { // Force a close err = HE_DISCONNECTED; } } if (err != HE_NONE) { server_->Remove(connection_id_); } else if (mode == HM_CONNECT) { base_.recv(current_->request()); } else if (mode == HM_RECV) { ASSERT(current_ != NULL); // TODO: do we need this? //request_.document_->rewind(); HttpTransaction* transaction = current_; current_ = NULL; server_->SignalHttpRequest(server_, transaction); } else if (mode == HM_SEND) { current_->request()->clear(true); current_->request()->document.reset(new MemoryStream); current_->response()->clear(true); base_.recv(current_->request()); } else { ASSERT(false); }}voidHttpServer::Connection::onHttpClosed(HttpError err) { UNUSED(err); server_->Remove(connection_id_);}///////////////////////////////////////////////////////////////////////////////// HttpListenServer///////////////////////////////////////////////////////////////////////////////HttpListenServer::HttpListenServer(AsyncSocket* listener) : listener_(listener) { listener_->SignalReadEvent.connect(this, &HttpListenServer::OnReadEvent);}HttpListenServer::~HttpListenServer() {}intHttpListenServer::Listen(const SocketAddress& address) { if ((listener_->Bind(address) != SOCKET_ERROR) && (listener_->Listen(5) != SOCKET_ERROR)) return 0; return listener_->GetError();}boolHttpListenServer::GetAddress(SocketAddress& address) { address = listener_->GetLocalAddress(); return !address.IsNil();}voidHttpListenServer::OnReadEvent(AsyncSocket* socket) { ASSERT(socket == listener_); AsyncSocket* incoming = static_cast<AsyncSocket*>(listener_->Accept(NULL)); if (incoming) HandleConnection(new SocketStream(incoming));}///////////////////////////////////////////////////////////////////////////////} // namespace utils_base
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -