diff options
author | Adam <Adam@anope.org> | 2011-05-21 04:57:27 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-05-21 04:57:27 -0400 |
commit | 115f94bfc23c481eab50298895f76bd494179cd8 (patch) | |
tree | eeda28c466e9f2f532b2dee75cb817eba9066357 /src/sockets.cpp | |
parent | 7e5727288d9b2da5b53476b91f8cb9fe96e14d53 (diff) |
Made Anope able to process normally when disconnected from the uplink and not sleep(), enable usage of non-blocking connect() and default all sockets to non blocking mode. Some cleanup to m_ssl and some cleanup to main.cpp.
Diffstat (limited to 'src/sockets.cpp')
-rw-r--r-- | src/sockets.cpp | 132 |
1 files changed, 97 insertions, 35 deletions
diff --git a/src/sockets.cpp b/src/sockets.cpp index 96acbe981..c9758cb12 100644 --- a/src/sockets.cpp +++ b/src/sockets.cpp @@ -251,7 +251,7 @@ bool cidr::match(sockaddrs &other) * @param sz How much to read * @return Number of bytes received */ -int SocketIO::Recv(Socket *s, char *buf, size_t sz) const +int SocketIO::Recv(Socket *s, char *buf, size_t sz) { size_t i = recv(s->GetFD(), buf, sz, 0); TotalRead += i; @@ -263,7 +263,7 @@ int SocketIO::Recv(Socket *s, char *buf, size_t sz) const * @param buf What to write * @return Number of bytes written */ -int SocketIO::Send(Socket *s, const Anope::string &buf) const +int SocketIO::Send(Socket *s, const Anope::string &buf) { size_t i = send(s->GetFD(), buf.c_str(), buf.length(), 0); TotalWritten += i; @@ -272,8 +272,9 @@ int SocketIO::Send(Socket *s, const Anope::string &buf) const /** Accept a connection from a socket * @param s The socket + * @return The new client socket */ -void SocketIO::Accept(ListenSocket *s) +ClientSocket *SocketIO::Accept(ListenSocket *s) { sockaddrs conaddr; @@ -285,32 +286,44 @@ void SocketIO::Accept(ListenSocket *s) #endif if (newsock > 0 && newsock != INVALID_SOCKET) - s->OnAccept(newsock, conaddr); + return s->OnAccept(newsock, conaddr); else throw SocketException("Unable to accept connection: " + Anope::LastError()); } +/** Bind a socket + * @param s The socket + * @param ip The IP to bind to + * @param port The optional port to bind to + */ +void SocketIO::Bind(Socket *s, const Anope::string &ip, int port) +{ + s->bindaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, ip, port); + if (bind(s->GetFD(), &s->bindaddr.sa, s->bindaddr.size()) == -1) + throw SocketException("Unable to bind to address: " + Anope::LastError()); +} + /** Connect the socket * @param s THe socket * @param target IP to connect to * @param port to connect to - * @param bindip IP to bind to, if any */ -void SocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port, const Anope::string &bindip) +void SocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port) { - s->bindaddr.clear(); - s->conaddr.clear(); - - if (!bindip.empty()) + 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) { - s->bindaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, bindip, 0); - if (bind(s->GetFD(), &s->bindaddr.sa, s->bindaddr.size()) == -1) - throw SocketException(Anope::string("Unable to bind to address: ") + Anope::LastError()); + if (Anope::LastErrorCode() != EINPROGRESS) + throw SocketException("Error connecting to server: " + Anope::LastError()); + else + SocketEngine::MarkWritable(s); + } + else + { + s->OnConnect(); + s->connected = true; } - - s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port); - if (connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size()) == -1 && errno != EINPROGRESS) - throw SocketException(Anope::string("Error connecting to server: ") + Anope::LastError()); } /** Empty constructor, used for things such as the pipe socket @@ -335,6 +348,7 @@ Socket::Socket(int sock, bool ipv6, int type) : Flags<SocketFlag, 2>(SocketFlagS this->Sock = socket(this->IPv6 ? AF_INET6 : AF_INET, type, 0); else this->Sock = sock; + this->SetNonBlocking(); SocketEngine::AddSocket(this); } @@ -391,6 +405,15 @@ bool Socket::SetNonBlocking() #endif } +/** Bind the socket to an ip and port + * @param ip The ip + * @param port The port + */ +void Socket::Bind(const Anope::string &ip, int port) +{ + this->IO->Bind(this, ip, port); +} + /** Called when there is something to be received for this socket * @return true on success, false to drop this socket */ @@ -445,7 +468,9 @@ bool BufferedSocket::ProcessRead() char tbuffer[NET_BUFSIZE] = ""; RecvLen = this->IO->Recv(this, tbuffer, sizeof(tbuffer) - 1); - if (RecvLen <= 0) + if (RecvLen == -2) + return true; + else if (RecvLen <= 0) return false; Anope::string sbuffer = this->extrabuf; @@ -482,10 +507,10 @@ bool BufferedSocket::ProcessRead() */ bool BufferedSocket::ProcessWrite() { - if (this->WriteBuffer.empty()) - return true; int count = this->IO->Send(this, this->WriteBuffer); - if (count <= -1) + if (count == -2) + return true; + else if (count <= -1) return false; this->WriteBuffer = this->WriteBuffer.substr(count); if (this->WriteBuffer.empty()) @@ -557,10 +582,8 @@ ListenSocket::ListenSocket(const Anope::string &bindip, int port, bool ipv6) : S this->Type = SOCKTYPE_LISTEN; this->SetNonBlocking(); - this->listenaddrs.pton(IPv6 ? AF_INET6 : AF_INET, bindip, port); - - if (bind(Sock, &this->listenaddrs.sa, this->listenaddrs.size()) == -1) - throw SocketException(Anope::string("Unable to bind to address: ") + Anope::LastError()); + this->bindaddr.pton(IPv6 ? AF_INET6 : AF_INET, bindip, port); + this->IO->Bind(this, bindip, port); if (listen(Sock, 5) == -1) throw SocketException(Anope::string("Unable to listen: ") + Anope::LastError()); @@ -601,7 +624,7 @@ ClientSocket *ListenSocket::OnAccept(int fd, const sockaddrs &addr) * @param ipv6 true to use IPv6 * @param type The socket type, defaults to SOCK_STREAM */ -ConnectionSocket::ConnectionSocket(bool ipv6, int type) : BufferedSocket(0, ipv6, type) +ConnectionSocket::ConnectionSocket(bool ipv6, int type) : BufferedSocket(0, ipv6, type), connected(false) { this->Type = SOCKTYPE_CONNECTION; } @@ -609,19 +632,58 @@ ConnectionSocket::ConnectionSocket(bool ipv6, int type) : BufferedSocket(0, ipv6 /** Connect the socket * @param TargetHost The target host to connect to * @param Port The target port to connect to - * @param BindHost The host to bind to for connecting */ -void ConnectionSocket::Connect(const Anope::string &TargetHost, int Port, const Anope::string &BindHost) +void ConnectionSocket::Connect(const Anope::string &TargetHost, int Port) { - try - { - this->IO->Connect(this, TargetHost, Port, BindHost); - } - catch (const SocketException &) + this->IO->Connect(this, TargetHost, Port); +} + +/** Called when the socket is ready to be written to + * @return true on success, false to drop this socket + */ +bool ConnectionSocket::ProcessWrite() +{ + if (!this->connected) { - delete this; - throw; + SocketEngine::ClearWritable(this); + + int optval = 0; + socklen_t optlen = sizeof(optval); + if (!getsockopt(this->GetFD(), SOL_SOCKET, SO_ERROR, &optval, &optlen) && !optval) + { + this->OnConnect(); + this->connected = true; + return true; + } + + errno = optval; + this->OnError(Anope::LastError()); + return false; } + + return BufferedSocket::ProcessWrite(); +} + +/** Called when there is an error for this socket + * @return true on success, false to drop this socket + */ +void ConnectionSocket::ProcessError() +{ + if (!this->connected) + this->ProcessWrite(); +} + +/** Called on a successful connect + */ +void ConnectionSocket::OnConnect() +{ +} + +/** Called when a connection is not successful + * @param error The error + */ +void ConnectionSocket::OnError(const Anope::string &error) +{ } /** Constructor |