From dbeac36e5010da871ea80cd72eaa45c02be5e76f Mon Sep 17 00:00:00 2001 From: JAJames Date: Sat, 30 Jan 2016 10:06:19 -0500 Subject: [PATCH] Socket: * Replaced 'closeSocket' function with 'close' and 'shutdown' functions. * Added 'isShutdown' function --- Jupiter/HTTP_Server.cpp | 49 +++++++++++++++++---------------------- Jupiter/IRC_Client.cpp | 6 ++--- Jupiter/SecureSocket.cpp | 27 +++++++++++++-------- Jupiter/SecureSocket.h | 3 ++- Jupiter/Socket.cpp | 34 ++++++++++++++++++++------- Jupiter/Socket.h | 4 +++- Release/Jupiter.lib | Bin 300418 -> 301260 bytes 7 files changed, 71 insertions(+), 52 deletions(-) diff --git a/Jupiter/HTTP_Server.cpp b/Jupiter/HTTP_Server.cpp index ffe8f70..c829319 100644 --- a/Jupiter/HTTP_Server.cpp +++ b/Jupiter/HTTP_Server.cpp @@ -256,7 +256,7 @@ HTTPSession::HTTPSession(Jupiter::Socket &&in_sock) : sock(std::move(in_sock)) HTTPSession::~HTTPSession() { - HTTPSession::sock.closeSocket(); + HTTPSession::sock.setBlocking(true); } // Server::Data struct @@ -267,10 +267,10 @@ struct Jupiter::HTTP::Server::Data Jupiter::ArrayList hosts; Jupiter::ArrayList ports; Jupiter::ArrayList sessions; - std::chrono::milliseconds session_timeout = std::chrono::milliseconds(30000); // TODO: Config variable - std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(30000); // TODO: Config variable + std::chrono::milliseconds session_timeout = std::chrono::milliseconds(2000); // TODO: Config variable + std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(5000); // TODO: Config variable size_t max_request_size = 1024; // TODO: Config variable - bool permit_keept_alive = true; // TODO: Config variable + bool permit_keept_alive = false; // TODO: Config variable /** Foward functions */ void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, Content *in_content); @@ -511,16 +511,10 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) result += Jupiter::StringS::Format("Content-Length: %u" ENDL, content_result->size()); - switch (session.version) - { - default: - case HTTPVersion::HTTP_1_0: - result += "Connection: close"_jrs ENDL; - break; - case HTTPVersion::HTTP_1_1: + if (session.keep_alive) result += "Connection: keep-alive"_jrs ENDL; - break; - } + else + result += "Connection: close"_jrs ENDL; result += "Content-Type: "_jrs; if (content->type == nullptr) @@ -572,16 +566,10 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) result += "Content-Length: 0"_jrs ENDL; - switch (session.version) - { - default: - case HTTPVersion::HTTP_1_0: - result += "Connection: close"_jrs ENDL; - break; - case HTTPVersion::HTTP_1_1: + if (session.keep_alive) result += "Connection: keep-alive"_jrs ENDL; - break; - } + else + result += "Connection: close"_jrs ENDL; result += ENDL ENDL; session.sock.send(result); @@ -615,7 +603,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) { Jupiter::ReferenceString connection_type = line.getWord(1, " "); if (connection_type.equalsi("keep-alive"_jrs)) - session.keep_alive = true; + session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; } } else // command @@ -650,7 +638,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) else if (protocol_str.equalsi("http/1.1"_jrs)) { session.version = HTTPVersion::HTTP_1_1; - session.keep_alive = true; + session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; } } else if (first_token.equals("HEAD"_jrs)) @@ -683,7 +671,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) else if (protocol_str.equalsi("http/1.1"_jrs)) { session.version = HTTPVersion::HTTP_1_1; - session.keep_alive = true; + session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive; } } else @@ -801,9 +789,14 @@ int Jupiter::HTTP::Server::think() { session = Jupiter::HTTP::Server::data_->sessions.get(--index); std::chrono::steady_clock::now(); - if ((std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->keep_alive_session_timeout) + if (session->sock.isShutdown()) + { + if (session->sock.recv() == 0) + delete Jupiter::HTTP::Server::data_->sessions.remove(index); + } + else if ((std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->keep_alive_session_timeout) || (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->session_timeout)) - delete Jupiter::HTTP::Server::data_->sessions.remove(index); + session->sock.shutdown(); else if (session->sock.recv() > 0) { const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer(); @@ -815,7 +808,7 @@ int Jupiter::HTTP::Server::think() session->last_active = std::chrono::steady_clock::now(); Jupiter::HTTP::Server::data_->process_request(*session); if (session->keep_alive == false) // remove completed session - delete Jupiter::HTTP::Server::data_->sessions.remove(index); + session->sock.shutdown(); } else if (session->request.size() == Jupiter::HTTP::Server::data_->max_request_size) // reject (full buffer) delete Jupiter::HTTP::Server::data_->sessions.remove(index); diff --git a/Jupiter/IRC_Client.cpp b/Jupiter/IRC_Client.cpp index dc4e6d4..14bdf1d 100644 --- a/Jupiter/IRC_Client.cpp +++ b/Jupiter/IRC_Client.cpp @@ -199,7 +199,7 @@ Jupiter::IRC::Client::Client(const Jupiter::ReadableString &configSection) Jupiter::IRC::Client::~Client() { - Jupiter::IRC::Client::data_->sock->closeSocket(); + Jupiter::IRC::Client::data_->sock->close(); Jupiter::IRC::Client::data_->channels.emptyAndDelete(); Jupiter::IRC::Client::data_->users.emptyAndDelete(); @@ -687,7 +687,7 @@ int Jupiter::IRC::Client::primaryHandler() else { // Something went wrong. Kill the socket. - t->closeSocket(); + t->close(); } } break; @@ -1302,7 +1302,7 @@ void Jupiter::IRC::Client::disconnect(bool stayDead) { Jupiter::IRC::Client::data_->channels.emptyAndDelete(); Jupiter::IRC::Client::data_->connectionStatus = 0; - Jupiter::IRC::Client::data_->sock->closeSocket(); + Jupiter::IRC::Client::data_->sock->close(); Jupiter::IRC::Client::data_->reconnectTime = time(0) + Jupiter::IRC::Client::data_->reconnectDelay; Jupiter::IRC::Client::data_->dead = stayDead; this->OnDisconnect(); diff --git a/Jupiter/SecureSocket.cpp b/Jupiter/SecureSocket.cpp index 31212d9..fff5872 100644 --- a/Jupiter/SecureSocket.cpp +++ b/Jupiter/SecureSocket.cpp @@ -96,18 +96,25 @@ bool Jupiter::SecureSocket::bind(const char *hostname, unsigned short iPort, boo return Jupiter::Socket::bind(hostname, iPort, andListen); } -void Jupiter::SecureSocket::closeSocket() +void Jupiter::SecureSocket::shutdown() { - if (Jupiter::SecureSocket::SSLdata_ != nullptr) + Jupiter::Socket::shutdown(); + if (Jupiter::SecureSocket::SSLdata_ != nullptr && Jupiter::SecureSocket::SSLdata_->handle != nullptr) { - Jupiter::Socket::closeSocket(); - if (Jupiter::SecureSocket::SSLdata_->handle != nullptr) - { - if (SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle) == 0) - SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle); - SSL_free(Jupiter::SecureSocket::SSLdata_->handle); - Jupiter::SecureSocket::SSLdata_->handle = nullptr; - } + if (SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle) == 0) + SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle); + } +} + +void Jupiter::SecureSocket::close() +{ + Jupiter::Socket::close(); + if (Jupiter::SecureSocket::SSLdata_ != nullptr && Jupiter::SecureSocket::SSLdata_->handle != nullptr) + { + if (SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle) == 0) + SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle); + SSL_free(Jupiter::SecureSocket::SSLdata_->handle); + Jupiter::SecureSocket::SSLdata_->handle = nullptr; } } diff --git a/Jupiter/SecureSocket.h b/Jupiter/SecureSocket.h index 52f9c32..1d63491 100644 --- a/Jupiter/SecureSocket.h +++ b/Jupiter/SecureSocket.h @@ -119,7 +119,8 @@ namespace Jupiter /** * @brief Closes the socket. */ - virtual void closeSocket() override; + virtual void shutdown() override; + virtual void close() override; /** * @brief Writes new data from the socket to the buffer, without removing it from the socket queue. diff --git a/Jupiter/Socket.cpp b/Jupiter/Socket.cpp index 9532b7a..395a085 100644 --- a/Jupiter/Socket.cpp +++ b/Jupiter/Socket.cpp @@ -61,6 +61,7 @@ struct Jupiter::Socket::Data Jupiter::CStringS bound_host; int sockType = SOCK_RAW; int sockProto = IPPROTO_RAW; + bool is_shutdown = false; #if defined _WIN32 unsigned long blockMode = 0; #endif @@ -116,7 +117,7 @@ Jupiter::Socket::~Socket() { if (Jupiter::Socket::data_->rawSock > 0) { - Jupiter::Socket::closeSocket(); + Jupiter::Socket::close(); } delete Jupiter::Socket::data_; } @@ -185,9 +186,9 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const if (::connect(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR) { #if defined _WIN32 - closesocket(Jupiter::Socket::data_->rawSock); + ::closesocket(Jupiter::Socket::data_->rawSock); #else // _WIN32 - close(Jupiter::Socket::data_->rawSock); + ::close(Jupiter::Socket::data_->rawSock); #endif // WIN32 Jupiter::Socket::data_->rawSock = INVALID_SOCKET; info = info->ai_next; @@ -226,9 +227,9 @@ bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andL if (::bind(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR) { #if defined _WIN32 - closesocket(Jupiter::Socket::data_->rawSock); + ::closesocket(Jupiter::Socket::data_->rawSock); #else // _WIN32 - close(Jupiter::Socket::data_->rawSock); + ::close(Jupiter::Socket::data_->rawSock); #endif // WIN32 Jupiter::Socket::data_->rawSock = INVALID_SOCKET; info = info->ai_next; @@ -245,20 +246,35 @@ bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andL return false; } -void Jupiter::Socket::closeSocket() +void Jupiter::Socket::shutdown() { if (Jupiter::Socket::data_ != nullptr) { - shutdown(Jupiter::Socket::data_->rawSock, 2); + ::shutdown(Jupiter::Socket::data_->rawSock, 2); + Jupiter::Socket::data_->is_shutdown = true; + } +} + +void Jupiter::Socket::close() +{ + if (Jupiter::Socket::data_ != nullptr) + { + if (Jupiter::Socket::data_->is_shutdown == false) + this->shutdown(); #if defined _WIN32 - closesocket(Jupiter::Socket::data_->rawSock); + ::closesocket(Jupiter::Socket::data_->rawSock); #else // _WIN32 - close(Jupiter::Socket::data_->rawSock); + ::close(Jupiter::Socket::data_->rawSock); #endif // _WIN32 Jupiter::Socket::data_->rawSock = 0; } } +bool Jupiter::Socket::isShutdown() const +{ + return Jupiter::Socket::data_->is_shutdown; +} + addrinfo *Jupiter::Socket::getAddrInfo(const char *hostname, const char *port) // static { addrinfo *ptr; diff --git a/Jupiter/Socket.h b/Jupiter/Socket.h index 377f9d6..29fda66 100644 --- a/Jupiter/Socket.h +++ b/Jupiter/Socket.h @@ -275,7 +275,9 @@ namespace Jupiter /** * @brief Closes the socket. */ - virtual void closeSocket(); + virtual void shutdown(); + virtual void close(); + bool isShutdown() const; /** * @brief Returns the hostname that the socket is connected to. diff --git a/Release/Jupiter.lib b/Release/Jupiter.lib index 418c7b7faa1ce016fe1a2abe1789298ffbf9bb01..7753ab085461d11899e6c5eb0fd9610952551af1 100644 GIT binary patch delta 34043 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 KkkO-A;r|7KKE4J3 delta 33413 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