summaryrefslogtreecommitdiff
path: root/src/modules/extra
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-26 01:43:09 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-09-26 01:43:09 +0000
commit939cb0ba987f927f1ad900d45f98ba6d8e03e9d4 (patch)
treef35510ff56e01ece2a0417c9a6fbad17fb7acfee /src/modules/extra
parentc8026bc2d73344e1df526f0a80694046efa4b22a (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/extra')
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp17
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp254
2 files changed, 81 insertions, 190 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...