Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


documentation changes
[palacios.git] / misc / network_servers / vtl / socks.cc
1 #include "socks.h"
2 #include <signal.h>
3 #include <assert.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7
8
9 #if defined(__sparc__)
10 #include <sys/filio.h>
11 #endif
12
13 #if defined(__sparc__) || (defined(WIN32) && !defined(__CYGWIN__))
14 #define SOCKOPT_TYPE char *
15 #else
16 #define SOCKOPT_TYPE void *
17 #endif
18
19 #if defined(linux)
20 #define SOCKOPT_LEN_TYPE unsigned
21 #else
22 #define SOCKOPT_LEN_TYPE int
23 #endif
24
25
26
27 template <typename A, typename B> bool MIN(const A &a, const B &b) {
28   return ((a < b) ? a : b);
29 }
30
31
32 int GetSockType(const SOCK fd) {
33   int type;
34   SOCKOPT_LEN_TYPE len = sizeof(int);
35   
36   if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (SOCKOPT_TYPE)&type, &len)) {
37     return -1;
38   } else {
39     return type;
40   }
41 }
42
43
44 int IsSocket(const SOCK fd) {
45   return (GetSockType(fd) >= 0);
46 }
47
48 int IsStreamSocket(const SOCK fd) {
49   return (GetSockType(fd) == SOCK_STREAM);
50 }
51
52 int IsDatagramSocket(const SOCK fd) {
53   return (GetSockType(fd) == SOCK_DGRAM);
54 }
55
56 #ifdef linux
57 int IsVirtualSocket(const SOCK fd) {
58   struct stat mystat;
59   fstat(fd, &mystat);
60
61   return S_ISFIFO(mystat.st_mode);
62 }
63 #endif
64
65 int IsValidIPMulticastAddress(const unsigned adx) {
66   
67   //int x=(ntohl(port)>>24)&0xff;
68   int x = (adx >> 24) & 0xff;
69
70   if ((x < 224) || (x > 239)) {
71     return 0;
72   } else {
73     return 1;
74   }
75 }
76
77 void IPToHostname(const unsigned ip, char *name, const int namesize) { 
78   struct in_addr ia;
79   struct hostent * he;
80
81   ia.s_addr = ip;
82
83   he = gethostbyaddr((const char *)&ia, sizeof(ia), AF_INET);
84
85   strncpy(name, he ? he->h_name : "UNKNOWN HOST", namesize - 1);
86 }
87
88
89 void PrintIPAddress(const unsigned adx, FILE *out) {
90   fprintf(out,"%3d.%3d.%3d.%3d", 
91           (adx >> 24) & 0xff,
92           (adx >> 16) & 0xff, 
93           (adx >> 8) & 0xff, 
94           (adx) & 0xff);
95 }
96
97 unsigned ToIPAddress(const char * hostname) {
98   unsigned x;
99
100   if ((x = inet_addr(hostname)) != INADDR_NONE) {
101     return ntohl(x);
102   } else {
103     struct hostent * he;
104     
105     if ((he = gethostbyname(hostname)) == NULL) {
106       return INADDR_NONE;
107     } else {
108       memcpy(&x, he->h_addr, 4);
109       x = ntohl(x);
110       return x;
111     }
112   }
113 }
114
115 unsigned long GetRemoteSockAddress(SOCK sock) {
116   struct sockaddr_in remote_addr;
117   unsigned long remote_ip;
118
119   if (GetRemoteSockAddress(sock, (struct sockaddr *)&remote_addr) == -1) {
120     return 0;
121   }
122   
123   assert(remote_addr.sin_family == AF_INET);
124   remote_ip = ntohl(remote_addr.sin_addr.s_addr);
125   return remote_ip;
126 }
127
128 int GetRemoteSockAddress(SOCK sock, struct sockaddr * addr) {
129   SOCKOPT_LEN_TYPE addr_len = sizeof(struct sockaddr);
130
131   if (addr == NULL) {
132     return -1;
133   }
134   
135   if (getpeername(sock, addr, &addr_len) == -1) {
136     return -1;
137   }
138
139   return 0;
140 }
141
142
143 unsigned long GetLocalSockAddress(SOCK sock) {
144  struct sockaddr_in local_addr;
145  unsigned long local_ip; 
146
147  if (GetLocalSockAddress(sock, (struct sockaddr *)&local_addr) == -1) {
148    return 0;
149  }
150
151  assert(local_addr.sin_family == AF_INET);
152  local_ip = ntohl(local_addr.sin_addr.s_addr);
153  return local_ip;
154 }
155
156 int GetLocalSockAddress(SOCK sock, struct sockaddr * addr) {
157   SOCKOPT_LEN_TYPE addr_len = sizeof(struct sockaddr);
158
159   if (addr == NULL) {
160     return -1;
161   }
162
163   if (getsockname(sock, addr, &addr_len) == -1) {
164     return -1;
165   }
166
167   return 0;
168 }
169
170
171 int GetLocalMacAddress(const string dev_name, char * buf) {
172   return GetLocalMacAddress(dev_name.c_str(), buf);
173 }
174
175 int GetLocalMacAddress(const char * dev_name, char * buf) {
176 #ifdef linux
177   struct ifreq mac_req;
178   SOCK fd = socket(AF_INET, SOCK_STREAM, 0);
179
180   snprintf(mac_req.ifr_name, IF_NAMESIZE, "%s", dev_name);
181
182   if (ioctl(fd, SIOCGIFHWADDR, &mac_req) < 0) {
183     cerr << "Error Could not get the local MAC Address" << endl;
184     perror("perror: ");
185     return -1;
186   }
187   
188   memcpy(buf, mac_req.ifr_hwaddr.sa_data, 6);
189 #elif WIN32
190   char temp_dev_name[256];
191   PIP_ADAPTER_INFO temp_adapter;
192   IP_ADAPTER_INFO AdapterInfo[16];       // Allocate information
193   // for up to 16 NICs
194   DWORD dwBufLen = sizeof(AdapterInfo);  // Save memory size of buffer
195   
196   DWORD dwStatus = GetAdaptersInfo(AdapterInfo,                 // [out] buffer to receive data
197                                    &dwBufLen);                  // [in] size of receive data buffer
198   
199   assert(dwStatus == ERROR_SUCCESS);  // Verify return value 
200   
201   temp_adapter = AdapterInfo;
202   
203   while(temp_adapter) {
204     sprintf(temp_dev_name, "\\Device\\NPF_%s", temp_adapter->AdapterName);
205     
206     if (strcmp(dev_name, temp_dev_name) == 0) {
207       memcpy(buf, temp_adapter->Address, 6);
208       break;
209     }   
210     temp_adapter = temp_adapter->Next;
211   } 
212 #endif
213   return 0;
214 }
215
216
217 int GetOpenTcpPorts(int ** ports) {
218 #ifdef linux
219   int proc_fd;
220   int num_ports = 0;
221   unsigned long rxq, txq, time_len, retr, inode, local_addr, rem_addr;
222   int d, local_port, rem_port, scan_num, timer_run, uid, timeout, state;
223   string proc_str;
224   char more[512];
225
226
227   enum {
228     TCP_ESTABLISHED = 1,
229     TCP_SYN_SENT,
230     TCP_SYN_RECV,
231     TCP_FIN_WAIT1,
232     TCP_FIN_WAIT2,
233     TCP_TIME_WAIT,
234     TCP_CLOSE,
235     TCP_CLOSE_WAIT,
236     TCP_LAST_ACK,
237     TCP_LISTEN,
238     TCP_CLOSING                 /* now a valid state */
239   };
240
241   /* 
242      We do this because we use realloc, 
243      so the first ptr-value must be null or we will realloc on some randome address
244   */
245   *ports = NULL;
246
247   proc_fd = open("/proc/net/tcp", O_RDONLY);
248   if (proc_fd == -1) {
249
250     return -1;
251   }
252   /* This supports IPv6 which we will ignore for now...
253     num = sscanf(line,
254     "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
255     &d, local_addr, &local_port, rem_addr, &rem_port, &state,
256     &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
257   */
258   GetLine(proc_fd, proc_str);
259  
260   while (GetLine(proc_fd, proc_str)) {
261     
262     // We pretty much stole this from netstat.c in the net-tools package
263     scan_num = sscanf(proc_str.c_str(),
264                       "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
265                       &d, &local_addr, &local_port, &rem_addr, &rem_port, &state,
266                       &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
267     
268     if (state == TCP_LISTEN) {
269       //printf("%s (%d)\n", ip_to_string(ntohl(local_addr)), local_port);
270       *ports = (int *)realloc((*ports), sizeof(int) * (num_ports + 1));
271  
272      (*ports)[num_ports] = local_port;
273
274       num_ports++;
275     }
276   }
277
278   close(proc_fd);
279   return num_ports;
280 #elif WIN32
281   LPVOID error_msg;
282   DWORD table_size = 0;
283   PMIB_TCPTABLE tcp_table;
284   DWORD dwError;
285   
286   // WINXP and higher
287   //    AllocateAndGetTcpExTableFromStack(&tcp_table, TRUE, GetProcessHeap(), 2, 2);
288   
289   dwError = GetTcpTable(NULL, &table_size, TRUE);
290   if (dwError != ERROR_INSUFFICIENT_BUFFER) {
291     cerr << "Error: " <<dwError <<   endl;
292     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
293                    NULL, dwError, 
294                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
295                    (LPTSTR) &error_msg, 0, NULL );
296     cerr << (char *)error_msg << endl;
297     return -1;
298   }
299   
300   tcp_table = (PMIB_TCPTABLE)malloc(table_size);
301    
302   if (GetTcpTable(tcp_table, &table_size, TRUE)) {
303     return -1;
304   }
305   
306   *ports = (int *)malloc(sizeof(int) * tcp_table->dwNumEntries);
307   
308   for (unsigned int i = 0; i < tcp_table->dwNumEntries; i++) {
309     //cerr << htons((WORD)tcp_table->table[i].dwLocalPort) << endl;
310     (*ports)[i] = ntohs((WORD)tcp_table->table[i].dwLocalPort);
311   }
312   
313   return tcp_table->dwNumEntries;
314 #endif
315 }
316
317 int GetOpenUdpPorts(int ** ports) {
318 #ifdef linux
319   int proc_fd;
320   int num_ports = 0;
321   char more[512];
322   int local_port, rem_port, d, state, timer_run, uid, timeout;
323   unsigned long local_addr, rem_addr;
324   unsigned long rxq, txq, time_len, retr, inode;
325   int scan_num;
326   string proc_str;
327   /* 
328      We do this because we use realloc, 
329      so the first ptr-value must be null or we will realloc on some randome address
330   */
331   *ports = NULL;
332
333   proc_fd = open("/proc/net/udp", O_RDONLY);
334   if (proc_fd == -1) {
335
336     return -1;
337   }
338
339   GetLine(proc_fd, proc_str);
340  
341   while (GetLine(proc_fd, proc_str)) {
342     
343     // We pretty much stole this from netstat.c in the net-tools package
344     scan_num = sscanf(proc_str.c_str(),
345                  "%d: %lX:%X %lX:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
346                  &d, &local_addr, &local_port,
347                  &rem_addr, &rem_port, &state,
348                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
349     
350     
351
352     //printf("%s (%d)\n", ip_to_string(ntohl(local_addr)), local_port);
353     if (state == 0x07) {
354       *ports = (int *)realloc((*ports), sizeof(int) * (num_ports + 1));
355       
356       (*ports)[num_ports] = local_port;
357       
358       num_ports++;
359     }
360   }
361
362   close(proc_fd);
363   return num_ports;
364 #elif WIN32
365   LPVOID error_msg;
366   DWORD table_size = 0;
367   PMIB_UDPTABLE udp_table;
368   DWORD dwError;
369   
370   // WINXP and higher
371   //    AllocateAndGetTcpExTableFromStack(&tcp_table, TRUE, GetProcessHeap(), 2, 2);
372   
373   dwError = GetUdpTable(NULL, &table_size, TRUE);
374   if (dwError != ERROR_INSUFFICIENT_BUFFER) {
375     cerr << "Error: " <<dwError <<   endl;
376     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
377                    NULL, dwError, 
378                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
379                    (LPTSTR) &error_msg, 0, NULL );
380     cerr << (char *)error_msg << endl;
381     return -1;
382   }
383   
384   udp_table = (PMIB_UDPTABLE)malloc(table_size);
385    
386   if (GetUdpTable(udp_table, &table_size, TRUE)) {
387     return -1;
388   }
389   
390   *ports = (int *)malloc(sizeof(int) * udp_table->dwNumEntries);
391   
392   for (unsigned int i = 0; i < udp_table->dwNumEntries; i++) {
393     //cerr << htons((WORD)udp_table->table[i].dwLocalPort) << endl;
394     (*ports)[i] = ntohs((WORD)udp_table->table[i].dwLocalPort);
395   }
396   
397   return udp_table->dwNumEntries;
398 #endif
399 }
400
401
402
403 #define WELL_KNOWN_HOST ((char*)"www.cnn.com")
404 #define WELL_KNOWN_PORT 80
405
406 unsigned GetMyIPAddress() {
407   static unsigned adx = 0;
408   //static bool setup = false;
409   char * host;
410   short port;
411   SOCK fd;
412
413   host = getenv("RPS_WELL_KNOWN_HOST") ? getenv("RPS_WELL_KNOWN_HOST") : WELL_KNOWN_HOST;
414   port = getenv("RPS_WELL_KNOWN_PORT") ? atoi(getenv("RPS_WELL_KNOWN_PORT")) : WELL_KNOWN_PORT;
415
416   //  if (setup) {
417   //  return adx;
418   //  } else {
419     // Connect to a well known machine and check out our socket's address
420     if ((fd = CreateAndSetupTcpSocket()) == -1) {
421       return adx;
422     } else { 
423       if (ConnectToHost(fd, host, port) == -1) {
424         CLOSE(fd);
425         return adx;
426       }
427
428       adx = GetLocalSockAddress(fd);
429       
430       CLOSE(fd);  
431       return adx;
432     }
433     //}
434 }
435
436 SOCK CreateAndSetupUdpSocket(const int bufsize, const bool nonblocking) {
437   SOCK mysocket;
438   int val = 0;
439
440   // create socket for connections
441   if ((mysocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
442     return -1;
443   }
444     
445   // set reuseaddr to avoid binding problems
446   if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int))) {
447     return -1;
448   }
449   
450   val = bufsize;
451
452   if (setsockopt(mysocket, SOL_SOCKET, SO_SNDBUF,
453                  (const char*) &val, sizeof(val)) < 0) {
454     CLOSE(mysocket);
455     return -1;
456   }
457
458   val = bufsize;
459
460   if (setsockopt(mysocket, SOL_SOCKET, SO_RCVBUF,
461                  (const char*)&val, sizeof(val)) < 0) {
462     CLOSE(mysocket);
463     return -1;
464   }
465
466   if (nonblocking) {
467     val = 1;
468     if (IOCTL(mysocket, FIONBIO, &val)) {
469       CLOSE(mysocket);
470       return -1;
471     }
472   }
473
474   return mysocket;
475 }
476
477
478 SOCK CreateAndSetupTcpSocket(const int bufsize, const bool nodelay, const bool nonblocking) {
479   SOCK mysocket;
480   int val = 1;
481
482   // create socket for connections
483   if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
484     return -1;
485   }
486     
487   // set reuseaddr to avoid binding problems
488   if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int))) {
489     return -1;
490   }
491   
492   // Set nodelay so that our messages get
493   if (nodelay) {
494     val = 1;
495     if (setsockopt(mysocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&val, sizeof(int))) {
496       CLOSE(mysocket);
497       return -1;
498     }
499   }
500
501   val = bufsize;
502
503   if (setsockopt(mysocket, SOL_SOCKET, SO_SNDBUF,
504                  (const char*) &val, sizeof(val)) < 0) {
505     CLOSE(mysocket);
506     return -1;
507   }
508
509   val = bufsize;
510
511   if (setsockopt(mysocket, SOL_SOCKET, SO_RCVBUF,
512                  (const char*)&val, sizeof(val)) < 0) {
513     CLOSE(mysocket);
514     return -1;
515   }
516
517   if (nonblocking) {
518     val = 1;
519     if (IOCTL(mysocket, FIONBIO, &val)) {
520       CLOSE(mysocket);
521       return -1;
522     }
523   }
524
525   return mysocket;
526 }
527
528
529 SOCK CreateAndSetupUnixDomainSocket(const int bufsize, const bool nonblocking) {
530   SOCK mysocket;
531   int val;
532
533   // create socket for connections
534   if ((mysocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
535     return -1;
536   }
537     
538   // set reuseaddr to avoid binding problems
539   if (setsockopt(mysocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(int))) {
540     return -1;
541   }
542   
543   val = bufsize;
544
545   if (setsockopt(mysocket, SOL_SOCKET, SO_SNDBUF,
546                  (const char*)&val, sizeof(val)) < 0) {
547     CLOSE(mysocket);
548     return -1;
549   }
550
551   val = bufsize;
552
553   if (setsockopt(mysocket, SOL_SOCKET, SO_RCVBUF,
554                  (const char*)&val, sizeof(val)) < 0) {
555     CLOSE(mysocket);
556     return -1;
557   }
558
559   if (nonblocking) {
560     val = 1;
561     if (IOCTL(mysocket, FIONBIO, &val)) {
562       CLOSE(mysocket);
563       return -1;
564     }
565   }
566
567   return mysocket;
568 }
569
570
571 int SetNoDelaySocket(const SOCK fd, const bool nodelay) {
572   int val = nodelay == true;
573
574   // Set nodelay so that our messages get
575   return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&val, sizeof(int));
576 }
577
578
579 int BindSocket(const SOCK mysocket, const unsigned adx, const int myport) {  
580   struct sockaddr_in my_sa;
581
582   memset(&my_sa, 0, sizeof(my_sa));
583   my_sa.sin_port = htons(myport);
584   my_sa.sin_addr.s_addr = htonl(adx);
585   my_sa.sin_family = AF_INET;
586
587   if (bind(mysocket, (struct sockaddr *)&my_sa, sizeof(my_sa))) {
588     return -1;
589   }
590   return 0;
591 }
592
593 int BindSocket(const SOCK mysocket, const int myport) {
594   return BindSocket(mysocket, (unsigned)INADDR_ANY, myport);
595 }  
596
597 int BindSocket(const SOCK mysocket, const char *host_or_ip, const int myport) {
598   return BindSocket(mysocket, ToIPAddress(host_or_ip), myport);
599 }
600
601 int BindSocket(const SOCK mysocket, const char *pathname) {
602 #if defined(WIN32) && !defined(__CYGWIN__)
603   return -1;
604 #else 
605   struct sockaddr_un my_sa;
606   int len;
607  
608   memset(&my_sa, 0, sizeof(my_sa));
609   my_sa.sun_family = AF_UNIX;
610   strcpy(my_sa.sun_path, pathname);
611   len = strlen(my_sa.sun_path) + sizeof(my_sa.sun_family);
612
613   if (bind(mysocket, (struct sockaddr *)&my_sa,len)) {
614     return -1;
615   }
616   return 0;
617 #endif
618 }  
619
620
621 int ListenSocket(const SOCK mysocket, const int maxc) {
622   int maxcon = MIN(maxc, SOMAXCONN);
623   return listen(mysocket, maxcon);
624 }
625
626 int ConnectToHost(const SOCK mysocket, const int hostip, const int port) {
627   struct sockaddr_in sa;
628
629   memset(&sa, 0, sizeof(sa));
630   sa.sin_port = htons(port);
631   sa.sin_addr.s_addr = htonl(hostip);
632   sa.sin_family = AF_INET;
633
634   return connect(mysocket, (struct sockaddr *)&sa, sizeof(sa));
635 }
636   
637
638 int ConnectToHost(const SOCK mysocket, const char *host, const  int port) {
639   return ConnectToHost(mysocket, ToIPAddress(host), port);
640 }
641
642
643 int ConnectToPath(const SOCK mysocket, const char *pathname) {
644 #if defined(WIN32) && !defined(__CYGWIN__)
645   return -1;
646 #else 
647   struct sockaddr_un my_sa;
648   int len;
649
650   memset(&my_sa, 0, sizeof(my_sa));
651   my_sa.sun_family = AF_UNIX;
652   strcpy(my_sa.sun_path, pathname);
653   len = strlen(my_sa.sun_path) + sizeof(my_sa.sun_family);
654
655   if (connect(mysocket, (struct sockaddr *)&my_sa,len)) {
656     return -1;
657   }
658   return 0;
659 #endif
660 }
661   
662
663
664 int JoinMulticastGroup(const SOCK mysocket, const unsigned adx) {
665   if (!IsValidIPMulticastAddress(adx)) {
666     return -1;
667   }
668
669   struct ip_mreq req;
670
671   memset(&req, 0, sizeof(req));
672   
673   req.imr_multiaddr.s_addr = htonl(adx);
674   req.imr_interface.s_addr = htonl(INADDR_ANY);
675   
676   if (setsockopt(mysocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
677                  (const char*)&req, sizeof(req)) < 0) {
678     return -1;
679   }
680   return 0;
681 }
682
683 int JoinMulticastGroup(const SOCK mysocket, const char *IP) {
684   return JoinMulticastGroup(mysocket, ToIPAddress(IP));
685 }
686
687
688 int LeaveMulticastGroup(const SOCK mysocket, const unsigned adx) {
689   if (!IsValidIPMulticastAddress(adx)) {
690     return -1;
691   }
692
693   struct ip_mreq req;
694
695   memset(&req, 0, sizeof(req));
696   
697   req.imr_multiaddr.s_addr = htonl(adx);
698   req.imr_interface.s_addr = htonl(INADDR_ANY);
699   
700   if (setsockopt(mysocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
701                  (const char *) &req, sizeof(req)) < 0) {
702     return -1;
703   }
704
705   return 0;
706 }
707
708
709 int LeaveMulticastGroup(const SOCK mysocket, const char *IP) {
710   return LeaveMulticastGroup(mysocket, ToIPAddress(IP));
711 }
712
713
714
715 int SetMulticastTimeToLive(const SOCK mysocket, const unsigned char ttl) {
716   if (setsockopt(mysocket, IPPROTO_IP, IP_MULTICAST_TTL,
717                  (SOCKOPT_TYPE)&ttl, (SOCKOPT_LEN_TYPE)sizeof(ttl)) < 0) {
718     return -1;
719   }
720   return 0;
721 }
722
723 int SendTo(const SOCK mysocket, 
724            const unsigned ip, const int port, 
725            const char *buf, const int len, const bool sendall) {
726   struct sockaddr_in sa;
727   
728   memset(&sa, 0, sizeof(sockaddr_in));
729   sa.sin_family = AF_INET;
730   sa.sin_addr.s_addr = htonl(ip);
731   sa.sin_port = htons(port);
732   
733   if (!sendall) {
734     return sendto(mysocket, buf, len, 0, (struct sockaddr *)&sa, sizeof(sockaddr_in));
735   } else {
736     int left = len;
737     int sent;
738     while (left > 0) {
739       sent = sendto(mysocket, &(buf[len - left]), left, 0, (struct sockaddr *)&sa, sizeof(sockaddr_in));
740       if (sent < 0) {
741         if (errno == EINTR) {
742           continue;
743         } else {
744           return -1;
745         }
746       } else {
747         left -= sent;
748       }
749     }
750     return len;
751   }
752 }
753
754
755 int ReceiveFrom(const SOCK mysocket, 
756                 const unsigned ip, const int port, 
757                 char *buf, const int len,
758                 const bool recvall)
759 {
760   struct sockaddr_in sa;
761   SOCKOPT_LEN_TYPE size = sizeof(sockaddr_in);
762   
763   memset(&sa, 0, sizeof(sockaddr_in));
764   sa.sin_family = AF_INET;
765   sa.sin_addr.s_addr = htonl(ip);
766   sa.sin_port = htons(port);
767   
768   if (!recvall) {
769     return recvfrom(mysocket, buf, len, 0, (struct sockaddr *)&sa, &size);
770   } else {
771     int left = len;     
772     int received;
773     while (left > 0) {
774       received = recvfrom(mysocket, &(buf[len - left]), left, 0, (struct sockaddr *)&sa, &size);
775       if (received < 0) {
776         if (errno == EINTR) {
777           continue;
778         } else {
779           return -1;
780         }
781       } else if (received == 0) {
782         break;
783       } else {  
784         left -= received;
785       }
786     }
787     return len - left;
788   }
789 }
790
791 int SendTo(const SOCK mysocket, 
792            const char *host_or_ip, const int port, 
793            const char *buf, const int len, const bool sendall) {
794   return SendTo(mysocket, ToIPAddress(host_or_ip), port, buf, len, sendall);
795 }
796
797 int ReceiveFrom(const SOCK mysocket, 
798                 const char *host_or_ip, const int port, 
799                 char *buf, const int len, const bool recvall) {
800   return ReceiveFrom(mysocket, ToIPAddress(host_or_ip), port, buf, len, recvall);
801 }
802
803
804 #if defined(USE_SSL)
805
806 int Send(SOCK fd, SSL *ssl, const char *buf, const int len, const bool sendall) {
807   if (!sendall) {
808     if (ssl != NULL) {
809       return SSL_write(ssl, buf, len);
810     } else {
811       return write(fd, buf, len);
812     }
813   } else {
814     int left = len;
815     int sent;
816     while (left > 0) {
817       if (ssl != NULL) {
818         sent = SSL_write(ssl, &(buf[len - left]), left);
819       } else {
820         sent = write(fd, &(buf[len - left]), left);
821       }
822
823       if (sent < 0) {
824         if (errno == EINTR) {
825           continue;
826         } else {
827           return -1;
828         }
829       } else if (sent == 0) {
830         break;
831       } else {
832         left -= sent;
833       }
834     }
835     return len - left;
836   }
837 }
838
839 int Receive(SOCK fd, SSL *ssl, char *buf, const int len, const bool recvall) {
840   if (!recvall) {
841     if (ssl != NULL) {
842       return SSL_read(ssl, buf, len);
843     } else {
844       return read(fd, buf, len);
845     }
846   } else {
847     int left = len;     
848     int received;
849
850     while (left > 0) {
851       if (ssl != NULL) {
852         received = SSL_read(ssl, &(buf[len - left]), left);
853       } else {
854         received = read(fd, &(buf[len - left]), left);
855       }
856       
857       if (received < 0) {
858         if (errno == EINTR) {
859           continue;
860         } else {
861           return -1;
862         }
863       } else if (received == 0) {
864         return 0;
865       } else {  
866         left -= received;
867       }
868     }
869     return len - left;
870   }
871 }
872
873
874 int GetLine(SOCK fd, SSL *ssl, string &s) {
875   char c;
876   s.erase(s.begin(), s.end());
877   while (1) { 
878     int rc = Receive(fd, ssl, &c, 1, true);
879     if (rc < 0) { 
880       return rc;
881     } 
882     if ((rc == 0) || (c == '\n')) {
883       return s.size();
884     }
885     s += c;
886   }
887 }
888
889
890 int PutLine(SOCK fd, SSL *ssl, const string &s) {
891   string s2 = s;
892   s2 += '\n';
893   return (Send(fd, ssl, s2.c_str(), s2.size(), true) - 1);
894 }
895 #endif
896
897 int Send(SOCK fd,  const char *buf, const int len, const bool sendall) {
898   if (!sendall) {
899     return WRITE(fd, buf, len);
900   } else {
901     int left = len;
902     int sent;
903     while (left > 0) {
904       sent = WRITE(fd, &(buf[len - left]), left);
905
906       if (sent < 0) {
907         if (errno == EINTR) {
908           continue;
909         } else {
910           return -1;
911         }
912       } else if (sent == 0) {
913         break;
914       } else {
915         left -= sent;
916       }
917     }
918     return len - left;
919   }
920 }
921
922 int Receive(SOCK fd, char *buf, const int len, const bool recvall) {
923   if (!recvall) {
924     return READ(fd, buf, len);
925   } else {
926     int left = len;     
927     int received;
928
929     while (left > 0) {
930       received = READ(fd, &(buf[len - left]), left);
931       
932       if (received < 0) {
933         if (errno == EINTR) {
934           continue;
935         } else {
936           return -1;
937         }
938       } else if (received == 0) {
939         return 0;
940       } else {  
941         left -= received;
942       }
943     }
944     return len - left;
945   }
946 }
947
948
949 int GetLine(SOCK fd, string &s) {
950   char c;
951   s.erase(s.begin(), s.end());
952
953   while (1) { 
954     int rc = Receive(fd, &c, 1, true);
955
956     if (rc < 0) { 
957       return rc;
958     }
959
960     if ((rc == 0) || (c == '\n')) {
961       return s.size();
962     }
963
964     s += c;
965   }
966 }
967
968
969 int PutLine(SOCK fd, const string &s) {
970   string s2 = s;
971   s2 += '\n';
972   return (Send(fd, s2.c_str(), s2.size(), true) - 1);
973 }
974
975
976
977
978 int SetSignalHandler(const int signum, void (*handler)(int), const bool oneshot)
979 {
980 #if defined(WIN32) || defined(CYGWIN) // cygwin does not appear to have sigaction, so...
981   signal(signum,handler);  //notice that this is oneshot
982   return 0;
983 #else
984   struct sigaction sa;
985
986 #if defined(__sparc__)
987   sa.sa_handler= (void (*)(...)) handler;  // SUN FREAKS
988 #else
989   sa.sa_handler=handler;
990 #endif  
991
992   sigemptyset(&(sa.sa_mask));
993 #if defined(linux) 
994 #define SIGHAND_ONESHOT SA_ONESHOT
995 #endif
996 #if defined(__osf__) || defined(__FreeBSD__) || defined(__sparc__)
997 #define SIGHAND_ONESHOT SA_RESETHAND
998 #endif
999
1000   sa.sa_flags = ((oneshot == true) ? SIGHAND_ONESHOT : 0);
1001 #if defined(linux)
1002   sa.sa_restorer = 0;
1003 #endif
1004
1005   return sigaction(signum, &sa, 0);
1006 #endif
1007 }
1008
1009
1010 int IgnoreSignal(const int signum)
1011 {
1012   return SetSignalHandler(signum, SIG_IGN);
1013 }
1014
1015 int ListenToSignal(const int signum)
1016 {
1017   return SetSignalHandler(signum, SIG_DFL);
1018 }
1019
1020 #if defined(WIN32) && !defined(__CYGWIN__)
1021
1022 class SockInit {
1023 public:
1024   SockInit() { 
1025     WSADATA foo;
1026     WSAStartup(MAKEWORD(2,0),&foo);
1027   }
1028   ~SockInit() { 
1029     if (WSAIsBlocking()) {
1030       WSACancelBlockingCall();
1031     }
1032     WSACleanup();
1033   }
1034 };
1035
1036 SockInit thesockinit; // constructor should get called on startup.
1037 #endif
1038
1039