/* net/netclient.cc 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 "sys/sys.h" #include "core/net.h" namespace core { NetClient::NetClient(std::string host, int port) : client_host(host) { client_error = true; client_state = Connecting; con_print << host << ":" << port << " connects." << std::endl; // Get a socket file descriptor client_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (client_fd == -1) { con_warn << "Network client socket() failed!" << std::endl; abort(); return; } client_host = host; client_port = port; client_addr.sin_family = AF_INET; client_addr.sin_port = htons(port); client_addr.sin_addr.s_addr = inet_addr(host.c_str()); if (client_addr.sin_addr.s_addr == INADDR_NONE) { con_warn << "Network invalid client address " << host << "!" << std::endl; abort(); return; } memset(client_addr.sin_zero, '\0', sizeof(client_addr.sin_zero)); std::ostringstream osstream; client_player.player_id = client_fd; sendq.clear(); messageblock.clear(); client_error = false; } NetClient::~NetClient() { con_print << host() << ":" << port() << " disconnects." << std::endl; if (client_fd) { ::close(client_fd); } } void NetClient::abort() { client_error = true; } std::string NetClient::host() const { return client_host; } int NetClient::port() const { return client_port; } Player *NetClient::player() { return &client_player; } bool NetClient::has_messages() const { return (recvq.size() > 0 ); } void NetClient::retreive(std::string & message) { if (recvq.size() > 0 ) { message.assign(recvq.front()); recvq.pop_front(); } else { message.clear(); } } // receive data and decode it into lines void NetClient::receive(char *data) { std::string datablock; datablock.assign(data); while(datablock.size() > 0 ) { // scan the datablock for enters if (datablock[0] == '\n' || datablock[0] == '\r') { // TODO detect "begin binary block" message for zlib compression if (messageblock.size() > 0 ) { recvq.push_back(messageblock); messageblock.clear(); } } else { if (messageblock.size() < FRAMESIZE) { messageblock.append(datablock.substr(0,1)); } else { con_warn << "Incoming message exceeds " << FRAMESIZE << " bytes!\n"; messageblock.clear(); } } datablock.erase(0,1); } } void NetClient::send(std::string const &msg) { sendq.append(msg); } void NetClient::transmit() { if (sendq.size() >= BLOCKSIZE) { con_warn << "Outgoing message exceeds " << BLOCKSIZE << " bytes!\n"; sendq.clear(); return; } ssize_t bytes_sent = 0; while (sendq.size() && !error()) { bytes_sent = sendto(client_fd, sendq.c_str(), sendq.size(), 0, (struct sockaddr *)&client_addr, sizeof(client_addr)); if (bytes_sent < 0) { abort(); return; } sendq.erase(0, bytes_sent); } sendq.clear(); } }