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