view core/UdpServer.cpp @ 126:719119fb2905 scope-refactoring

Closing socket in the destructor
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 24 Aug 2015 15:25:34 +0100
parents 23137a333c93
children ff28e56e5b7e
line wrap: on
line source
/*
 * udpServer.cpp
 *
 *  Created on: 19 May 2015
 *      Author: giulio moro
 */
#include "../include/UdpServer.h"

UdpServer::UdpServer(int aPort){
	init(aPort);
};
UdpServer::UdpServer(){
	init(0);
}
UdpServer::~UdpServer(){
	close();
};
bool UdpServer::init(int aPort){
	enabled=true;
	stZeroTimeOut.tv_sec = 0; //set timeout to 0
	stZeroTimeOut.tv_usec = 0;
	inSocket=socket(AF_INET, SOCK_DGRAM, 0);
	if (inSocket < 0){
		enabled=false;
	}
	length = sizeof(server);
	server.sin_family=AF_INET;
	server.sin_addr.s_addr=INADDR_ANY;
	enabled=bindToPort(aPort);
	wasteBufferSize=2048;
	wasteBuffer=malloc(wasteBufferSize);
	return enabled;
}

bool UdpServer::bindToPort(int aPort){
	port=aPort;
	if(port<1){
		enabled=false;
		return false;
	}
	server.sin_port=htons(port);
	if (bind(inSocket,(struct sockaddr *)&server,length)<0){
		enabled=false;
		return false;
	}
	enabled=true;
	return true;
}

void UdpServer::close(){
	int ret=::close(inSocket);
	if(ret != 0)
		printf("Error while closing socket, errno: %d\n", errno);//Stop receiving data for this socket. If further data arrives, reject it.
	inSocket=0;
}

int UdpServer::waitUntilReady(bool readyForReading, int timeoutMsecs){
//	If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1.
	if(enabled==false)
		return -1;
	if(timeoutMsecs<0)
		return select(inSocket+1, &stReadFDS, NULL, NULL, NULL); //calling this with a NULL timeout will block indefinitely
	FD_ZERO(&stReadFDS);
	FD_SET(inSocket, &stReadFDS);
	if(timeoutMsecs>=1000){
		float timeOutSecs=timeoutMsecs*0.001;
		stTimeOut.tv_sec=(long int)timeOutSecs;
		timeOutSecs-=(int)timeOutSecs;
		stTimeOut.tv_usec=(long int)(timeOutSecs*1000000);
	} else //faster!
		stTimeOut.tv_usec=(long int)timeoutMsecs*1000;
	int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stTimeOut);
	return descriptorReady>0? 1 : descriptorReady;
}

int UdpServer::read(//Returns the number of bytes read, or -1 if there was an error.
					void *destBuffer,
					int maxBytesToRead,
					bool blockUntilSpecifiedAmountHasArrived)
{
	if(enabled==false)
		return -1;
	FD_ZERO(&stReadFDS);
	FD_SET(inSocket, &stReadFDS);
	int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stZeroTimeOut);
	if(descriptorReady<0){ //an error occurred
		return -1;
	}
	int numberOfBytes=0;
//	do
	{
		if (FD_ISSET(inSocket, &stReadFDS))
		{
	//		numberOfBytes=recvfrom(inSocket,destBuffer,maxBytesToRead,0,(struct sockaddr *)&from,&fromLength);
			numberOfBytes+=recv(inSocket,destBuffer,maxBytesToRead-numberOfBytes,0);
			if(numberOfBytes<0)
				return -1;
		}
	}
//	while (blockUntilSpecifiedAmountHasArrived && numberOfBytes==maxBytesToRead);
	return numberOfBytes;
}
int UdpServer::emptySocket(){
	return emptySocket(0);
}
int UdpServer::emptySocket(int maxBytes){//discards up to maxBytes from the socket. Returns the number of bytes discarded.
	if(wasteBuffer==NULL)
		return -1;
	int numberOfBytes=0;
	while(int n=read(wasteBuffer, wasteBufferSize, false)){// calls the read function until it does not return any more bytes (i.e.: socket is empty)
		if(n>0)
			numberOfBytes+=n;
		if(n<0)
			return -1;
		if(maxBytes>0 && numberOfBytes>=maxBytes)
			break;
	};
	return numberOfBytes;
}
void* UdpServer::getWaste(){ //returns the last datagram retrieved by emptySocket()
	return wasteBuffer;
}