summaryrefslogtreecommitdiff
path: root/modules/extra/m_ssl.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2011-07-31 03:22:23 -0400
committerAdam <Adam@anope.org>2011-07-31 03:22:23 -0400
commit1cb11bba5dd36c2ac1f02e7b49c659de142ce481 (patch)
tree1650215b843b98fc64991f373b018dc0b238975c /modules/extra/m_ssl.cpp
parentf29c88bcd535e6dcf3bbf453423bca4b697a60fc (diff)
Fixed a few small problems, including m_ssl's connect feature sometimes failing for no good reason
Diffstat (limited to 'modules/extra/m_ssl.cpp')
-rw-r--r--modules/extra/m_ssl.cpp141
1 files changed, 94 insertions, 47 deletions
diff --git a/modules/extra/m_ssl.cpp b/modules/extra/m_ssl.cpp
index 30e548150..eb723a341 100644
--- a/modules/extra/m_ssl.cpp
+++ b/modules/extra/m_ssl.cpp
@@ -28,11 +28,6 @@ class MySSLService : public SSLService
class SSLSocketIO : public SocketIO
{
- /** Check whether this socket has a pending connect() or accept()
- * @return 0 if neither, -1 if connect/accept fails, -2 to wait more
- */
- int CheckState();
-
public:
/* The SSL socket for this socket */
SSL *sslsock;
@@ -64,6 +59,12 @@ class SSLSocketIO : public SocketIO
*/
ClientSocket *Accept(ListenSocket *s);
+ /** Check if a connection has been accepted
+ * @param s The client socket
+ * @return -1 on error, 0 to wait, 1 on success
+ */
+ int Accepted(ClientSocket *cs);
+
/** Connect the socket
* @param s THe socket
* @param target IP to connect to
@@ -71,6 +72,12 @@ class SSLSocketIO : public SocketIO
*/
void Connect(ConnectionSocket *s, const Anope::string &target, int port);
+ /** Check if this socket is connected
+ * @param s The socket
+ * @return -1 for error, 0 for wait, 1 for connected
+ */
+ int Connected(ConnectionSocket *s);
+
/** Called when the socket is destructing
*/
void Destroy();
@@ -187,34 +194,6 @@ void MySSLService::Init(Socket *s)
s->IO = new SSLSocketIO();
}
-int SSLSocketIO::CheckState()
-{
- if (this->connected == 0 || this->accepted == 0)
- {
- int ret;
- if (this->connected == 0)
- ret = SSL_connect(this->sslsock);
- else if (this->accepted == 0)
- ret = SSL_accept(this->sslsock);
- if (ret <= 0)
- {
- int error = SSL_get_error(this->sslsock, ret);
-
- if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
- // Wait more
- return -2;
- return -1;
- }
-
- if (this->connected == 0)
- this->connected = 1;
- else if (this->accepted == 0)
- this->accepted = 1;
- }
-
- return 0;
-}
-
SSLSocketIO::SSLSocketIO() : connected(-1), accepted(-1)
{
this->sslsock = NULL;
@@ -222,22 +201,14 @@ SSLSocketIO::SSLSocketIO() : connected(-1), accepted(-1)
int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
{
- int i = this->CheckState();
- if (i < 0)
- return i;
-
- i = SSL_read(this->sslsock, buf, sz);
+ int i = SSL_read(this->sslsock, buf, sz);
TotalRead += i;
return i;
}
int SSLSocketIO::Send(Socket *s, const Anope::string &buf)
{
- int i = this->CheckState();
- if (i < 0)
- return i;
-
- i = SSL_write(this->sslsock, buf.c_str(), buf.length());
+ int i = SSL_write(this->sslsock, buf.c_str(), buf.length());
TotalWritten += i;
return i;
}
@@ -260,13 +231,49 @@ ClientSocket *SSLSocketIO::Accept(ListenSocket *s)
if (!SSL_set_fd(IO->sslsock, newsocket->GetFD()))
throw SocketException("Unable to set SSL fd");
- IO->accepted = 0;
- if (this->CheckState() == -1)
+ int ret = SSL_accept(IO->sslsock);
+ if (ret <= 0)
+ {
+ IO->accepted = 0;
+ int error = SSL_get_error(IO->sslsock, ret);
+ if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
+ {
+ SocketEngine::MarkWritable(newsocket);
+ return newsocket;
+ }
+
throw SocketException("Unable to accept new SSL connection: " + Anope::string(ERR_error_string(ERR_get_error(), NULL)));
+ }
+ IO->accepted = 1;
return newsocket;
}
+int SSLSocketIO::Accepted(ClientSocket *cs)
+{
+ SSLSocketIO *IO = debug_cast<SSLSocketIO *>(cs->IO);
+
+ if (IO->accepted == 0)
+ {
+ int ret = SSL_accept(IO->sslsock);
+ if (ret <= 0)
+ {
+ int error = SSL_get_error(IO->sslsock, ret);
+ if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
+ {
+ SocketEngine::MarkWritable(cs);
+ return 0;
+ }
+
+ return -1;
+ }
+ IO->accepted = 1;
+ return 0;
+ }
+
+ return IO->accepted;
+}
+
void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port)
{
if (s->IO == &normalSocketIO)
@@ -283,9 +290,49 @@ void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int
if (!SSL_set_fd(IO->sslsock, s->GetFD()))
throw SocketException("Unable to set SSL fd");
- IO->connected = 0;
- if (this->CheckState() == -1)
+ int ret = SSL_connect(IO->sslsock);
+ if (ret <= 0)
+ {
+ IO->connected = 0;
+ int error = SSL_get_error(IO->sslsock, ret);
+ if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
+ {
+ SocketEngine::MarkWritable(s);
+ return;
+ }
+
throw SocketException("Unable to connect to server: " + Anope::string(ERR_error_string(ERR_get_error(), NULL)));
+ }
+
+ IO->connected = 1;
+}
+
+int SSLSocketIO::Connected(ConnectionSocket *s)
+{
+ if (s->IO == &normalSocketIO)
+ throw SocketException("Connected() called for non ssl socket?");
+
+ int i = SocketIO::Connected(s);
+ if (i != 1)
+ return i;
+
+ SSLSocketIO *IO = debug_cast<SSLSocketIO *>(s->IO);
+
+ if (IO->connected == 0)
+ {
+ int ret = SSL_connect(IO->sslsock);
+ if (ret <= 0)
+ {
+ int error = SSL_get_error(IO->sslsock, ret);
+ if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
+ return 0;
+ return -1;
+ }
+ IO->connected = 1;
+ return 0; // poll for next read/write (which will be real), don't assume ones available
+ }
+
+ return IO->connected;
}
void SSLSocketIO::Destroy()