]> git.vomp.tv Git - vompclient.git/blob - dsock.cc
Language changes, fix for main menu hang
[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 ULONG DatagramSocket::iterate_ip = 0;
24
25 DatagramSocket::DatagramSocket(short port)
26 {
27   theInstance = this;
28   myPort = port;
29   addrlen = sizeof(struct sockaddr);
30   initted = false;
31 }
32
33 DatagramSocket::~DatagramSocket()
34 {
35   if (initted) shutdown();
36 }
37
38 DatagramSocket* DatagramSocket::theInstance = 0;
39 DatagramSocket* DatagramSocket::getInstance(void)
40 {
41   return theInstance;
42 }
43
44 int DatagramSocket::init()
45 {
46   if (initted) return 0;
47
48   if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
49   { perror("socket"); return 0; }
50
51   myAddr.sin_family = AF_INET;         // host byte order
52   myAddr.sin_port = htons(myPort);     // short, network byte order
53   myAddr.sin_addr.s_addr = getIPNumber(iterate_ip++); // auto-fill with my IP
54   memset(&(myAddr.sin_zero), 0, 8);    // zero the rest of the struct
55
56   if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1)
57   { perror("bind"); return 0; }
58
59   FD_ZERO(&readfds);
60   FD_SET(socketnum, &readfds);
61   tv.tv_sec = 0;
62   tv.tv_usec = 0;
63
64   int allowed = 1;
65   setsockopt(socketnum, SOL_SOCKET, SO_BROADCAST, (char*)&allowed, sizeof(allowed));
66
67   initted = true;
68
69   return 1;
70 }
71
72 void DatagramSocket::shutdown()
73 {
74   if (!initted) return;
75   CLOSESOCKET(socketnum);
76   initted = false;
77 }
78
79 unsigned char DatagramSocket::waitforMessage(unsigned char how)
80 {
81   if (!initted) return 0;
82
83   /* how = 0 - block
84      how = 1 - start new wait
85      how = 2 - continue wait
86   */
87
88   struct timeval* passToSelect = NULL;
89
90
91   if (how == 0)
92   {
93     passToSelect = NULL;
94   }
95   else if (how == 1)
96   {
97     tv.tv_sec = 1;
98     tv.tv_usec = 500000;
99     passToSelect = &tv;
100   }
101   else if (how == 2)
102   {
103     if ((tv.tv_sec == 0) && (tv.tv_usec == 0))  // protection in case timer = 0
104     {
105       tv.tv_sec = 1;
106       tv.tv_usec = 500000;
107     }
108     passToSelect = &tv;
109   }
110   FD_ZERO(&readfds);
111   FD_SET(socketnum, &readfds);
112
113   if (select(socketnum + 1, &readfds, NULL, NULL, passToSelect) <= 0)
114   {  return 1;  }
115
116   if ((mlength = recvfrom(socketnum, buf, MAXBUFLEN, 0,
117       (struct sockaddr *)&theirAddr, &addrlen)) == -1)
118   { perror("recvfrom"); return 0; }
119   else
120   {
121     memset(&buf[mlength], 0, MAXBUFLEN - mlength);
122     strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr));
123     fromPort = ntohs(theirAddr.sin_port);
124
125     if (DSOCKDEBUG)
126     {
127       //printf("%s:%i\tIN  %i\t", fromIPA, fromPort, mlength);
128       int k;
129       for(k = 0; k < mlength; k++)
130         printf("%u ", (unsigned char)buf[k]);
131       printf("\n");
132     }
133     return 2;
134   }
135
136   /* Return 0, failure
137      Return 1, nothing happened, timer expired
138      Return 2, packet arrived (timer not expired)
139   */
140 }
141
142 int DatagramSocket::getDataLength(void) const
143 {
144   return mlength;
145 }
146
147 char *DatagramSocket::getData(void)             {  return buf;  }
148 char *DatagramSocket::getFromIPA(void)          {  return fromIPA;  }
149 short DatagramSocket::getFromPort(void) const   {  return fromPort; }
150
151 void DatagramSocket::send(char *ipa, short port, char *message, int length)
152 {
153   if (!initted) return;
154
155   if (DSOCKDEBUG)
156   {
157     printf("%s:%i\tOUT %i\t", ipa, port, length);
158     int k;
159     UCHAR l;
160     for (k = 0; k < length; k++)
161       { l = (UCHAR)message[k]; printf("%u ", l); }
162   }
163
164   int sentLength = 0;
165
166   theirAddr.sin_family = AF_INET;      // host byte order
167   theirAddr.sin_port = htons(port);    // short, network byte order
168   struct in_addr tad;                  // temp struct tad needed to pass to theirAddr.sin_addr
169   tad.s_addr = inet_addr(ipa);
170   theirAddr.sin_addr = tad;            // address
171   memset(&(theirAddr.sin_zero), 0, 8); // zero the rest of the struct
172
173   errno = 0;
174
175   sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
176   if (sentLength == length)
177   {
178     if (DSOCKDEBUG) printf(" GOOD\n");
179   }
180   else
181   {
182     if (DSOCKDEBUG)
183     {
184       printf(" --BAD--");  fflush(stdout);
185     }
186     sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen);
187     if (sentLength == length)
188     {
189       if (DSOCKDEBUG) printf(" GOOD\n");
190     }
191     else
192     {
193       if (DSOCKDEBUG && (sentLength != length))
194       {
195
196         printf(" -#-FAILED-#-\n");
197         printf("--------------\n");
198         printf("Sendto failure\n");
199         printf("--------------\n");
200         printf("%s:%i\tOUT %i %i ...\n", ipa, port, length, sentLength);
201         perror("Perror reports");
202         printf("errno value: %d\n", errno);
203         printf("errno translated: %s\n", strerror(errno));
204       //  printf("h_errno value: %d\n", h_errno);
205       //  printf("\nActual address: %s\n", inet_ntoa(tad));
206       //  printf("Actual port: %i\n", ntohs(theirAddr.sin_port));
207         printf("continuing...\n\n");
208
209       }
210     }
211   }
212 }
213
214 ULONG DatagramSocket::getIPNumber(ULONG num)
215 {
216   char buffer[100];
217   ULONG returnaddress;
218
219   if (gethostname(buffer,sizeof(buffer))==SOCKET_ERROR)
220   {
221     return INADDR_ANY; //well take any address, if we fail
222   }
223
224   struct hostent *hosts=gethostbyname(buffer);
225   if (hosts==NULL)
226   {
227     return INADDR_ANY; //well take any address, if we fail
228   }
229
230   int num_ip=0;
231   for (num_ip=0;hosts->h_addr_list[num_ip]!=NULL;num_ip++);
232
233   int get_ip=(num%num_ip);//Just wrap around, if no interface are present any more
234   memcpy(&returnaddress, hosts->h_addr_list[get_ip], sizeof(ULONG));
235   return returnaddress;
236 }