diff options
author | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-09-26 01:43:09 +0000 |
---|---|---|
committer | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-09-26 01:43:09 +0000 |
commit | 939cb0ba987f927f1ad900d45f98ba6d8e03e9d4 (patch) | |
tree | f35510ff56e01ece2a0417c9a6fbad17fb7acfee /src/modules | |
parent | c8026bc2d73344e1df526f0a80694046efa4b22a (diff) |
Clean up SocketEngine interface to allow edge-triggered I/O and sockets that do not force readability.
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11760 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/extra/m_ssl_gnutls.cpp | 17 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_openssl.cpp | 254 | ||||
-rw-r--r-- | src/modules/m_httpd_stats.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_ident.cpp | 8 |
4 files changed, 84 insertions, 197 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index a7175005f..e72666062 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -439,7 +439,7 @@ class ModuleSSLGnuTLS : public Module } else if (session->status == ISSL_HANDSHAKING_WRITE) { - MakePollWrite(user); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE); return 0; } @@ -515,17 +515,18 @@ class ModuleSSLGnuTLS : public Module if (ret == (int)sendq.length()) { + ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_WRITE); return 1; } else if (ret > 0) { sendq = sendq.substr(ret); - MakePollWrite(user); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE); return 0; } else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) { - MakePollWrite(user); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE); return 0; } else if (ret == 0) @@ -559,12 +560,13 @@ class ModuleSSLGnuTLS : public Module { // gnutls_handshake() wants to read() again. session->status = ISSL_HANDSHAKING_READ; + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); } else { // gnutls_handshake() wants to write() again. session->status = ISSL_HANDSHAKING_WRITE; - MakePollWrite(user); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE); } } else @@ -583,7 +585,7 @@ class ModuleSSLGnuTLS : public Module VerifyCertificate(session,user); // Finish writing, if any left - MakePollWrite(user); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE); return true; } @@ -605,11 +607,6 @@ class ModuleSSLGnuTLS : public Module } } - void MakePollWrite(EventHandler* eh) - { - ServerInstance->SE->WantWrite(eh); - } - void CloseSession(issl_session* session) { if(session->sess) diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 8a2737f0e..e72bdc816 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -36,7 +36,6 @@ enum issl_status { ISSL_NONE, ISSL_HANDSHAKING, ISSL_OPEN }; -enum issl_io_status { ISSL_WRITE, ISSL_READ }; static bool SelfSigned = false; @@ -54,20 +53,15 @@ class issl_session : public classbase public: SSL* sess; issl_status status; - issl_io_status rstat; - issl_io_status wstat; - unsigned int inbufoffset; - char* inbuf; // Buffer OpenSSL reads into. - std::string outbuf; int fd; bool outbound; + bool data_to_write; issl_session() { outbound = false; - rstat = ISSL_READ; - wstat = ISSL_WRITE; + data_to_write = false; } }; @@ -106,10 +100,7 @@ class ModuleSSLOpenSSL : public Module public: - InspIRCd* PublicInstance; - ModuleSSLOpenSSL(InspIRCd* Me) - : Module(Me), PublicInstance(Me) { ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); @@ -137,7 +128,7 @@ class ModuleSSLOpenSSL : public Module // Needs the flag as it ignores a plain /rehash OnModuleRehash(NULL,"ssl"); Implementation eventlist[] = { - I_On005Numeric, I_OnBufferFlushed, I_OnRequest, I_OnRehash, I_OnModuleRehash, I_OnPostConnect, + I_On005Numeric, I_OnRequest, I_OnRehash, I_OnModuleRehash, I_OnPostConnect, I_OnHookIO }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); } @@ -350,8 +341,6 @@ class ModuleSSLOpenSSL : public Module issl_session* session = &sessions[fd]; session->fd = fd; - session->inbuf = new char[inbufsize]; - session->inbufoffset = 0; session->sess = SSL_new(ctx); session->status = ISSL_NONE; session->outbound = false; @@ -378,8 +367,6 @@ class ModuleSSLOpenSSL : public Module issl_session* session = &sessions[fd]; session->fd = fd; - session->inbuf = new char[inbufsize]; - session->inbufoffset = 0; session->sess = SSL_new(clictx); session->status = ISSL_NONE; session->outbound = true; @@ -423,19 +410,12 @@ class ModuleSSLOpenSSL : public Module if (session->status == ISSL_HANDSHAKING) { - if (session->rstat == ISSL_READ || session->wstat == ISSL_READ) - { - // The handshake isn't finished and it wants to read, try to finish it. - if (!Handshake(user, session)) - { - // Couldn't resume handshake. - if (session->status == ISSL_NONE) - return -1; - return 0; - } - } - else + // The handshake isn't finished and it wants to read, try to finish it. + if (!Handshake(user, session)) { + // Couldn't resume handshake. + if (session->status == ISSL_NONE) + return -1; return 0; } } @@ -444,26 +424,40 @@ class ModuleSSLOpenSSL : public Module if (session->status == ISSL_OPEN) { - if (session->wstat == ISSL_READ) + char* buffer = ServerInstance->GetReadBuffer(); + size_t bufsiz = ServerInstance->Config->NetBufferSize; + int ret = SSL_read(session->sess, buffer, bufsiz); + + if (ret > 0) { - if(DoWrite(user, session) == 0) - return 0; + recvq.append(buffer, ret); + return 1; } - - if (session->rstat == ISSL_READ) + else if (ret == 0) + { + // Client closed connection. + CloseSession(session); + return -1; + } + else if (ret < 0) { - int ret = DoRead(user, session); + int err = SSL_get_error(session->sess, ret); - if (ret > 0) + if (err == SSL_ERROR_WANT_READ) { - recvq.append(session->inbuf, session->inbufoffset); - session->inbufoffset = 0; - return 1; + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ); + return 0; } - else if (errno == EAGAIN || errno == EINTR) + else if (err == SSL_ERROR_WANT_WRITE) + { + ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE); return 0; + } else + { + CloseSession(session); return -1; + } } } @@ -473,9 +467,6 @@ class ModuleSSLOpenSSL : public Module int OnStreamSocketWrite(StreamSocket* user, std::string& buffer) { int fd = user->GetFd(); - /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) - return -1; issl_session* session = &sessions[fd]; @@ -485,136 +476,61 @@ class ModuleSSLOpenSSL : public Module return -1; } + session->data_to_write = true; + if (session->status == ISSL_HANDSHAKING) { - // The handshake isn't finished, try to finish it. - if (session->rstat == ISSL_WRITE || session->wstat == ISSL_WRITE) + if (!Handshake(user, session)) { - if (!Handshake(user, session)) - { - // Couldn't resume handshake. - if (session->status == ISSL_NONE) - return -1; - return 0; - } + // Couldn't resume handshake. + if (session->status == ISSL_NONE) + return -1; + return 0; } } - int rv = 0; - - // don't pull items into the output buffer until they are - // unlikely to block; this allows sendq exceeded to continue - // to work for SSL users. - // TODO better signaling for I/O requests so this isn't needed - if (session->outbuf.empty()) - { - session->outbuf = buffer; - rv = 1; - } - if (session->status == ISSL_OPEN) { - if (session->rstat == ISSL_WRITE) + int ret = SSL_write(session->sess, buffer.data(), buffer.size()); + if (ret == (int)buffer.length()) { - DoRead(user, session); + session->data_to_write = false; + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); + return 1; } - - if (session->wstat == ISSL_WRITE) + else if (ret > 0) { - DoWrite(user, session); - } - } - - if (rv == 0 || !session->outbuf.empty()) - ServerInstance->SE->WantWrite(user); - - return rv; - } - - int DoWrite(StreamSocket* user, issl_session* session) - { - if (!session->outbuf.size()) - return -1; - - int ret = SSL_write(session->sess, session->outbuf.data(), session->outbuf.size()); - - if (ret == 0) - { - CloseSession(session); - return 0; - } - else if (ret < 0) - { - int err = SSL_get_error(session->sess, ret); - - if (err == SSL_ERROR_WANT_WRITE) - { - session->wstat = ISSL_WRITE; - ServerInstance->SE->WantWrite(user); - return -1; - } - else if (err == SSL_ERROR_WANT_READ) - { - session->wstat = ISSL_READ; - return -1; - } - else - { - CloseSession(session); + buffer = buffer.substr(ret); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE); return 0; } - } - else - { - session->outbuf = session->outbuf.substr(ret); - return ret; - } - } - - int DoRead(StreamSocket* user, issl_session* session) - { - // Is this right? Not sure if the unencrypted data is garaunteed to be the same length. - // Read into the inbuffer, offset from the beginning by the amount of data we have that insp hasn't taken yet. - - int ret = SSL_read(session->sess, session->inbuf + session->inbufoffset, inbufsize - session->inbufoffset); - - if (ret == 0) - { - // Client closed connection. - CloseSession(session); - return 0; - } - else if (ret < 0) - { - int err = SSL_get_error(session->sess, ret); - - if (err == SSL_ERROR_WANT_READ) + else if (ret == 0) { - session->rstat = ISSL_READ; - return -1; - } - else if (err == SSL_ERROR_WANT_WRITE) - { - session->rstat = ISSL_WRITE; - ServerInstance->SE->WantWrite(user); + CloseSession(session); return -1; } - else + else if (ret < 0) { - CloseSession(session); - return 0; - } - } - else - { - // Read successfully 'ret' bytes into inbuf + inbufoffset - // There are 'ret' + 'inbufoffset' bytes of data in 'inbuf' - // 'buffer' is 'count' long - - session->inbufoffset += ret; + int err = SSL_get_error(session->sess, ret); - return ret; + if (err == SSL_ERROR_WANT_WRITE) + { + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_WRITE); + return 0; + } + else if (err == SSL_ERROR_WANT_READ) + { + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); + return 0; + } + else + { + CloseSession(session); + return -1; + } + } } + return 0; } bool Handshake(EventHandler* user, issl_session* session) @@ -632,15 +548,14 @@ class ModuleSSLOpenSSL : public Module if (err == SSL_ERROR_WANT_READ) { - session->rstat = ISSL_READ; + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); session->status = ISSL_HANDSHAKING; return true; } else if (err == SSL_ERROR_WANT_WRITE) { - session->wstat = ISSL_WRITE; + ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_POLL_WRITE); session->status = ISSL_HANDSHAKING; - ServerInstance->SE->WantWrite(user); return true; } else @@ -653,13 +568,11 @@ class ModuleSSLOpenSSL : public Module else if (ret > 0) { // Handshake complete. - // This will do for setting the ssl flag...it could be done earlier if it's needed. But this seems neater. - EventHandler *u = ServerInstance->SE->GetRef(session->fd); - VerifyCertificate(session, u); + VerifyCertificate(session, user); session->status = ISSL_OPEN; - ServerInstance->SE->WantWrite(user); + ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE); return true; } @@ -672,17 +585,6 @@ class ModuleSSLOpenSSL : public Module return true; } - void OnBufferFlushed(User* user) - { - if (user->GetIOHook() == this) - { - std::string dummy; - issl_session* session = &sessions[user->GetFd()]; - if (session && session->outbuf.size()) - OnStreamSocketWrite(user, dummy); - } - } - void CloseSession(issl_session* session) { if (session->sess) @@ -691,13 +593,6 @@ class ModuleSSLOpenSSL : public Module SSL_free(session->sess); } - if (session->inbuf) - { - delete[] session->inbuf; - } - - session->outbuf.clear(); - session->inbuf = NULL; session->sess = NULL; session->status = ISSL_NONE; errno = EIO; @@ -771,8 +666,7 @@ class ModuleSSLOpenSSL : public Module static int error_callback(const char *str, size_t len, void *u) { - ModuleSSLOpenSSL* mssl = (ModuleSSLOpenSSL*)u; - mssl->PublicInstance->Logs->Log("m_ssl_openssl",DEFAULT, "SSL error: " + std::string(str, len - 1)); + ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "SSL error: " + std::string(str, len - 1)); // // XXX: Remove this line, it causes valgrind warnings... diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index 884793e1c..01d77d806 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -87,7 +87,7 @@ class ModuleHttpStats : public Module data << "<usercount>" << ServerInstance->Users->clientlist->size() << "</usercount>"; data << "<channelcount>" << ServerInstance->chanlist->size() << "</channelcount>"; data << "<opercount>" << ServerInstance->Users->all_opers.size() << "</opercount>"; - data << "<socketcount>" << (ServerInstance->SE->GetMaxFds() - ServerInstance->SE->GetRemainingFds()) << "</socketcount><socketmax>" << ServerInstance->SE->GetMaxFds() << "</socketmax><socketengine>" << ServerInstance->SE->GetName() << "</socketengine>"; + data << "<socketcount>" << (ServerInstance->SE->GetUsedFds()) << "</socketcount><socketmax>" << ServerInstance->SE->GetMaxFds() << "</socketmax><socketengine>" << ServerInstance->SE->GetName() << "</socketengine>"; time_t current_time = 0; current_time = ServerInstance->Time(); diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index 973c93f72..66bd8835a 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -127,21 +127,17 @@ class IdentRequestSocket : public EventHandler } /* Add fd to socket engine */ - if (!ServerInstance->SE->AddFd(this)) + if (!ServerInstance->SE->AddFd(this, FD_WANT_NO_READ | FD_WANT_POLL_WRITE)) { this->Close(); throw ModuleException("out of fds"); } - - /* Important: We set WantWrite immediately after connect() - * because a successful connection will trigger a writability event - */ - ServerInstance->SE->WantWrite(this); } virtual void OnConnected() { ServerInstance->Logs->Log("m_ident",DEBUG,"OnConnected()"); + ServerInstance->SE->ChangeEventMask(this, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); char req[32]; |