diff options
Diffstat (limited to 'src/Net/ClientConnection.cpp')
-rw-r--r-- | src/Net/ClientConnection.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/Net/ClientConnection.cpp b/src/Net/ClientConnection.cpp new file mode 100644 index 0000000..396c70a --- /dev/null +++ b/src/Net/ClientConnection.cpp @@ -0,0 +1,82 @@ +/* + * ClientConnection.cpp + * + * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ClientConnection.h" +#include "IPAddress.h" +#include <cstring> +#include <errno.h> +#include <sys/socket.h> + +namespace Mad { +namespace Net { + +void ClientConnection::connect(const IPAddress &address) throw(ConnectionException) { + const int kx_list[] = {GNUTLS_KX_ANON_DH, 0}; + + if(connected) + disconnect(); + + peer = new IPAddress(address); + + sock = socket(PF_INET, SOCK_STREAM, 0); + if(sock < 0) + throw ConnectionException("socket()", std::strerror(errno)); + + if(::connect(sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) + throw ConnectionException("connect()", std::strerror(errno)); + + gnutls_anon_allocate_client_credentials(&anoncred); + gnutls_init(&session, GNUTLS_CLIENT); + + 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) + throw ConnectionException("gnutls_handshake()", gnutls_strerror(ret)); + + connected = true; +} + +void ClientConnection::disconnect() { + gnutls_bye(session, GNUTLS_SHUT_RDWR); + + if(sock >= 0) { + shutdown(sock, SHUT_RDWR); /* no more receptions */ + close(sock); + sock = -1; + } + + gnutls_deinit(session); + gnutls_anon_free_client_credentials(anoncred); + + if(peer) { + delete peer; + peer = 0; + } + + connected = false; +} + +} +} |