/* 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 const &to_host, int to_port) { if (valid()) return; // resolve serverhostname struct hostent *serverhostent; serverhostent = gethostbyname(to_host.c_str()); if (!serverhostent) { con_warn << "Could not 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 << "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!\n"; 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; } }