giuliomoro@44: /* giuliomoro@44: * udpServer.cpp giuliomoro@44: * giuliomoro@44: * Created on: 19 May 2015 giuliomoro@44: * Author: giulio moro giuliomoro@44: */ giuliomoro@44: #include "../include/UdpServer.h" giuliomoro@44: giuliomoro@44: UdpServer::UdpServer(int aPort){ giuliomoro@44: init(aPort); giuliomoro@44: }; giuliomoro@44: UdpServer::UdpServer(){ giuliomoro@44: init(0); giuliomoro@44: } giuliomoro@44: UdpServer::~UdpServer(){ giuliomoro@54: //TODO: unbind from port. AFAIK, this involves closing the socket, therefore creating the socket should become part of bindToPort giuliomoro@44: }; giuliomoro@44: bool UdpServer::init(int aPort){ giuliomoro@44: enabled=true; giuliomoro@121: stZeroTimeOut.tv_sec = 0; //set timeout to 0 giuliomoro@121: stZeroTimeOut.tv_usec = 0; giuliomoro@44: inSocket=socket(AF_INET, SOCK_DGRAM, 0); giuliomoro@44: if (inSocket < 0){ giuliomoro@44: enabled=false; giuliomoro@44: } giuliomoro@44: length = sizeof(server); giuliomoro@44: server.sin_family=AF_INET; giuliomoro@44: server.sin_addr.s_addr=INADDR_ANY; giuliomoro@44: enabled=bindToPort(aPort); giuliomoro@44: wasteBufferSize=2048; giuliomoro@44: wasteBuffer=malloc(wasteBufferSize); giuliomoro@44: return enabled; giuliomoro@44: } giuliomoro@44: giuliomoro@44: bool UdpServer::bindToPort(int aPort){ giuliomoro@44: port=aPort; giuliomoro@53: if(port<1){ giuliomoro@53: enabled=false; giuliomoro@53: return false; giuliomoro@53: } giuliomoro@44: server.sin_port=htons(port); giuliomoro@44: if (bind(inSocket,(struct sockaddr *)&server,length)<0){ giuliomoro@44: enabled=false; giuliomoro@44: return false; giuliomoro@44: } giuliomoro@53: enabled=true; giuliomoro@44: return true; giuliomoro@44: }; giuliomoro@121: int UdpServer::waitUntilReady(bool readyForReading, int timeoutMsecs){ giuliomoro@121: // 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. giuliomoro@121: if(enabled==false) giuliomoro@121: return -1; giuliomoro@121: if(timeoutMsecs<0) giuliomoro@121: return select(inSocket+1, &stReadFDS, NULL, NULL, NULL); //calling this with a NULL timeout will block indefinitely giuliomoro@121: FD_ZERO(&stReadFDS); giuliomoro@121: FD_SET(inSocket, &stReadFDS); giuliomoro@121: if(timeoutMsecs>=1000){ giuliomoro@121: float timeOutSecs=timeoutMsecs*0.001; giuliomoro@121: stTimeOut.tv_sec=(long int)timeOutSecs; giuliomoro@121: timeOutSecs-=(int)timeOutSecs; giuliomoro@121: stTimeOut.tv_usec=(long int)(timeOutSecs*1000000); giuliomoro@121: } else //faster! giuliomoro@121: stTimeOut.tv_usec=(long int)timeoutMsecs*1000; giuliomoro@121: int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stTimeOut); giuliomoro@121: return descriptorReady>0? 1 : descriptorReady; giuliomoro@121: } giuliomoro@121: giuliomoro@44: int UdpServer::read(//Returns the number of bytes read, or -1 if there was an error. giuliomoro@44: void *destBuffer, giuliomoro@121: int maxBytesToRead, giuliomoro@121: bool blockUntilSpecifiedAmountHasArrived) giuliomoro@121: { giuliomoro@44: if(enabled==false) giuliomoro@44: return -1; giuliomoro@44: FD_ZERO(&stReadFDS); giuliomoro@44: FD_SET(inSocket, &stReadFDS); giuliomoro@121: int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stZeroTimeOut); giuliomoro@44: if(descriptorReady<0){ //an error occurred giuliomoro@44: return -1; giuliomoro@44: } giuliomoro@44: int numberOfBytes=0; giuliomoro@121: // do giuliomoro@121: { giuliomoro@121: if (FD_ISSET(inSocket, &stReadFDS)) giuliomoro@121: { giuliomoro@121: // numberOfBytes=recvfrom(inSocket,destBuffer,maxBytesToRead,0,(struct sockaddr *)&from,&fromLength); giuliomoro@121: numberOfBytes+=recv(inSocket,destBuffer,maxBytesToRead-numberOfBytes,0); giuliomoro@121: if(numberOfBytes<0) giuliomoro@121: return -1; giuliomoro@121: } giuliomoro@44: } giuliomoro@121: // while (blockUntilSpecifiedAmountHasArrived && numberOfBytes==maxBytesToRead); giuliomoro@44: return numberOfBytes; giuliomoro@121: } giuliomoro@44: int UdpServer::emptySocket(){ giuliomoro@44: return emptySocket(0); giuliomoro@44: } giuliomoro@44: int UdpServer::emptySocket(int maxBytes){//discards up to maxBytes from the socket. Returns the number of bytes discarded. giuliomoro@44: if(wasteBuffer==NULL) giuliomoro@44: return -1; giuliomoro@44: int numberOfBytes=0; giuliomoro@121: while(int n=read(wasteBuffer, wasteBufferSize, false)){// calls the read function until it does not return any more bytes (i.e.: socket is empty) giuliomoro@44: if(n>0) giuliomoro@44: numberOfBytes+=n; giuliomoro@44: if(n<0) giuliomoro@44: return -1; giuliomoro@44: if(maxBytes>0 && numberOfBytes>=maxBytes) giuliomoro@44: break; giuliomoro@44: }; giuliomoro@44: return numberOfBytes; giuliomoro@44: } giuliomoro@44: void* UdpServer::getWaste(){ //returns the last datagram retrieved by emptySocket() giuliomoro@44: return wasteBuffer; giuliomoro@44: } giuliomoro@44: