]> git.vomp.tv Git - vompclient.git/blob - dsock.cc
Prebuffering
[vompclient.git] / dsock.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "dsock.h"
22
23 DatagramSocket::DatagramSocket(short port)
24 {
25   theInstance = this;
26   myPort = port;
27   addrlen = sizeof(struct sockaddr);
28
29   if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
30   { perror("socket"); exit(1); }
31
32   myAddr.sin_family = AF_INET;         // host byte order
33   myAddr.sin_port = htons(myPort);     // short, network byte order
34   myAddr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP
35   memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
36
37   if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1)
38   { perror("bind"); exit(1); }
39
40   FD_ZERO(&readfds);
41   FD_SET(socketnum, &readfds);
42   tv.tv_sec = 0;
43   tv.tv_usec = 0;
44
45   int allowed = 1;
46   setsockopt(socketnum, SOL_SOCKET, SO_BROADCAST, (char*)&allowed, sizeof(allowed));
47 }
48
49 DatagramSocket::~DatagramSocket()
50 {
51   CLOSESOCKET(socketnum);
52 }
53
54 DatagramSocket* DatagramSocket::theInstance = 0;
55 DatagramSocket* DatagramSocket::getInstance(void)
56 {
57   return theInstance;
58 }
59
60 unsigned char DatagramSocket::waitforMessage(unsigned char how)
61 {
62   /* how = 0 - block
63      how = 1 - start new wait
64      how = 2 - continue wait
65   */
66
67   struct timeval* passToSelect = NULL;
68
69
70   if (how == 0)
71   {
72     passToSelect = NULL;
73   }
74   else if (how == 1)
75   {
76     tv.tv_sec = 1;
77     tv.tv_usec = 500000;
78     passToSelect = &tv;
79   }
80   else if (how == 2)
81   {
82     if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
83     {
84       tv.tv_sec = 1;
85       tv.tv_usec = 500000;
86     }
87     passToSelect = &tv;
88   }
89   FD_ZERO(&readfds);
90   FD_SET(socketnum, &readfds);
91
92   if (select(socketnum + 1, &readfds, NULL, NULL, passToSelect) <= 0)
93   {  return 1;  }
94
95   if ((mlength = recvfrom(socketnum, buf, MAXBUFLEN, 0,
96       (struct sockaddr *)&theirAddr, &addrlen)) == -1)
97   { perror("recvfrom"); return 0; }
98   else
99   {
100     memset(&buf[mlength], 0, MAXBUFLEN - mlength);
101     strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr));
102     fromPort = ntohs(theirAddr.sin_port);
103
104     if (DSOCKDEBUG)
105     {
106       //printf("%s:%i\tIN  %i\t", fromIPA, fromPort, mlength);
107       int k;
108       for(k = 0; k < mlength; k++)
109         printf("%u ", (unsigned char)buf[k]);
110       printf("\n");
111     }
112     return 2;
113   }
114
115   /* Return 0, failure
116      Return 1, nothing happened, timer expired
117      Return 2, packet arrived (timer not expired)
118   */
119 }
120
121 int DatagramSocket::getDataLength(void) const
122 {
123   return mlength;
124 }
125
126 char *DatagramSocket::getData(void)             {  return buf;  }
127 char *DatagramSocket::getFromIPA(void)          {  return fromIPA;  }
128 short DatagramSocket::getFromPort(void) const   {  return fromPort; }
129
130 void DatagramSocket::send(char *ipa, short port, char *message, int length)
131 {
132   if (DSOCKDEBUG)
133   {
134     printf("%s:%i\tOUT %i\t", ipa, port, length);
135     int k;
136     UCHAR l;
137     for (k = 0; k < length; k++)
138       { l = (UCHAR)message[k]; printf("%u ", l); }
139   }
140
141   int sentLength = 0;
142
143   theirAddr.sin_family = AF_INET;      // host byte order
144   theirAddr.sin_port = htons(port);    // short, network byte order
145   struct in_addr tad;                  // temp struct tad needed to pass to theirAddr.sin_addr
146   tad.s_addr = inet_addr(ipa);
147   theirAddr.sin_addr = tad;            // address
148   memset(&(theirAddr.sin_zero), 0, 8); // zero the rest of the struct
149
150   errno = 0;
151
152   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
153   if (sentLength == length)
154   {
155     if (DSOCKDEBUG) printf(" GOOD\n");
156   }
157   else
158   {
159     if (DSOCKDEBUG)
160     {
161       printf(" --BAD--");  fflush(stdout);
162     }
163     sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
164     if (sentLength == length)
165     {
166       if (DSOCKDEBUG) printf(" GOOD\n");
167     }
168     else
169     {
170       if (DSOCKDEBUG && (sentLength != length))
171       {
172
173         printf(" -#-FAILED-#-\n");
174         printf("--------------\n");
175         printf("Sendto failure\n");
176         printf("--------------\n");
177         printf("%s:%i\tOUT %i %i ...\n", ipa, port, length, sentLength);
178         perror("Perror reports");
179         printf("errno value: %d\n", errno);
180         printf("errno translated: %s\n", strerror(errno));
181       //  printf("h_errno value: %d\n", h_errno);
182       //  printf("\nActual address: %s\n", inet_ntoa(tad));
183       //  printf("Actual port: %i\n", ntohs(theirAddr.sin_port));
184         printf("continuing...\n\n");
185
186       }
187     }
188   }
189 }
190