sources/network/udpsocket.cpp

Thu, 11 Dec 2014 07:18:11 +0200

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Thu, 11 Dec 2014 07:18:11 +0200
changeset 8
8b697d30c49f
parent 6
c709bb1a08e4
child 9
e7a09ceb4505
permissions
-rw-r--r--

- added huffman lib, now capable of initializing an rcon connection!

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#include "udpsocket.h"
#include "../huffman/huffman.h"

static unsigned char g_huffmanBuffer[131072];

// -----------------------------------------------------------------------------
//
UDPSocket::UDPSocket() :
	m_socket (socket (AF_INET, SOCK_DGRAM, 0)) {}

// -----------------------------------------------------------------------------
//
UDPSocket::~UDPSocket() {}

// -------------------------------------------------------------------------------------------------
//
METHOD
UDPSocket::set_blocking (bool a) -> bool
{
	int flags = fcntl (m_socket, F_GETFL, 0);
	int newflags = (a ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK));

	if (flags < 0 || fcntl (m_socket, F_SETFL, newflags) != 0)
	{
		m_error = "Unable to set socket as non-blocking";
		return false;
	}

	return true;
}

// -------------------------------------------------------------------------------------------------
//
METHOD
UDPSocket::bind (unsigned short port) -> bool
{
	struct sockaddr_in svaddr;
	memset (&svaddr, 0, sizeof svaddr);
	svaddr.sin_family = AF_INET;
	svaddr.sin_port = htons (port);
	svaddr.sin_addr.s_addr = htonl (INADDR_ANY);

	if (::bind (m_socket, reinterpret_cast<struct sockaddr*> (&svaddr), sizeof svaddr) == -1)
	{
		m_error = String ("Couldn't bind to port ") + String::from_number (port);
		return false;
	}

	return true;
}

// -------------------------------------------------------------------------------------------------
//
METHOD
UDPSocket::read (Datagram& datagram) -> bool
{
	sockaddr_in claddr;
	socklen_t socklen = sizeof claddr;
	static unsigned char packet[MAX_DATAGRAM_LENGTH];
	int length = ::recvfrom (m_socket, g_huffmanBuffer, sizeof packet, 0,
		reinterpret_cast<struct sockaddr*> (&claddr), &socklen);

	if (length == -1)
	{
		// We got an error, though EWOULDBLOCK is silent as it means no packets recieved.
		if (errno != EWOULDBLOCK)
			m_error.sprintf ("recvfrom error: %s", strerror (errno));;

		return false;
	}

	int decodedlength = sizeof g_huffmanBuffer;
	HUFFMAN_Decode (g_huffmanBuffer, packet, length, &decodedlength);
	datagram.from.host = ntohl (claddr.sin_addr.s_addr);
	datagram.from.port = ntohs (claddr.sin_port);
	datagram.data = Bytestream (packet, decodedlength);
	return true;
}

// -------------------------------------------------------------------------------------------------
//
METHOD
UDPSocket::send (const IPAddress& address, const Bytestream& data) -> bool
{
	int encodedlength = sizeof g_huffmanBuffer;
	HUFFMAN_Encode (data.data(), g_huffmanBuffer, data.written_length(), &encodedlength);
	struct sockaddr_in claddr = address.to_sockaddr_in();
	int res = ::sendto (m_socket, g_huffmanBuffer, encodedlength, 0,
		reinterpret_cast<struct sockaddr*> (&claddr), sizeof claddr);

	if (res == -1)
	{
		m_error = String ("Unable to launch packet: ") + strerror (errno);
		return false;
	}

	return true;
}

mercurial