diff options
Diffstat (limited to 'src/HttpServerCommand.cc')
| -rw-r--r-- | src/HttpServerCommand.cc | 173 |
1 files changed, 90 insertions, 83 deletions
diff --git a/src/HttpServerCommand.cc b/src/HttpServerCommand.cc index bab3ab29..f39d2fab 100644 --- a/src/HttpServerCommand.cc +++ b/src/HttpServerCommand.cc @@ -54,48 +54,44 @@ #include "MessageDigest.h" #include "message_digest_helper.h" #ifdef ENABLE_WEBSOCKET -# include "WebSocketResponseCommand.h" +#include "WebSocketResponseCommand.h" #endif // ENABLE_WEBSOCKET namespace aria2 { -HttpServerCommand::HttpServerCommand -(cuid_t cuid, - DownloadEngine* e, - const std::shared_ptr<SocketCore>& socket, - bool secure) - : Command(cuid), - e_(e), - socket_(socket), - httpServer_(std::make_shared<HttpServer>(socket)), - writeCheck_(false) +HttpServerCommand::HttpServerCommand(cuid_t cuid, DownloadEngine* e, + const std::shared_ptr<SocketCore>& socket, + bool secure) + : Command(cuid), + e_(e), + socket_(socket), + httpServer_(std::make_shared<HttpServer>(socket)), + writeCheck_(false) { setStatus(Command::STATUS_ONESHOT_REALTIME); e_->addSocketForReadCheck(socket_, this); httpServer_->setSecure(secure); httpServer_->setUsernamePassword(e_->getOption()->get(PREF_RPC_USER), e_->getOption()->get(PREF_RPC_PASSWD)); - if(e_->getOption()->getAsBool(PREF_RPC_ALLOW_ORIGIN_ALL)) { + if (e_->getOption()->getAsBool(PREF_RPC_ALLOW_ORIGIN_ALL)) { httpServer_->setAllowOrigin("*"); } #ifdef HAVE_ZLIB httpServer_->enableGZip(); -#else // !HAVE_ZLIB +#else // !HAVE_ZLIB httpServer_->disableGZip(); #endif // !HAVE_ZLIB checkSocketRecvBuffer(); } -HttpServerCommand::HttpServerCommand -(cuid_t cuid, - const std::shared_ptr<HttpServer>& httpServer, - DownloadEngine* e, - const std::shared_ptr<SocketCore>& socket) - : Command(cuid), - e_(e), - socket_(socket), - httpServer_(httpServer), - writeCheck_(false) +HttpServerCommand::HttpServerCommand( + cuid_t cuid, const std::shared_ptr<HttpServer>& httpServer, + DownloadEngine* e, const std::shared_ptr<SocketCore>& socket) + : Command(cuid), + e_(e), + socket_(socket), + httpServer_(httpServer), + writeCheck_(false) { e_->addSocketForReadCheck(socket_, this); checkSocketRecvBuffer(); @@ -104,17 +100,20 @@ HttpServerCommand::HttpServerCommand HttpServerCommand::~HttpServerCommand() { e_->deleteSocketForReadCheck(socket_, this); - if(writeCheck_) { + if (writeCheck_) { e_->deleteSocketForWriteCheck(socket_, this); } } void HttpServerCommand::checkSocketRecvBuffer() { - if(!httpServer_->getSocketRecvBuffer()->bufferEmpty()) { - setStatus(Command::STATUS_ONESHOT_REALTIME); - e_->setNoWait(true); + if (httpServer_->getSocketRecvBuffer()->bufferEmpty() && + socket_->getRecvBufferedLength() == 0) { + return; } + + setStatus(Command::STATUS_ONESHOT_REALTIME); + e_->setNoWait(true); } #ifdef ENABLE_WEBSOCKET @@ -137,14 +136,17 @@ std::string createWebSocketServerKey(const std::string& clientKey) namespace { int websocketHandshake(const HttpHeader* header) { - if(header->getMethod() != "GET" || - header->find(HttpHeader::SEC_WEBSOCKET_KEY).empty()) { + if (header->getMethod() != "GET" || + header->find(HttpHeader::SEC_WEBSOCKET_KEY).empty()) { return 400; - } else if(header->find(HttpHeader::SEC_WEBSOCKET_VERSION) != "13") { + } + else if (header->find(HttpHeader::SEC_WEBSOCKET_VERSION) != "13") { return 426; - } else if(header->getRequestPath() != "/jsonrpc") { + } + else if (header->getRequestPath() != "/jsonrpc") { return 404; - } else { + } + else { return 101; } } @@ -154,12 +156,13 @@ int websocketHandshake(const HttpHeader* header) void HttpServerCommand::updateWriteCheck() { - if(httpServer_->wantWrite()) { - if(!writeCheck_) { + if (httpServer_->wantWrite()) { + if (!writeCheck_) { writeCheck_ = true; e_->addSocketForWriteCheck(socket_, this); } - } else if(writeCheck_) { + } + else if (writeCheck_) { writeCheck_ = false; e_->deleteSocketForWriteCheck(socket_, this); } @@ -167,20 +170,20 @@ void HttpServerCommand::updateWriteCheck() bool HttpServerCommand::execute() { - if(e_->getRequestGroupMan()->downloadFinished() || e_->isHaltRequested()) { + if (e_->getRequestGroupMan()->downloadFinished() || e_->isHaltRequested()) { return true; } try { - if(socket_->isReadable(0) || - (writeCheck_ && socket_->isWritable(0)) || - !httpServer_->getSocketRecvBuffer()->bufferEmpty()) { + if (socket_->isReadable(0) || (writeCheck_ && socket_->isWritable(0)) || + socket_->getRecvBufferedLength() || + !httpServer_->getSocketRecvBuffer()->bufferEmpty()) { timeoutTimer_ = global::wallclock(); #ifdef ENABLE_SSL - if(httpServer_->getSecure()) { + if (httpServer_->getSecure()) { // tlsAccept() just returns true if handshake has already // finished. - if(!socket_->tlsAccept()) { + if (!socket_->tlsAccept()) { updateWriteCheck(); e_->addCommand(std::unique_ptr<Command>(this)); return false; @@ -188,86 +191,90 @@ bool HttpServerCommand::execute() } #endif // ENABLE_SSL - if(!httpServer_->receiveRequest()) { + if (!httpServer_->receiveRequest()) { updateWriteCheck(); e_->addCommand(std::unique_ptr<Command>(this)); return false; } // CORS preflight request uses OPTIONS method. It is not // restricted by authentication. - if(!httpServer_->authenticate() && - httpServer_->getMethod() != "OPTIONS") { + if (!httpServer_->authenticate() && + httpServer_->getMethod() != "OPTIONS") { httpServer_->disableKeepAlive(); - httpServer_->feedResponse - (401, "WWW-Authenticate: Basic realm=\"aria2\"\r\n"); - e_->addCommand(make_unique<HttpServerResponseCommand> - (getCuid(), httpServer_, e_, socket_)); + httpServer_->feedResponse( + 401, "WWW-Authenticate: Basic realm=\"aria2\"\r\n"); + e_->addCommand(make_unique<HttpServerResponseCommand>( + getCuid(), httpServer_, e_, socket_)); e_->setNoWait(true); return true; } auto& header = httpServer_->getRequestHeader(); - if(header->fieldContains(HttpHeader::UPGRADE, "websocket") && - header->fieldContains(HttpHeader::CONNECTION, "upgrade")) { + if (header->fieldContains(HttpHeader::UPGRADE, "websocket") && + header->fieldContains(HttpHeader::CONNECTION, "upgrade")) { #ifdef ENABLE_WEBSOCKET int status = websocketHandshake(header.get()); - if(status == 101) { - std::string serverKey = - createWebSocketServerKey - (header->find(HttpHeader::SEC_WEBSOCKET_KEY)); - httpServer_->feedUpgradeResponse("websocket", - fmt("Sec-WebSocket-Accept: %s\r\n", - serverKey.c_str())); - e_->addCommand(make_unique<rpc::WebSocketResponseCommand> - (getCuid(), httpServer_, e_, socket_)); - } else { - if(status == 426) { + if (status == 101) { + std::string serverKey = createWebSocketServerKey( + header->find(HttpHeader::SEC_WEBSOCKET_KEY)); + httpServer_->feedUpgradeResponse( + "websocket", + fmt("Sec-WebSocket-Accept: %s\r\n", serverKey.c_str())); + e_->addCommand(make_unique<rpc::WebSocketResponseCommand>( + getCuid(), httpServer_, e_, socket_)); + } + else { + if (status == 426) { httpServer_->feedResponse(426, "Sec-WebSocket-Version: 13\r\n"); - } else { + } + else { httpServer_->feedResponse(status); } - e_->addCommand(make_unique<HttpServerResponseCommand> - (getCuid(), httpServer_, e_, socket_)); + e_->addCommand(make_unique<HttpServerResponseCommand>( + getCuid(), httpServer_, e_, socket_)); } e_->setNoWait(true); return true; -#else // !ENABLE_WEBSOCKET +#else // !ENABLE_WEBSOCKET httpServer_->feedResponse(400); - e_->addCommand(make_unique<HttpServerResponseCommand> - (getCuid(), httpServer_, e_, socket_)); + e_->addCommand(make_unique<HttpServerResponseCommand>( + getCuid(), httpServer_, e_, socket_)); e_->setNoWait(true); return true; #endif // !ENABLE_WEBSOCKET - } else { - if(e_->getOption()->getAsInt(PREF_RPC_MAX_REQUEST_SIZE) < - httpServer_->getContentLength()) { - A2_LOG_INFO - (fmt("Request too long. ContentLength=%" PRId64 "." - " See --rpc-max-request-size option to loose" - " this limitation.", - httpServer_->getContentLength())); + } + else { + if (e_->getOption()->getAsInt(PREF_RPC_MAX_REQUEST_SIZE) < + httpServer_->getContentLength()) { + A2_LOG_INFO(fmt("Request too long. ContentLength=%" PRId64 "." + " See --rpc-max-request-size option to loose" + " this limitation.", + httpServer_->getContentLength())); return true; } - e_->addCommand(make_unique<HttpServerBodyCommand> - (getCuid(), httpServer_, e_, socket_)); + e_->addCommand(make_unique<HttpServerBodyCommand>( + getCuid(), httpServer_, e_, socket_)); e_->setNoWait(true); return true; } - } else { - if(timeoutTimer_.difference(global::wallclock()) >= 30_s) { + } + else { + if (timeoutTimer_.difference(global::wallclock()) >= 30_s) { A2_LOG_INFO("HTTP request timeout."); return true; - } else { + } + else { e_->addCommand(std::unique_ptr<Command>(this)); return false; } } - } catch(RecoverableException& e) { - A2_LOG_INFO_EX(fmt("CUID#%" PRId64 " - Error occurred while reading HTTP request", + } + catch (RecoverableException& e) { + A2_LOG_INFO_EX(fmt("CUID#%" PRId64 + " - Error occurred while reading HTTP request", getCuid()), e); return true; } - } } // namespace aria2 |
