Mostly minor fixes up until version 0.8.10.
[irreco.git] / irtrans / irserver / src / lanio.c
blob40ba23bd26c6666c7bd012b990cfbbb394c3a44d
1 /*
2 * Copyright (c) 2007, IRTrans GmbH
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of IRTrans GmbH nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY IRTrans GmbH ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL IRTrans GmbH BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifdef WIN32
31 #include "winsock2.h"
32 #include <windows.h>
33 #include <time.h>
34 #include <sys/timeb.h>
35 #endif
37 #ifdef WINCE
38 #include "winsock2.h"
39 #include <windows.h>
40 #include <time.h>
41 #endif
43 #include <stdio.h>
45 #ifdef LINUX
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <sys/un.h>
51 #include <arpa/inet.h>
52 #include <dirent.h>
53 #include <sys/stat.h>
54 #include <errno.h>
55 #include <fcntl.h>
56 #include <net/if.h>
57 #include <sys/ioctl.h>
58 #include <signal.h>
59 #include <stdint.h>
60 #include <sys/time.h>
62 typedef int SOCKET;
63 typedef int DWORD;
64 typedef int WSAEVENT;
65 #define closesocket close
66 #endif
69 #include "remote.h"
70 #include "errcode.h"
71 #include "network.h"
72 #include "dbstruct.h"
73 #include "lowlevel.h"
74 #include "fileio.h"
75 #include "global.h"
77 #ifdef WIN32
78 #include "winio.h"
79 #include "winusbio.h"
80 BOOL WINAPI ShutdownHandler (DWORD type);
81 #endif
83 #ifdef WIN32
84 WSAEVENT IrtLanEvent;
85 #endif
88 SOCKET irtlan_outbound;
89 SOCKET irtlan_socket;
92 int rcv_status_timeout (int timeout,uint32_t ip);
95 int IRTransLanFlash (DEVICEINFO *dev,IRDATA_LAN_FLASH *ird,int len,uint32_t ip)
97 int res;
98 byte bcast = 0;
99 struct sockaddr_in target;
102 if (bcast) {
103 memset (&target,0,sizeof (struct sockaddr));
104 target.sin_family = AF_INET;
105 target.sin_addr.s_addr = INADDR_BROADCAST;
106 target.sin_port = htons ((word)IRTRANS_PORT);
109 else if (dev) memcpy (&target,&dev->io.IPAddr[0],sizeof (struct sockaddr_in));
112 if ((bcast || dev) && connect (irtlan_outbound,(struct sockaddr *)&target,sizeof (struct sockaddr_in)) < 0) return (ERR_BINDSOCKET);
115 res = send (irtlan_outbound,(char *)ird,len + 5,0);
117 msSleep (30);
119 return (rcv_status_timeout (500,ip));
124 int IRTransLanSend (DEVICEINFO *dev,IRDATA *ird)
126 int res;
127 IRDATA_LAN irdlan;
128 struct sockaddr_in target;
130 memset (&irdlan,0,sizeof (IRDATA_LAN));
132 if (ird->command == START_FLASH_MODE) {
133 if (ird->len == 0) {
134 irdlan.netcommand = COMMAND_FLASH_END;
135 ird->len = 3;
137 else irdlan.netcommand = COMMAND_FLASH_START;
140 else if (ird->command == TRANSFER_FLASH) {
141 irdlan.netcommand = COMMAND_FLASH_DATA;
144 else {
145 irdlan.netcommand = COMMAND_LAN;
147 if (dev) {
148 memcpy (&target,&dev->io.IPAddr[0],sizeof (struct sockaddr_in));
149 if (dev && connect (irtlan_outbound,(struct sockaddr *)&target,sizeof (struct sockaddr_in)) < 0) return (ERR_BINDSOCKET);
152 memcpy (&(irdlan.ir_data),ird,ird->len);
154 res = send (irtlan_outbound,(char *)&irdlan,ird->len + sizeof (IRDATA_LAN) - sizeof (IRDATA),0);
156 msSleep (30);
158 return (0);
162 int rcv_status_timeout (int timeout,uint32_t ip)
164 byte data[1000];
165 int stat,sz,val;
166 int res = -1;
167 struct sockaddr_in from;
169 #ifdef LINUX
170 fd_set events;
171 int maxfd,wait,flags;
172 struct timeval tv;
174 flags = fcntl (irtlan_socket,F_GETFL);
175 #endif
177 retry:
178 #ifdef WIN32
179 stat = WaitForSingleObject (IrtLanEvent,timeout);
180 if (stat == WAIT_TIMEOUT) return (-1);
181 #endif
183 #ifdef LINUX
184 FD_ZERO (&events);
186 FD_SET (irtlan_socket,&events);
187 maxfd = irtlan_socket + 1;
189 tv.tv_sec = timeout / 1000;
190 tv.tv_usec = (timeout % 1000) * 1000;
192 stat = select (maxfd,&events,NULL,NULL,&tv);
193 if (stat == 0) return (-1);
195 fcntl (irtlan_socket,F_SETFL,flags | O_NONBLOCK);
196 #endif
198 do {
199 sz = sizeof (from);
200 val = recvfrom (irtlan_socket,data,1000,0,(struct sockaddr *)&from,&sz);
201 #ifdef WIN32
202 if (val > 0 && (!ip || from.sin_addr.S_un.S_addr == ip)) res = data[0];
203 #else
204 if (val > 0 && (!ip || from.sin_addr.s_addr == ip)) res = data[0];
205 #endif
206 } while (val > 0);
208 #ifdef WIN32
209 WSAResetEvent (IrtLanEvent);
210 #endif
211 if (res == -1) goto retry;
213 #ifdef LINUX
214 fcntl (irtlan_socket,F_SETFL,flags);
215 #endif
217 return (res);
221 int rcv_status ()
223 byte val,res = 0;
225 val = recv (irtlan_socket,&res,1,0);
227 return res;
230 void InitWinsock ()
232 #ifdef WIN32
233 int err;
234 WORD wVersionRequired;
235 WSADATA wsaData;
236 wVersionRequired = MAKEWORD(2,2);
237 err = WSAStartup(wVersionRequired, &wsaData);
238 if (err != 0) exit(1);
240 #endif
243 extern int irtrans_udp_port;
245 int OpenIRTransLANSocket (void)
247 int res;
248 struct sockaddr_in serv_addr;
250 irtlan_outbound = socket (PF_INET,SOCK_DGRAM,0);
251 if (irtlan_outbound < 0) return (ERR_OPENSOCKET);
253 res = 1;
254 setsockopt (irtlan_outbound,SOL_SOCKET,SO_BROADCAST,(char *)&res,sizeof (int));
256 memset (&serv_addr,0,sizeof (serv_addr));
257 serv_addr.sin_family = AF_INET;
258 serv_addr.sin_addr.s_addr = 0;
259 serv_addr.sin_port = htons (0);
260 if (bind (irtlan_outbound,(struct sockaddr *)&serv_addr,sizeof (serv_addr)) < 0) {
261 fprintf (stderr,"\n\nError binding send socket ... Abort [%d].\n",errno);
262 exit (-1);
266 irtlan_socket = socket (PF_INET,SOCK_DGRAM,0);
267 if (irtlan_socket < 0) return (ERR_OPENSOCKET);
269 memset (&serv_addr,0,sizeof (serv_addr));
270 serv_addr.sin_family = AF_INET;
272 serv_addr.sin_addr.s_addr = htonl (INADDR_ANY);
273 serv_addr.sin_port = htons ((short)irtrans_udp_port);
275 if (bind (irtlan_socket,(struct sockaddr *)&serv_addr,sizeof (serv_addr)) < 0) {
276 fprintf (stderr,"\n\nError binding socket ... Abort [%d].\n",errno);
277 exit (-1);
279 return (0);
282 #ifdef LINUX
284 SOCKET irt_bcast[32];
285 int if_count;
287 int OpenIRTransBroadcastSockets (void)
289 int res,i;
290 unsigned int ips[32];
292 struct sockaddr_in serv_addr;
294 if_count = GetInterfaces (ips);
296 for (i=0;i < if_count;i++) {
298 irt_bcast[i] = socket (PF_INET,SOCK_DGRAM,0);
299 if (irt_bcast[i] < 0) return (ERR_OPENSOCKET);
301 res = 1;
302 setsockopt (irt_bcast[i],SOL_SOCKET,SO_BROADCAST,(char *)&res,sizeof (int));
304 memset (&serv_addr,0,sizeof (serv_addr));
305 serv_addr.sin_family = AF_INET;
306 serv_addr.sin_addr.s_addr = ips[i];
307 serv_addr.sin_port = htons (0);
308 if (bind (irt_bcast[i],(struct sockaddr *)&serv_addr,sizeof (serv_addr)) < 0) {
309 fprintf (stderr,"\n\nError binding send socket ... Abort [%d].\n",errno);
310 exit (-1);
312 memset (&serv_addr,0,sizeof (serv_addr));
313 serv_addr.sin_family = AF_INET;
315 serv_addr.sin_addr.s_addr = htonl (INADDR_BROADCAST);
316 serv_addr.sin_port = htons ((short)irtrans_udp_port);
318 if (connect (irt_bcast[i],(struct sockaddr *)&serv_addr,sizeof (struct sockaddr_in)) < 0) return (ERR_BINDSOCKET);
321 return (0);
326 int GetInterfaces (unsigned int ips[])
328 int i,j,cnt;
329 FILE *fp;
330 char *pnt,ln[256];
331 struct sockaddr_in *sinp;
332 struct ifreq ifr;
333 int s; /* Socket */
334 char local_ip_addr[16];
336 fp = fopen ("/proc/net/dev","r");
337 if (!fp) return (0);
338 s = socket(AF_INET, SOCK_DGRAM, 0);
340 cnt = 0;
341 pnt = fgets (ln,sizeof (ln),fp);
342 while (pnt) {
343 i = 0;
344 while (ln[i] == ' ') i++;
345 if (!memcmp (ln+i,"eth",3) || !memcmp (ln+i,"wlan",4)) {
346 j = i;
347 while ((ln[j] >= '0' && ln[j] <= '9') || (ln[j] >= 'a' && ln[j] <= 'z') || (ln[j] >= 'A' && ln[j] <= 'Z')) j++;
348 ln[j] = 0;
349 memset (&ifr,0,sizeof (ifr));
350 strcpy(ifr.ifr_name, ln+i);
351 ioctl(s, SIOCGIFADDR, &ifr);
352 sinp = (struct sockaddr_in*)&ifr.ifr_addr;
353 ips[cnt++] = sinp->sin_addr.s_addr;
355 pnt = fgets (ln,sizeof (ln),fp);
358 close (s);
359 fclose (fp);
361 return (cnt);
364 #endif