Skip to:

TCPSocket.cc

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>

#include "TCPSocket.h"


char *TCPSocket::ErrorMessage()
{
	return szErrorMessage_;
}


unsigned long TCPSocket::getHostByName(const char *hostName)
{
	struct hostent *hent;

	hent = gethostbyname(hostName);
	if (!hent)
		return FALSE;

	return *((unsigned long *)hent->h_addr);
}


int TCPSocket::getServiceByName(const char *ServiceName, const char *Protocol)
{
	struct servent *sent;

	sent = getservbyname(ServiceName, Protocol);
	if (!sent)
		return FALSE;

	return ntohs(sent->s_port);
}


TCPSocket::TCPSocket()
	:socket_(0), portNumber_(0), hostAddress_(0), initialized_(FALSE)
{
	szErrorMessage_ = "";
}


TCPSocket::~TCPSocket()
{
	Close();
}


int TCPSocket::init(const char *hostName, const char *serviceName)
{
	hostAddress_ = TCPSocket::getHostByName(hostName);
	if (!hostAddress_) {
		szErrorMessage_ = "Failed to resolve host name";
		return FALSE;
	}

	portNumber_ = TCPSocket::getServiceByName(serviceName, "tcp");
	if (!portNumber_) {
		portNumber_ = atoi(serviceName);
		if (!portNumber) {
			szErrorMessage_ = "Failed to resolve service name";
			return FALSE;
		}
	}

	initialized_ = TRUE;
	return TRUE;
}


int TCPSocket::Connect()
{
	struct sockaddr_in sin;

	if (!initialized_) {
		szErrorMessage_ = "Socket must be initialized before use";
		return FALSE;
	}	

	if (socket_) {
		szErrorMessage_ = "Socket already exists. Call close before connect";
		return FALSE;
	}

	socket_ = socket( AF_INET, SOCK_STREAM, 0 );
	if (SOCKET_IS_INVALID(socket_)) {
		szErrorMessage_ = "Couldn't create socket:";
		return FALSE;
	}

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(portNumber_);
	sin.sin_addr.s_addr = hostAddress_;

	if (connect(socket_, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) {
		szErrorMessage_ = "Connect failed";
		return FALSE;
	} else
		return TRUE;
}


int TCPSocket::Recv(char *buf, int *bufSize)
{
	int n = *bufSize;

	if (!initialized_) {
		szErrorMessage_ = "Socket must be initialized before use";
		return FALSE;
	}	

	if (!socket_) {
		szErrorMessage_ = "Socket does not exist, call connect first";
		return FALSE;
	}

	if ((n = recv(socket_, buf, n, 0)) == -1) {
		szErrorMessage_ = "ERROR: Call to recv failed";
		*bufSize = -1;
		return FALSE;
	} else {
		*bufSize = n;
		return TRUE;
	}
}

int TCPSocket::RecvAll(void **ppResult, long *pResultSize)
{
	int iBufferSize = 1460;
	char szBuffer[1460 +1];
	int MoreToRead = TRUE;
	char *szResultBuffer = NULL;
	int iResultBufferSize = 0;


	memset(szBuffer, 0, sizeof(szBuffer));

	if (!initialized_) {
		szErrorMessage_ = "Socket must be initialized before use";
		return FALSE;
	}	

	if (!socket_) {
		szErrorMessage_ = "Socket does not exist, call connect first";
		return FALSE;
	}

	while (MoreToRead || Poll(0, TRUE)) {
		int n;

		MoreToRead = FALSE;
		if ((n = recv(socket_, szBuffer, iBufferSize, 0)) == -1) {
			szErrorMessage_ = "recv ERROR: Call to recv failed";
			return FALSE;
		}
		
		if (!szResultBuffer) {
			szResultBuffer = new char[n+1];
			memset(szResultBuffer, '\0', n+1);
		} else {
			char *szTmpBuffer = NULL;
			
			szTmpBuffer = new char[iResultBufferSize + n+1];
			memset(szTmpBuffer, '\0', iResultBufferSize + n+1);
			memcpy(szTmpBuffer, szResultBuffer, iResultBufferSize);
			delete szResultBuffer;
			szResultBuffer = szTmpBuffer;
		}

		memcpy(szResultBuffer + iResultBufferSize, szBuffer, n);
		iResultBufferSize += n;

		if (n < iBufferSize)
			break;

		MoreToRead = TRUE;
	}

	(*ppResult) = szResultBuffer;
	(*pResultSize) = iResultBufferSize;

	if (iResultBufferSize == 0) {
		szErrorMessage_ = "0 bytes received, connection was probobaly reset.";
		return FALSE;
	}
	return TRUE;
}


int TCPSocket::Send(const char *Buffer, int BufferSize)
{
	if (!initialized_) {
		szErrorMessage_ = "Socket must be initialized before use";
		return FALSE;
	}	

	if (!socket_) {
		szErrorMessage_ = "Socket does not exist, call connect first";
		return FALSE;
	}

	// This writes exactly 1024 characters and the receiving end reads
	// exactly 1024 bytes
	int siz = (BufferSize > 1024) ? BufferSize : (1024+1);

	char *pTemp = new char[siz+1];
	memset(pTemp, 0, siz+1);

	strncpy(pTemp, Buffer, BufferSize);

	if (send(socket_, pTemp, siz, 0) == -1) {
		szErrorMessage_ = "ERROR: Call to send failed";
		delete [] pTemp;
		return FALSE;
	} else {
		delete [] pTemp;
		return TRUE;
	}
}


int TCPSocket::Close()
{
	close(socket_);
}


int TCPSocket::Poll(double Timeout, int rw)
{
	fd_set fds, fdz;
 
	struct timeval tv;
	int n;

	tv.tv_sec = (long) Timeout;
	tv.tv_usec = (long) (1000000.0 * (Timeout - (double) tv.tv_sec));
 
	FD_ZERO(&fdz);
	FD_ZERO(&fds);
	FD_SET(socket_, &fds);

	n = select(socket_+1, rw ? &fds : &fdz, !rw ? &fds : &fdz, &fdz, &tv);
	if (n < 0) {
		szErrorMessage_ = "select() failed";
		return FALSE;
	}
 
	if (n == 0) {
		szErrorMessage_ = "Timeout waiting for socket";
		return FALSE;
	}

	if (FD_ISSET(socket_, &fds))
		return TRUE;
 
	szErrorMessage_ = "Call to Poll succeeded but socket not ready?!?";
	return FALSE;
}
 

Company Registration