diff options
Diffstat (limited to 'src/Net/ClientConnection.cpp')
-rw-r--r-- | src/Net/ClientConnection.cpp | 76 |
1 files changed, 25 insertions, 51 deletions
diff --git a/src/Net/ClientConnection.cpp b/src/Net/ClientConnection.cpp index 1523b44..ca12f9f 100644 --- a/src/Net/ClientConnection.cpp +++ b/src/Net/ClientConnection.cpp @@ -22,18 +22,11 @@ #include <cstring> #include <cerrno> #include <sys/socket.h> -#include <sys/select.h> +#include <fcntl.h> namespace Mad { namespace Net { -void ClientConnection::sendConnectionHeader(bool daemon) { - ConnectionHeader header = {'M', 'A', 'D', daemon ? 'D' : 'C', 0, 1, 1, 1}; - - rawSend(reinterpret_cast<unsigned char*>(&header), sizeof(header)); - rawReceive(sizeof(ConnectionHeader), sigc::mem_fun(this, &ClientConnection::connectionHeaderReceiveHandler)); -} - void ClientConnection::connectionHeaderReceiveHandler(const void *data, unsigned long length) { if(length != sizeof(ConnectionHeader)) // Error... disconnect @@ -49,14 +42,20 @@ void ClientConnection::connectionHeaderReceiveHandler(const void *data, unsigned // Unsupported protocol... disconnect return; - connecting = false; enterReceiveLoop(); } -void ClientConnection::connect(const IPAddress &address, bool daemon) throw(ConnectionException) { - const int kx_list[] = {GNUTLS_KX_ANON_DH, 0}; +void ClientConnection::connectionHeader() { + ConnectionHeader header = {'M', 'A', 'D', daemon ? 'D' : 'C', 0, 1, 1, 1}; - if(connected) + rawSend(reinterpret_cast<unsigned char*>(&header), sizeof(header)); + rawReceive(sizeof(ConnectionHeader), sigc::mem_fun(this, &ClientConnection::connectionHeaderReceiveHandler)); +} + +void ClientConnection::connect(const IPAddress &address, bool daemon0) throw(ConnectionException) { + daemon = daemon0; + + if(isConnected()) disconnect(); sock = socket(PF_INET, SOCK_STREAM, 0); @@ -68,58 +67,33 @@ void ClientConnection::connect(const IPAddress &address, bool daemon) throw(Conn if(::connect(sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) { close(sock); delete peer; + peer = 0; throw ConnectionException("connect()", std::strerror(errno)); } - connected = true; - connecting = true; - - gnutls_init(&session, GNUTLS_CLIENT); + // Set non-blocking flag + int flags = fcntl(sock, F_GETFL, 0); - gnutls_set_default_priority(session); - gnutls_kx_set_priority(session, kx_list); - - gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); - - gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(sock)); - - int ret = gnutls_handshake(session); - if(ret < 0) { - disconnect(); + if(flags < 0) { + close(sock); - throw ConnectionException("gnutls_handshake()", gnutls_strerror(ret)); + throw ConnectionException("fcntl()", std::strerror(errno)); } - sendConnectionHeader(daemon); -} - -void ClientConnection::disconnect() { - if(!connected) - return; - - gnutls_bye(session, GNUTLS_SHUT_RDWR); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); - shutdown(sock, SHUT_RDWR); - close(sock); - - gnutls_deinit(session); + gnutls_init(&session, GNUTLS_CLIENT); - delete peer; + gnutls_set_default_priority(session); - connected = false; -} - -bool ClientConnection::dataPending() const { - if(!connected) - return false; + const int kx_list[] = {GNUTLS_KX_ANON_DH, 0}; + gnutls_kx_set_priority(session, kx_list); - fd_set fds; - FD_ZERO(&fds); - FD_SET(sock, &fds); + gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); - struct timeval timeout = {0, 0}; + gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(sock)); - return (select(sock + 1, &fds, NULL, NULL, &timeout) == 1); + handshake(); } } |