]> git.vomp.tv Git - vompclient.git/blob - tcp.cc
New options code, enable radio, other stuff for dongle 15
[vompclient.git] / tcp.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3     Copyright 2003-2004 University Of Bradford
4
5     This file is part of VOMP.
6
7     VOMP is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     VOMP is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with VOMP; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21
22 #include "tcp.h"
23
24 TCP::TCP()
25 {
26   sock = 0;
27   connected = 0;
28   timeoutEnabled = 1;
29 }
30
31 TCP::~TCP()
32 {
33   if (connected)
34   {
35     close(sock);
36     Log::getInstance()->log("TCP", Log::DEBUG, "Have closed");
37   }
38 }
39
40 void TCP::disableTimeout()
41 {
42   timeoutEnabled = 0;
43 }
44
45 int TCP::connectTo(char* host, unsigned short port)
46 {
47   sock = socket(PF_INET, SOCK_STREAM, 0);
48   if (sock == -1) return 0;
49
50   struct sockaddr_in dest_addr;
51   dest_addr.sin_family = AF_INET;
52   dest_addr.sin_port = htons(port);
53
54   if (!inet_aton(host, &dest_addr.sin_addr))
55   {
56     close(sock);
57     return 0;
58   }
59
60   memset(&(dest_addr.sin_zero), '\0', 8);
61
62   // set non blocking
63   int oldflags = fcntl (sock, F_GETFL, 0);
64   oldflags |= O_NONBLOCK;
65   fcntl(sock, F_SETFL, oldflags);
66
67   // ok, how to open a connection in non blocking mode (and therefore have a self set timeout!!)
68
69   int success = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
70
71   if (success == 0)  // if by some miracle the connection succeeded in no time flat, just return!
72   {
73     connected = 1;
74     return 1;
75   }
76
77   // first check errno for EINPROGRESS, otherwise it's a fail
78   // this doesn't work?
79   if (errno != EINPROGRESS)
80   {
81     close(sock);
82     return 0;
83   }
84
85   // now do a timeout wait on writability on the socket
86
87   fd_set connectSet;
88   struct timeval timeout;
89   FD_ZERO(&connectSet);
90   FD_SET(sock, &connectSet);
91   timeout.tv_sec = 10;
92   timeout.tv_usec = 0;
93   success = select(sock + 1, NULL, &connectSet, NULL, &timeout);
94   if (success < 1)
95   {
96     // timeout or error
97     close(sock);
98     return 0;
99   }
100
101   // so the socket became available for writing. Contrary to expectation, this doesn't actually
102   // mean it connected...
103
104   int soError;
105   socklen_t soErrorSize = sizeof(soError);
106   int gso = getsockopt(sock, SOL_SOCKET, SO_ERROR, &soError, &soErrorSize);
107
108   if ((gso == 0) && (soError == 0))
109   {
110     // success!
111     connected = 1;
112     return 1;
113   }
114   else
115   {
116     close(sock);
117     return 0;
118   }
119
120 /*
121 The full documentation:
122
123        EINPROGRESS
124               The  socket is non-blocking and the connection canĀ­
125               not be completed immediately.  It  is  possible  to
126               select(2)  or  poll(2)  for completion by selecting
127               the socket  for  writing.  After  select  indicates
128               writability, use getsockopt(2) to read the SO_ERROR
129               option at level  SOL_SOCKET  to  determine  whether
130               connect  completed  successfully (SO_ERROR is zero)
131               or unsuccessfully (SO_ERROR is  one  of  the  usual
132               error  codes listed here, explaining the reason for
133               the failure).
134 */
135 }
136
137 void TCP::assignSocket(int tsocket)
138 {
139   sock = tsocket;
140 }
141
142 int TCP::isConnected()
143 {
144   return connected;
145 }
146
147 int TCP::sendPacket(void* bufR, size_t count)
148 {
149   size_t bytes_sent = 0;
150   int this_write;
151   int temp_write;
152
153   unsigned char* buf = (unsigned char*)bufR;
154
155   while (bytes_sent < count)
156   {
157     do
158     {
159       temp_write = this_write = write(sock, buf, count - bytes_sent);
160 //      Log::getInstance()->log("TCP", Log::DEBUG, "TCP has written %i bytes", temp_write);
161     } while ( (this_write < 0) && (errno == EINTR) );
162
163
164     if (this_write <= 0)
165     {
166       return(this_write);
167     }
168     bytes_sent += this_write;
169     buf += this_write;
170   }
171   return(count);
172 }
173
174 UCHAR* TCP::receivePacket()
175 {
176   ULONG packetLength;
177   int success;
178
179   success = readData((UCHAR*)&packetLength, sizeof(int));
180   if (!success) return NULL;
181
182   packetLength = ntohl(packetLength);
183
184   if (packetLength > 500000)
185   {
186     Log::getInstance()->log("TCP", Log::ERR, "Received packet > 500000");
187     return NULL;
188   }
189   if (packetLength == 0)
190   {
191     Log::getInstance()->log("TCP", Log::ERR, "Received packet len = 0");
192     return NULL;
193   }
194
195   UCHAR* buffer = (UCHAR*) malloc(packetLength);
196
197   success = readData(buffer, packetLength);
198
199   if (!success)
200   {
201     Log::getInstance()->log("TCP", Log::ERR, "readData failed");
202     free(buffer);
203     close(sock);
204     connected = 0;
205     return NULL;
206   }
207
208   dataLength = packetLength;
209   return buffer;
210 }
211
212 int TCP::getDataLength()
213 {
214   return dataLength;
215 }
216
217 int TCP::readData(UCHAR* buffer, int totalBytes)
218 {
219
220   int bytesRead = 0;
221   int thisRead;
222   int readTries = 0;
223   int success;
224   fd_set readSet;
225   struct timeval timeout;
226   struct timeval* passToSelect;
227
228   if (timeoutEnabled) passToSelect = &timeout;
229   else passToSelect = NULL;
230
231   while(1)
232   {
233     FD_ZERO(&readSet);
234     FD_SET(sock, &readSet);
235     timeout.tv_sec = 10;
236     timeout.tv_usec = 0;
237     success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
238     if (success < 1)
239     {
240       Log::getInstance()->log("TCP", Log::ERR, "Error or timeout");
241       return 0;  // error, or timeout
242     }
243
244     thisRead = read(sock, &buffer[bytesRead], totalBytes - bytesRead);
245 //    printf("read %i\n", thisRead);
246     if (!thisRead)
247     {
248       // if read returns 0 then connection is closed
249       // in non-blocking mode if read is called with no data available, it returns -1
250       // and sets errno to EGAGAIN. but we use select so it wouldn't do that anyway.
251       Log::getInstance()->log("TCP", Log::ERR, "Detected connection closed");
252       connected = 0;
253       return 0;
254     }
255     bytesRead += thisRead;
256
257     if (bytesRead == totalBytes)
258     {
259       return 1;
260     }
261     else
262     {
263       if (++readTries == 100)
264       {
265 //        Log::getInstance()->log("TCP", Log::ERR, "Too many reads");
266 //        return 0;
267       }
268     }
269   }
270 }
271
272 void TCP::dump(unsigned char* data, ULONG size)
273 {
274   printf("Size = %lu\n", size);
275
276   ULONG c = 0;
277   while(c < size)
278   {
279     if ((size - c) > 15)
280     {
281       printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
282         data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
283         data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
284         dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
285         dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15]));
286       c += 16;
287     }
288     else
289     {
290       switch (size - c)
291       {
292         case 15:
293           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X     %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
294             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
295             data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
296             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
297             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]));
298           c += 15;
299           break;
300         case 14:
301           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X        %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
302             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
303             data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
304             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
305             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
306           c += 14;
307           break;
308         case 13:
309           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X  %02X           %c%c%c%c%c%c%c%c%c%c%c%c%c\n",
310             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
311             data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
312             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
313             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
314           c += 13;
315           break;
316         case 12:
317           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X %02X               %c%c%c%c%c%c%c%c%c%c%c%c\n",
318             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
319             data[c+8], data[c+9], data[c+10], data[c+11],
320             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
321             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
322           c += 12;
323           break;
324         case 11:
325           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X %02X                  %c%c%c%c%c%c%c%c%c%c%c\n",
326             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
327             data[c+8], data[c+9], data[c+10],
328             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
329             dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
330           c += 11;
331           break;
332         case 10:
333           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X %02X                     %c%c%c%c%c%c%c%c%c%c\n",
334             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
335             data[c+8], data[c+9],
336             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
337             dcc(data[c+8]), dcc(data[c+9]));
338           c += 10;
339           break;
340         case 9:
341           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X  %02X                        %c%c%c%c%c%c%c%c%c\n",
342             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
343             data[c+8],
344             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
345             dcc(data[c+8]));
346           c += 9;
347           break;
348         case 8:
349           printf(" %02X %02X %02X %02X  %02X %02X %02X %02X                            %c%c%c%c%c%c%c%c\n",
350             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
351             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]));
352           c += 8;
353           break;
354         case 7:
355           printf(" %02X %02X %02X %02X  %02X %02X %02X                               %c%c%c%c%c%c%c\n",
356             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
357             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]));
358           c += 7;
359           break;
360         case 6:
361           printf(" %02X %02X %02X %02X  %02X %02X                                  %c%c%c%c%c%c\n",
362             data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
363             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
364           c += 6;
365           break;
366         case 5:
367           printf(" %02X %02X %02X %02X  %02X                                     %c%c%c%c%c\n",
368             data[c], data[c+1], data[c+2], data[c+3], data[c+4],
369             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
370           c += 5;
371           break;
372         case 4:
373           printf(" %02X %02X %02X %02X                                         %c%c%c%c\n",
374             data[c], data[c+1], data[c+2], data[c+3],
375             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
376           c += 4;
377           break;
378         case 3:
379           printf(" %02X %02X %02X                                            %c%c%c\n",
380             data[c], data[c+1], data[c+2],
381             dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
382           c += 3;
383           break;
384         case 2:
385           printf(" %02X %02X                                               %c%c\n",
386             data[c], data[c+1],
387             dcc(data[c]), dcc(data[c+1]));
388           c += 2;
389           break;
390         case 1:
391           printf(" %02X                                                  %c\n",
392             data[c],
393             dcc(data[c]));
394           c += 1;
395           break;
396       }
397     }
398   }
399 }
400
401 UCHAR TCP::dcc(UCHAR c)
402 {
403   if (isspace(c)) return ' ';
404   if (isprint(c)) return c;
405   return '.';
406 }