giuliomoro@44
|
1 /*
|
giuliomoro@44
|
2 * udpServer.cpp
|
giuliomoro@44
|
3 *
|
giuliomoro@44
|
4 * Created on: 19 May 2015
|
giuliomoro@44
|
5 * Author: giulio moro
|
giuliomoro@44
|
6 */
|
giuliomoro@44
|
7 #include "../include/UdpServer.h"
|
giuliomoro@44
|
8
|
giuliomoro@44
|
9 UdpServer::UdpServer(int aPort){
|
giuliomoro@44
|
10 init(aPort);
|
giuliomoro@44
|
11 };
|
giuliomoro@44
|
12 UdpServer::UdpServer(){
|
giuliomoro@44
|
13 init(0);
|
giuliomoro@44
|
14 }
|
giuliomoro@44
|
15 UdpServer::~UdpServer(){
|
giuliomoro@124
|
16 printf("Close the socket\n");
|
giuliomoro@124
|
17 shutdown(inSocket, 0); //Stop receiving data for this socket. If further data arrives, reject it.
|
giuliomoro@54
|
18 //TODO: unbind from port. AFAIK, this involves closing the socket, therefore creating the socket should become part of bindToPort
|
giuliomoro@44
|
19 };
|
giuliomoro@44
|
20 bool UdpServer::init(int aPort){
|
giuliomoro@44
|
21 enabled=true;
|
giuliomoro@121
|
22 stZeroTimeOut.tv_sec = 0; //set timeout to 0
|
giuliomoro@121
|
23 stZeroTimeOut.tv_usec = 0;
|
giuliomoro@44
|
24 inSocket=socket(AF_INET, SOCK_DGRAM, 0);
|
giuliomoro@44
|
25 if (inSocket < 0){
|
giuliomoro@44
|
26 enabled=false;
|
giuliomoro@44
|
27 }
|
giuliomoro@44
|
28 length = sizeof(server);
|
giuliomoro@44
|
29 server.sin_family=AF_INET;
|
giuliomoro@44
|
30 server.sin_addr.s_addr=INADDR_ANY;
|
giuliomoro@44
|
31 enabled=bindToPort(aPort);
|
giuliomoro@44
|
32 wasteBufferSize=2048;
|
giuliomoro@44
|
33 wasteBuffer=malloc(wasteBufferSize);
|
giuliomoro@44
|
34 return enabled;
|
giuliomoro@44
|
35 }
|
giuliomoro@44
|
36
|
giuliomoro@44
|
37 bool UdpServer::bindToPort(int aPort){
|
giuliomoro@44
|
38 port=aPort;
|
giuliomoro@53
|
39 if(port<1){
|
giuliomoro@53
|
40 enabled=false;
|
giuliomoro@53
|
41 return false;
|
giuliomoro@53
|
42 }
|
giuliomoro@44
|
43 server.sin_port=htons(port);
|
giuliomoro@44
|
44 if (bind(inSocket,(struct sockaddr *)&server,length)<0){
|
giuliomoro@44
|
45 enabled=false;
|
giuliomoro@44
|
46 return false;
|
giuliomoro@44
|
47 }
|
giuliomoro@53
|
48 enabled=true;
|
giuliomoro@44
|
49 return true;
|
giuliomoro@44
|
50 };
|
giuliomoro@121
|
51 int UdpServer::waitUntilReady(bool readyForReading, int timeoutMsecs){
|
giuliomoro@121
|
52 // 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
|
53 if(enabled==false)
|
giuliomoro@121
|
54 return -1;
|
giuliomoro@121
|
55 if(timeoutMsecs<0)
|
giuliomoro@121
|
56 return select(inSocket+1, &stReadFDS, NULL, NULL, NULL); //calling this with a NULL timeout will block indefinitely
|
giuliomoro@121
|
57 FD_ZERO(&stReadFDS);
|
giuliomoro@121
|
58 FD_SET(inSocket, &stReadFDS);
|
giuliomoro@121
|
59 if(timeoutMsecs>=1000){
|
giuliomoro@121
|
60 float timeOutSecs=timeoutMsecs*0.001;
|
giuliomoro@121
|
61 stTimeOut.tv_sec=(long int)timeOutSecs;
|
giuliomoro@121
|
62 timeOutSecs-=(int)timeOutSecs;
|
giuliomoro@121
|
63 stTimeOut.tv_usec=(long int)(timeOutSecs*1000000);
|
giuliomoro@121
|
64 } else //faster!
|
giuliomoro@121
|
65 stTimeOut.tv_usec=(long int)timeoutMsecs*1000;
|
giuliomoro@121
|
66 int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stTimeOut);
|
giuliomoro@121
|
67 return descriptorReady>0? 1 : descriptorReady;
|
giuliomoro@121
|
68 }
|
giuliomoro@121
|
69
|
giuliomoro@44
|
70 int UdpServer::read(//Returns the number of bytes read, or -1 if there was an error.
|
giuliomoro@44
|
71 void *destBuffer,
|
giuliomoro@121
|
72 int maxBytesToRead,
|
giuliomoro@121
|
73 bool blockUntilSpecifiedAmountHasArrived)
|
giuliomoro@121
|
74 {
|
giuliomoro@44
|
75 if(enabled==false)
|
giuliomoro@44
|
76 return -1;
|
giuliomoro@44
|
77 FD_ZERO(&stReadFDS);
|
giuliomoro@44
|
78 FD_SET(inSocket, &stReadFDS);
|
giuliomoro@121
|
79 int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stZeroTimeOut);
|
giuliomoro@44
|
80 if(descriptorReady<0){ //an error occurred
|
giuliomoro@44
|
81 return -1;
|
giuliomoro@44
|
82 }
|
giuliomoro@44
|
83 int numberOfBytes=0;
|
giuliomoro@121
|
84 // do
|
giuliomoro@121
|
85 {
|
giuliomoro@121
|
86 if (FD_ISSET(inSocket, &stReadFDS))
|
giuliomoro@121
|
87 {
|
giuliomoro@121
|
88 // numberOfBytes=recvfrom(inSocket,destBuffer,maxBytesToRead,0,(struct sockaddr *)&from,&fromLength);
|
giuliomoro@121
|
89 numberOfBytes+=recv(inSocket,destBuffer,maxBytesToRead-numberOfBytes,0);
|
giuliomoro@121
|
90 if(numberOfBytes<0)
|
giuliomoro@121
|
91 return -1;
|
giuliomoro@121
|
92 }
|
giuliomoro@44
|
93 }
|
giuliomoro@121
|
94 // while (blockUntilSpecifiedAmountHasArrived && numberOfBytes==maxBytesToRead);
|
giuliomoro@44
|
95 return numberOfBytes;
|
giuliomoro@121
|
96 }
|
giuliomoro@44
|
97 int UdpServer::emptySocket(){
|
giuliomoro@44
|
98 return emptySocket(0);
|
giuliomoro@44
|
99 }
|
giuliomoro@44
|
100 int UdpServer::emptySocket(int maxBytes){//discards up to maxBytes from the socket. Returns the number of bytes discarded.
|
giuliomoro@44
|
101 if(wasteBuffer==NULL)
|
giuliomoro@44
|
102 return -1;
|
giuliomoro@44
|
103 int numberOfBytes=0;
|
giuliomoro@121
|
104 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
|
105 if(n>0)
|
giuliomoro@44
|
106 numberOfBytes+=n;
|
giuliomoro@44
|
107 if(n<0)
|
giuliomoro@44
|
108 return -1;
|
giuliomoro@44
|
109 if(maxBytes>0 && numberOfBytes>=maxBytes)
|
giuliomoro@44
|
110 break;
|
giuliomoro@44
|
111 };
|
giuliomoro@44
|
112 return numberOfBytes;
|
giuliomoro@44
|
113 }
|
giuliomoro@44
|
114 void* UdpServer::getWaste(){ //returns the last datagram retrieved by emptySocket()
|
giuliomoro@44
|
115 return wasteBuffer;
|
giuliomoro@44
|
116 }
|
giuliomoro@44
|
117
|