1
0
mirror of https://github.com/anope/anope.git synced 2026-07-10 17:23:14 +02:00

Cleaned up some of the socket code, cleaned up the pipe engines, added support for binary sockets, and cleaned up the asynch connect/accept code

This commit is contained in:
Adam
2011-08-21 13:38:42 -04:00
parent 4fcb371bc8
commit 2eb708e5ad
16 changed files with 738 additions and 725 deletions
+117 -91
View File
@@ -31,8 +31,6 @@ class SSLSocketIO : public SocketIO
public:
/* The SSL socket for this socket */
SSL *sslsock;
/* -1 if not, 0 if waiting, 1 if true */
int connected, accepted;
/** Constructor
*/
@@ -46,12 +44,12 @@ class SSLSocketIO : public SocketIO
*/
int Recv(Socket *s, char *buf, size_t sz);
/** Really write something to the socket
* @param s The socket
* @param buf What to write
* @return Number of bytes written
/** Write something to the socket
* @param s The socket
* @param buf The data to write
* @param size The length of the data
*/
int Send(Socket *s, const Anope::string &buf);
int Send(Socket *s, const char *buf, size_t sz);
/** Accept a connection from a socket
* @param s The socket
@@ -59,11 +57,11 @@ 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
/** Finished accepting a connection from a socket
* @param s The socket
* @return SF_ACCEPTED if accepted, SF_ACCEPTING if still in process, SF_DEAD on error
*/
int Accepted(ClientSocket *cs);
SocketFlag FinishAccept(ClientSocket *cs);
/** Connect the socket
* @param s THe socket
@@ -72,11 +70,11 @@ class SSLSocketIO : public SocketIO
*/
void Connect(ConnectionSocket *s, const Anope::string &target, int port);
/** Check if this socket is connected
/** Called to potentially finish a pending connection
* @param s The socket
* @return -1 for error, 0 for wait, 1 for connected
* @return SF_CONNECTED on success, SF_CONNECTING if still pending, and SF_DEAD on error.
*/
int Connected(ConnectionSocket *s);
SocketFlag FinishConnect(ConnectionSocket *s);
/** Called when the socket is destructing
*/
@@ -194,7 +192,7 @@ void MySSLService::Init(Socket *s)
s->IO = new SSLSocketIO();
}
SSLSocketIO::SSLSocketIO() : connected(-1), accepted(-1)
SSLSocketIO::SSLSocketIO()
{
this->sslsock = NULL;
}
@@ -206,9 +204,9 @@ int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
return i;
}
int SSLSocketIO::Send(Socket *s, const Anope::string &buf)
int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
{
int i = SSL_write(this->sslsock, buf.c_str(), buf.length());
int i = SSL_write(this->sslsock, buf, sz);
TotalWritten += i;
return i;
}
@@ -217,8 +215,20 @@ ClientSocket *SSLSocketIO::Accept(ListenSocket *s)
{
if (s->IO == &normalSocketIO)
throw SocketException("Attempting to accept on uninitialized socket with SSL");
ClientSocket *newsocket = normalSocketIO.Accept(s);
sockaddrs conaddr;
socklen_t size = sizeof(conaddr);
int newsock = accept(s->GetFD(), &conaddr.sa, &size);
#ifndef INVALID_SOCKET
const int INVALID_SOCKET = -1;
#endif
if (newsock < 0 || newsock == INVALID_SOCKET)
throw SocketException("Unable to accept connection: " + Anope::LastError());
ClientSocket *newsocket = s->OnAccept(newsock, conaddr);
me->service.Init(newsocket);
SSLSocketIO *IO = debug_cast<SSLSocketIO *>(newsocket->IO);
@@ -231,47 +241,47 @@ ClientSocket *SSLSocketIO::Accept(ListenSocket *s)
if (!SSL_set_fd(IO->sslsock, newsocket->GetFD()))
throw SocketException("Unable to set SSL fd");
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)));
}
newsocket->SetFlag(SF_ACCEPTING);
this->FinishAccept(newsocket);
IO->accepted = 1;
return newsocket;
}
int SSLSocketIO::Accepted(ClientSocket *cs)
SocketFlag SSLSocketIO::FinishAccept(ClientSocket *cs)
{
if (cs->IO == &normalSocketIO)
throw SocketException("Attempting to finish connect uninitialized socket with SSL");
else if (cs->HasFlag(SF_ACCEPTED))
return SF_ACCEPTED;
else if (!cs->HasFlag(SF_ACCEPTING))
throw SocketException("SSLSocketIO::FinishAccept called for a socket not accepted nor accepting?");
SSLSocketIO *IO = debug_cast<SSLSocketIO *>(cs->IO);
if (IO->accepted == 0)
int ret = SSL_accept(IO->sslsock);
if (ret <= 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))
{
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;
SocketEngine::MarkWritable(cs);
return SF_ACCEPTING;
}
else
{
cs->OnError(ERR_error_string(ERR_get_error(), NULL));
cs->SetFlag(SF_DEAD);
cs->UnsetFlag(SF_ACCEPTING);
return SF_DEAD;
}
IO->accepted = 1;
return 0;
}
return IO->accepted;
else
{
cs->SetFlag(SF_ACCEPTED);
cs->UnsetFlag(SF_ACCEPTING);
cs->OnAccept();
return SF_ACCEPTED;
}
}
void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port)
@@ -279,62 +289,78 @@ void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int
if (s->IO == &normalSocketIO)
throw SocketException("Attempting to connect uninitialized socket with SSL");
normalSocketIO.Connect(s, target, port);
s->UnsetFlag(SF_CONNECTING);
s->UnsetFlag(SF_CONNECTED);
s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port);
int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size());
if (c == -1)
{
if (Anope::LastErrorCode() != EINPROGRESS)
{
s->OnError(Anope::LastError());
s->SetFlag(SF_DEAD);
return;
}
else
{
SocketEngine::MarkWritable(s);
s->SetFlag(SF_CONNECTING);
return;
}
}
else
{
s->SetFlag(SF_CONNECTING);
this->FinishConnect(s);
}
}
SocketFlag SSLSocketIO::FinishConnect(ConnectionSocket *s)
{
if (s->IO == &normalSocketIO)
throw SocketException("Attempting to finish connect uninitialized socket with SSL");
else if (s->HasFlag(SF_CONNECTED))
return SF_CONNECTED;
else if (!s->HasFlag(SF_CONNECTING))
throw SocketException("SSLSocketIO::FinishConnect called for a socket not connected nor connecting?");
SSLSocketIO *IO = debug_cast<SSLSocketIO *>(s->IO);
IO->sslsock = SSL_new(client_ctx);
if (!IO->sslsock)
throw SocketException("Unable to initialize SSL socket");
if (!SSL_set_fd(IO->sslsock, s->GetFD()))
throw SocketException("Unable to set SSL fd");
if (IO->sslsock == NULL)
{
IO->sslsock = SSL_new(client_ctx);
if (!IO->sslsock)
throw SocketException("Unable to initialize SSL socket");
if (!SSL_set_fd(IO->sslsock, s->GetFD()))
throw SocketException("Unable to set SSL fd");
}
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;
return SF_CONNECTING;
}
s->ProcessError();
}
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)
else
{
int error = SSL_get_error(IO->sslsock, ret);
if (ret == -1 && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE))
return 0;
s->ProcessError();
return -1;
s->OnError(ERR_error_string(ERR_get_error(), NULL));
s->UnsetFlag(SF_CONNECTING);
s->SetFlag(SF_DEAD);
return SF_DEAD;
}
IO->connected = 1;
return 0; // poll for next read/write (which will be real), don't assume ones available
}
return IO->connected;
else
{
s->UnsetFlag(SF_CONNECTING);
s->SetFlag(SF_CONNECTED);
s->OnConnect();
return SF_CONNECTED;
}
}
void SSLSocketIO::Destroy()