From 83e8023c5e46635753a609329cf9805a3520001e Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 13 Feb 2008 22:53:01 +0000 Subject: network subsystem initial import --- src/net/tcpconnection.cc | 188 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 src/net/tcpconnection.cc (limited to 'src/net/tcpconnection.cc') diff --git a/src/net/tcpconnection.cc b/src/net/tcpconnection.cc new file mode 100644 index 0000000..9eaba1f --- /dev/null +++ b/src/net/tcpconnection.cc @@ -0,0 +1,188 @@ +/* + net/tcpconnection.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sys/sys.h" +#include "net/net.h" +#include "net/tcpconnection.h" + +namespace net +{ + +TCPConnection::TCPConnection() +{ + tcpconnection_error = false; + tcpconnection_fd = -1; + tcpconnection_port = 0; +} + +TCPConnection::~TCPConnection() +{ + disconnect(); +} + +std::string TCPConnection::host() const +{ + return tcpconnection_host; +} + +int TCPConnection::port() const +{ + return tcpconnection_port; +} + +bool TCPConnection::error() const +{ + return tcpconnection_error; +} + +bool TCPConnection::valid() const +{ + return (tcpconnection_fd != -1); +} + +bool TCPConnection::invalid() const +{ + return (tcpconnection_fd == -1); +} + +int TCPConnection::fd() const +{ + return (tcpconnection_fd); +} + + +bool TCPConnection::connected() +{ + return ((tcpconnection_fd != -1) && !tcpconnection_error); +} + + +void TCPConnection::abort() +{ + tcpconnection_error= true; +} + +void TCPConnection::disconnect() +{ + if (tcpconnection_fd != -1) + close(tcpconnection_fd); + tcpconnection_fd = -1; + tcpconnection_error = false; + tcpconnection_host.clear(); + tcpconnection_port = 0; + con_debug << "Network disconnected from server" << std::endl; +} + +void TCPConnection::connect(std::string to_host, int to_port) +{ + if (valid()) + return; + + // resolve serverhostname + struct hostent *serverhostent; + serverhostent = gethostbyname(to_host.c_str()); + if (!serverhostent) { + con_warn << "Network can't resolve " << to_host.c_str() << "!" << std::endl; + abort(); + return; + } + + con_print << "Connecting to " << inet_ntoa(*((struct in_addr *)serverhostent->h_addr)) << ":" << to_port << "..." << std::endl; + + // Get a socket file descriptor + tcpconnection_fd = socket(PF_INET, SOCK_STREAM, 0); + if (tcpconnection_fd == -1) { + con_error << "Network socket() failed!" << std::endl; + abort(); + return; + } + + // make the connection + struct sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(to_port); + server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)serverhostent->h_addr))); + memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero); + + if (::connect(tcpconnection_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) != 0) { + con_error << "Network connect() failed!" << std::endl; + abort(); + return; + } + + tcpconnection_host = to_host; + tcpconnection_port = to_port; + tcpconnection_error = false; + con_print << "Connected to server." << std::endl; + +} + +void TCPConnection::receive(std::string &msg) +{ + if (error() || invalid()) + return; + + char recvbuf[FRAMESIZE]; // maximum block sizeq + size_t msglen = sizeof(recvbuf); + ssize_t bytes_received; + + memset(recvbuf, '\0', sizeof(recvbuf)); + bytes_received = ::recv(tcpconnection_fd, recvbuf, msglen, 0); + if (bytes_received == 0) { + con_print << "Server disconnected."; + abort(); + return; + } else if (bytes_received < 0) { + con_error << "Network receive() error!" << std::endl; + perror("recv"); + abort(); + return; + } + msg = recvbuf; +} + +void TCPConnection::send(std::string const &msg) +{ + if (error() || invalid()) + return; + + if (msg.size() > FRAMESIZE) { + con_warn << "Network message exceeds " << FRAMESIZE << " bytes!" << std::endl; + return; + } + + ssize_t bytes_sent = 0; + size_t total_sent = 0; + std::string sendbuf(msg); + + while (total_sent < msg.size()) { + bytes_sent = ::send(tcpconnection_fd, sendbuf.c_str(), sendbuf.size(), 0); + if (bytes_sent < 0) { + con_error << "Network send() error!" << std::endl; + perror("send"); + abort(); + return; + } + total_sent += bytes_sent; + + // assert (bytes_sent <= sendbuf.size()); + sendbuf.erase(sendbuf.size() - bytes_sent, bytes_sent); + } + + return; +} + +} -- cgit v1.2.3