1 /***************************************************************************
2     begin       : Tue Oct 02 2002
3     copyright   : (C) 2019 by Martin Preuss
4     email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 
31 
32 #include "inetsocket_p.h"
33 #include "inetaddr_p.h"
34 #include <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <sys/time.h>
42 #include <sys/un.h>
43 
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #ifdef HAVE_ARPA_INET_H
48 # include <arpa/inet.h>
49 #endif
50 
51 
52 
GWEN_LIST_FUNCTIONS(GWEN_SOCKET,GWEN_Socket)53 GWEN_LIST_FUNCTIONS(GWEN_SOCKET, GWEN_Socket)
54 GWEN_LIST2_FUNCTIONS(GWEN_SOCKET, GWEN_Socket)
55 
56 
57 
58 int GWEN_Socket_ModuleInit(void)
59 {
60   return 0;
61 }
62 
63 
64 
GWEN_Socket_ModuleFini(void)65 int GWEN_Socket_ModuleFini(void)
66 {
67   return 0;
68 }
69 
70 
71 
72 
GWEN_Socket_NetError2GwenError(int rv)73 int GWEN_Socket_NetError2GwenError(int rv)
74 {
75   switch (rv) {
76   case EINTR:
77     return GWEN_ERROR_INTERRUPTED;
78   case ENOTCONN:
79   case EWOULDBLOCK:
80     return GWEN_ERROR_TIMEOUT;
81   case EACCES:
82   case EPERM:
83     return GWEN_ERROR_PERMISSIONS;
84   case ECONNREFUSED:
85     return GWEN_ERROR_CONN_REFUSED;
86   case EISCONN:
87     return GWEN_ERROR_OPEN;
88   case ENETUNREACH:
89     return GWEN_ERROR_NET_UNREACHABLE;
90   case ETIMEDOUT:
91     return GWEN_ERROR_NOT_OPEN;
92   case ENOTSOCK:
93     return GWEN_ERROR_INVALID;
94   default:
95     DBG_INFO(GWEN_LOGDOMAIN, "socket error: %d (%s)", rv, strerror(rv));
96     return GWEN_ERROR_IO;
97   }
98 }
99 
100 
101 
GWEN_SocketSet_Clear(GWEN_SOCKETSET * ssp)102 int GWEN_SocketSet_Clear(GWEN_SOCKETSET *ssp)
103 {
104   assert(ssp);
105   FD_ZERO(&(ssp->set));
106   ssp->highest=0;
107   return 0;
108 }
109 
110 
111 
GWEN_SocketSet_new(void)112 GWEN_SOCKETSET *GWEN_SocketSet_new(void)
113 {
114   GWEN_SOCKETSET *ssp;
115 
116   GWEN_NEW_OBJECT(GWEN_SOCKETSET, ssp);
117   FD_ZERO(&(ssp->set));
118   return ssp;
119 }
120 
121 
122 
GWEN_SocketSet_free(GWEN_SOCKETSET * ssp)123 void GWEN_SocketSet_free(GWEN_SOCKETSET *ssp)
124 {
125   if (ssp) {
126     FD_ZERO(&(ssp->set));
127     GWEN_FREE_OBJECT(ssp);
128   }
129 }
130 
131 
132 
GWEN_SocketSet_AddSocket(GWEN_SOCKETSET * ssp,const GWEN_SOCKET * sp)133 int GWEN_SocketSet_AddSocket(GWEN_SOCKETSET *ssp,
134                              const GWEN_SOCKET *sp)
135 {
136   assert(ssp);
137   assert(sp);
138   if (sp->socket==-1) {
139     DBG_INFO(GWEN_LOGDOMAIN, "Socket is not connected, can not add");
140     return GWEN_ERROR_NOT_OPEN;
141   }
142   ssp->highest=(ssp->highest<sp->socket)?sp->socket:ssp->highest;
143   FD_SET(sp->socket, &(ssp->set));
144   ssp->count++;
145   return 0;
146 }
147 
148 
149 
GWEN_SocketSet_RemoveSocket(GWEN_SOCKETSET * ssp,const GWEN_SOCKET * sp)150 int GWEN_SocketSet_RemoveSocket(GWEN_SOCKETSET *ssp,
151                                 const GWEN_SOCKET *sp)
152 {
153   assert(ssp);
154   assert(sp);
155   ssp->highest=(ssp->highest<sp->socket)?sp->socket:ssp->highest;
156   FD_CLR(sp->socket, &(ssp->set));
157   ssp->count--;
158   return 0;
159 }
160 
161 
162 
GWEN_SocketSet_HasSocket(GWEN_SOCKETSET * ssp,const GWEN_SOCKET * sp)163 int GWEN_SocketSet_HasSocket(GWEN_SOCKETSET *ssp,
164                              const GWEN_SOCKET *sp)
165 {
166   assert(ssp);
167   assert(sp);
168   return FD_ISSET(sp->socket, &(ssp->set));
169 }
170 
171 
172 
GWEN_SocketSet_GetSocketCount(GWEN_SOCKETSET * ssp)173 int GWEN_SocketSet_GetSocketCount(GWEN_SOCKETSET *ssp)
174 {
175   assert(ssp);
176   return ssp->count;
177 }
178 
179 
180 
181 
GWEN_Socket_new(GWEN_SOCKETTYPE socketType)182 GWEN_SOCKET *GWEN_Socket_new(GWEN_SOCKETTYPE socketType)
183 {
184   GWEN_SOCKET *sp;
185 
186   GWEN_NEW_OBJECT(GWEN_SOCKET, sp);
187   GWEN_LIST_INIT(GWEN_SOCKET, sp);
188   sp->type=socketType;
189   sp->isNonSocket=0;
190   return sp;
191 }
192 
193 
194 
GWEN_Socket_fromFile(int fd)195 GWEN_SOCKET *GWEN_Socket_fromFile(int fd)
196 {
197   GWEN_SOCKET *sp;
198 
199   GWEN_NEW_OBJECT(GWEN_SOCKET, sp);
200   GWEN_LIST_INIT(GWEN_SOCKET, sp);
201   sp->type=GWEN_SocketTypeFile;
202   sp->socket=fd;
203   sp->isNonSocket=1;
204   return sp;
205 }
206 
207 
208 
GWEN_Socket_free(GWEN_SOCKET * sp)209 void GWEN_Socket_free(GWEN_SOCKET *sp)
210 {
211   if (sp) {
212     GWEN_LIST_FINI(GWEN_SOCKET, sp);
213     GWEN_FREE_OBJECT(sp);
214   }
215 }
216 
217 
218 
GWEN_Socket_Open(GWEN_SOCKET * sp)219 int GWEN_Socket_Open(GWEN_SOCKET *sp)
220 {
221   int s;
222 
223   assert(sp);
224   switch (sp->type) {
225   case GWEN_SocketTypeTCP:
226 #ifdef PF_INET
227     s=socket(PF_INET, SOCK_STREAM, 0);
228 #else
229     s=socket(AF_INET, SOCK_STREAM, 0);
230 #endif
231     if (s==-1) {
232       DBG_INFO(GWEN_LOGDOMAIN, "socket(): %s", strerror(errno));
233       return GWEN_ERROR_IO;
234     }
235     sp->socket=s;
236     break;
237 
238   case GWEN_SocketTypeUDP:
239 #ifdef PF_INET
240     s=socket(PF_INET, SOCK_DGRAM, 0);
241 #else
242     s=socket(AF_INET, SOCK_DGRAM, 0);
243 #endif
244     if (s==-1)
245       if (s==-1) {
246         DBG_INFO(GWEN_LOGDOMAIN, "socket(): %s", strerror(errno));
247         return GWEN_ERROR_IO;
248       }
249     sp->socket=s;
250     break;
251 
252   case GWEN_SocketTypeUnix:
253 #ifdef PF_UNIX
254     s=socket(PF_UNIX, SOCK_STREAM, 0);
255 #else
256     s=socket(AF_UNIX, SOCK_STREAM, 0);
257 #endif
258     if (s==-1) {
259       DBG_INFO(GWEN_LOGDOMAIN, "socket(): %s", strerror(errno));
260       return GWEN_ERROR_IO;
261     }
262     sp->socket=s;
263     DBG_INFO(GWEN_LOGDOMAIN, "Created socket %d", sp->socket);
264     break;
265 
266   default:
267     return GWEN_ERROR_BAD_SOCKETTYPE;
268   } /* switch */
269 
270   return 0;
271 }
272 
273 
274 
GWEN_Socket_Connect(GWEN_SOCKET * sp,const GWEN_INETADDRESS * addr)275 int GWEN_Socket_Connect(GWEN_SOCKET *sp,
276                         const GWEN_INETADDRESS *addr)
277 {
278   assert(sp);
279   if (connect(sp->socket,
280               addr->address,
281               addr->size)) {
282     if (errno==EINPROGRESS) {
283       DBG_INFO(GWEN_LOGDOMAIN, "Connection delayed");
284       return GWEN_ERROR_IN_PROGRESS;
285     }
286     else {
287       DBG_INFO(GWEN_LOGDOMAIN, "connect(): %d (%s)", errno, strerror(errno));
288       return GWEN_Socket_NetError2GwenError(errno);
289     }
290   }
291   return 0;
292 }
293 
294 
295 
GWEN_Socket_Close(GWEN_SOCKET * sp)296 int GWEN_Socket_Close(GWEN_SOCKET *sp)
297 {
298   int rv;
299 
300   assert(sp);
301   if (sp->socket==-1)
302     return GWEN_ERROR_NOT_OPEN;
303 
304   DBG_INFO(GWEN_LOGDOMAIN, "Closing socket %d", sp->socket);
305   rv=close(sp->socket);
306   sp->socket=-1;
307   if (rv==-1) {
308     DBG_INFO(GWEN_LOGDOMAIN, "close(): %s", strerror(errno));
309     return GWEN_ERROR_IO;
310   }
311   return 0;
312 }
313 
314 
315 
GWEN_Socket_Bind(GWEN_SOCKET * sp,const GWEN_INETADDRESS * addr)316 int GWEN_Socket_Bind(GWEN_SOCKET *sp,
317                      const GWEN_INETADDRESS *addr)
318 {
319   assert(sp);
320   assert(addr);
321   if (bind(sp->socket,
322            addr->address,
323            addr->size)) {
324     DBG_INFO(GWEN_LOGDOMAIN, "bind(): %s", strerror(errno));
325     return GWEN_ERROR_IO;
326   }
327   return 0;
328 }
329 
330 
331 
GWEN_Socket_Listen(GWEN_SOCKET * sp,int backlog)332 int GWEN_Socket_Listen(GWEN_SOCKET *sp, int backlog)
333 {
334   assert(sp);
335   if (listen(sp->socket, backlog)) {
336     DBG_INFO(GWEN_LOGDOMAIN, "listen(): %s", strerror(errno));
337     return GWEN_ERROR_IO;
338   }
339   return 0;
340 }
341 
342 
343 
GWEN_Socket_Accept(GWEN_SOCKET * sp,GWEN_INETADDRESS ** newaddr,GWEN_SOCKET ** newsock)344 int GWEN_Socket_Accept(GWEN_SOCKET *sp,
345                        GWEN_INETADDRESS **newaddr,
346                        GWEN_SOCKET **newsock)
347 {
348   unsigned int addrlen;
349   GWEN_INETADDRESS *localAddr;
350   GWEN_SOCKET *localSocket;
351   GWEN_AddressFamily af;
352 
353   assert(sp);
354   assert(newsock);
355   assert(newaddr);
356 
357   switch (sp->type) {
358   case GWEN_SocketTypeTCP:
359   case GWEN_SocketTypeUDP:
360     af=GWEN_AddressFamilyIP;
361     break;
362   case GWEN_SocketTypeUnix:
363     af=GWEN_AddressFamilyUnix;
364     break;
365   default:
366     return GWEN_ERROR_BAD_SOCKETTYPE;
367   } /* switch */
368 
369   localAddr=GWEN_InetAddr_new(af);
370   addrlen=localAddr->size;
371   localSocket=GWEN_Socket_new(sp->type);
372   localSocket->socket=accept(sp->socket,
373                              localAddr->address,
374                              &addrlen);
375   if (localSocket->socket==-1) {
376     GWEN_InetAddr_free(localAddr);
377     GWEN_Socket_free(localSocket);
378     if (errno==EAGAIN || errno==ENOTCONN)
379       return GWEN_ERROR_TIMEOUT;
380     else {
381       DBG_INFO(GWEN_LOGDOMAIN, "accept(): %s", strerror(errno));
382       return GWEN_ERROR_IO;
383     }
384   }
385   localSocket->type=sp->type;
386   localAddr->size=addrlen;
387   *newaddr=localAddr;
388   *newsock=localSocket;
389   return 0;
390 }
391 
392 
393 
GWEN_Socket_GetPeerAddr(GWEN_SOCKET * sp,GWEN_INETADDRESS ** newaddr)394 int GWEN_Socket_GetPeerAddr(GWEN_SOCKET *sp,
395                             GWEN_INETADDRESS **newaddr)
396 {
397   unsigned int addrlen;
398   GWEN_INETADDRESS *localAddr;
399   GWEN_AddressFamily af;
400 
401   assert(sp);
402   assert(newaddr);
403 
404   switch (sp->type) {
405   case GWEN_SocketTypeTCP:
406   case GWEN_SocketTypeUDP:
407     af=GWEN_AddressFamilyIP;
408     break;
409   case GWEN_SocketTypeUnix:
410     af=GWEN_AddressFamilyUnix;
411     break;
412   default:
413     return GWEN_ERROR_BAD_SOCKETTYPE;
414   } /* switch */
415 
416   localAddr=GWEN_InetAddr_new(af);
417   addrlen=localAddr->size;
418 
419   if (getpeername(sp->socket,
420                   localAddr->address, &addrlen)) {
421     GWEN_InetAddr_free(localAddr);
422     DBG_INFO(GWEN_LOGDOMAIN, "getpeername(): %s", strerror(errno));
423     return GWEN_ERROR_IO;
424   }
425   localAddr->size=addrlen;
426   *newaddr=localAddr;
427   return 0;
428 }
429 
430 
431 
GWEN_Socket_Select(GWEN_SOCKETSET * rs,GWEN_SOCKETSET * ws,GWEN_SOCKETSET * xs,int timeout)432 int GWEN_Socket_Select(GWEN_SOCKETSET *rs,
433                        GWEN_SOCKETSET *ws,
434                        GWEN_SOCKETSET *xs,
435                        int timeout)
436 {
437   int h, h1, h2, h3;
438   fd_set *s1, *s2, *s3;
439   int rv;
440   struct timeval tv;
441 
442   s1=s2=s3=0;
443   h1=h2=h3=0;
444 
445   if (rs && rs->count) {
446     h1=rs->highest;
447     s1=&rs->set;
448   }
449   if (ws && ws->count) {
450     h2=ws->highest;
451     s2=&ws->set;
452   }
453   if (xs && xs->count) {
454     h3=xs->highest;
455     s3=&xs->set;
456   }
457   h=(h1>h2)?h1:h2;
458   h=(h>h3)?h:h3;
459   if (timeout<0) {
460     /* wait for ever */
461     rv=select(h+1, s1, s2, s3, 0);
462   }
463   else {
464     uint32_t tmicro;
465     uint32_t tsecs;
466 
467     tmicro=timeout*1000;
468     tsecs=tmicro/1000000UL;
469     tmicro%=1000000UL;
470     /* return immediately */
471     tv.tv_sec=tsecs;
472     tv.tv_usec=tmicro;
473 
474 #if 0
475     {
476       int i;
477 
478       if (s1) {
479         DBG_INFO(GWEN_LOGDOMAIN, "Read sockets: (%d/%d)", h1, h);
480         for (i=0; i<=h; i++) {
481           if (FD_ISSET(i, s1)) {
482             DBG_INFO(GWEN_LOGDOMAIN, "Found socket %d", i);
483           }
484         }
485       }
486 
487       if (s2) {
488         DBG_INFO(GWEN_LOGDOMAIN, "Write sockets: (%d/%d)", h2, h);
489         for (i=0; i<=h; i++) {
490           if (FD_ISSET(i, s2)) {
491             DBG_INFO(GWEN_LOGDOMAIN, "Found socket %d", i);
492           }
493         }
494       }
495 
496       DBG_INFO(GWEN_LOGDOMAIN, "Times: %ld/%ld",
497                tv.tv_sec, tv.tv_usec);
498       DBG_INFO(GWEN_LOGDOMAIN, "h=%d", h);
499     }
500 #endif
501 
502     rv=select(h+1, s1, s2, s3, &tv);
503   }
504 
505   if (rv<0) {
506     /* error */
507     if (errno==EINTR)
508       return GWEN_ERROR_INTERRUPTED;
509     else {
510       DBG_INFO(GWEN_LOGDOMAIN, "select(): %s", strerror(errno));
511       return GWEN_ERROR_IO;
512     }
513   }
514   if (rv==0)
515     /* timeout */
516     return GWEN_ERROR_TIMEOUT;
517   return 0;
518 }
519 
520 
521 
GWEN_Socket_Read(GWEN_SOCKET * sp,char * buffer,int * bsize)522 int GWEN_Socket_Read(GWEN_SOCKET *sp, char *buffer, int *bsize)
523 {
524   int i;
525 
526   assert(sp);
527   assert(buffer);
528   assert(bsize);
529   if (sp->isNonSocket)
530       i=read(sp->socket, buffer, *bsize);
531   else
532     i=recv(sp->socket, buffer, *bsize, 0);
533   if (i<0) {
534     if (errno==EAGAIN || errno==ENOTCONN)
535       return GWEN_ERROR_TIMEOUT;
536     else if (errno==EINTR)
537       return GWEN_ERROR_INTERRUPTED;
538     else {
539       DBG_INFO(GWEN_LOGDOMAIN, "recv(): %s", strerror(errno));
540       return GWEN_ERROR_IO;
541     }
542   }
543   *bsize=i;
544   return 0;
545 }
546 
547 
548 
GWEN_Socket_Write(GWEN_SOCKET * sp,const char * buffer,int * bsize)549 int GWEN_Socket_Write(GWEN_SOCKET *sp, const char *buffer, int *bsize)
550 {
551   int i;
552 
553   assert(sp);
554   assert(buffer);
555   assert(bsize);
556 
557   if (sp->isNonSocket)
558     i=write(sp->socket, buffer, *bsize);
559   else
560     i=send(sp->socket,
561 	   buffer,
562 	   *bsize,
563 	   0
564 #ifdef MSG_NOSIGNAL
565 	   | MSG_NOSIGNAL
566 #endif
567 #ifdef MSG_DONTWAIT
568 	   | MSG_DONTWAIT
569 #endif
570 	  );
571 
572   if (i<0) {
573     if (errno==EAGAIN || errno==ENOTCONN)
574       return GWEN_ERROR_TIMEOUT;
575     else if (errno==EINTR)
576       return GWEN_ERROR_INTERRUPTED;
577     else {
578       DBG_INFO(GWEN_LOGDOMAIN, "send(): %d (%s)", errno, strerror(errno));
579       return GWEN_ERROR_IO;
580     }
581   }
582   *bsize=i;
583   return 0;
584 }
585 
586 
587 
GWEN_Socket_ReadFrom(GWEN_SOCKET * sp,GWEN_INETADDRESS ** newaddr,char * buffer,int * bsize)588 int GWEN_Socket_ReadFrom(GWEN_SOCKET *sp,
589                          GWEN_INETADDRESS **newaddr,
590                          char *buffer,
591                          int *bsize)
592 {
593   unsigned int addrlen;
594   int i;
595   GWEN_INETADDRESS *localAddr;
596   GWEN_AddressFamily af;
597 
598   assert(sp);
599   assert(newaddr);
600   assert(buffer);
601   assert(bsize);
602 
603   switch (sp->type) {
604   case GWEN_SocketTypeTCP:
605   case GWEN_SocketTypeUDP:
606     af=GWEN_AddressFamilyIP;
607     break;
608   case GWEN_SocketTypeUnix:
609     af=GWEN_AddressFamilyUnix;
610     break;
611   default:
612     return GWEN_ERROR_BAD_SOCKETTYPE;
613   } /* switch */
614 
615   localAddr=GWEN_InetAddr_new(af);
616   addrlen=localAddr->size;
617 
618   i=recvfrom(sp->socket,
619              buffer,
620              *bsize,
621              0,
622              localAddr->address,
623              &addrlen);
624   if (i<0) {
625     GWEN_InetAddr_free(localAddr);
626     if (errno==EAGAIN || errno==ENOTCONN)
627       return GWEN_ERROR_TIMEOUT;
628     else if (errno==EINTR)
629       return GWEN_ERROR_INTERRUPTED;
630     else {
631       DBG_INFO(GWEN_LOGDOMAIN, "recvfrom(): %s", strerror(errno));
632       return GWEN_ERROR_IO;
633     }
634   }
635   *bsize=i;
636   localAddr->size=addrlen;
637   *newaddr=localAddr;
638   return 0;
639 }
640 
641 
642 
GWEN_Socket_WriteTo(GWEN_SOCKET * sp,const GWEN_INETADDRESS * addr,const char * buffer,int * bsize)643 int GWEN_Socket_WriteTo(GWEN_SOCKET *sp,
644                         const GWEN_INETADDRESS *addr,
645                         const char *buffer,
646                         int *bsize)
647 {
648   int i;
649 
650   assert(sp);
651   assert(addr);
652   assert(buffer);
653   assert(bsize);
654   i=sendto(sp->socket,
655            buffer,
656            *bsize,
657 #ifndef MSG_NOSIGNAL
658            0,
659 #else
660            MSG_NOSIGNAL,
661 #endif
662            addr->address,
663            addr->size);
664   if (i<0) {
665     if (errno==EAGAIN || errno==ENOTCONN)
666       return GWEN_ERROR_TIMEOUT;
667     else if (errno==EINTR)
668       return GWEN_ERROR_INTERRUPTED;
669     else {
670       DBG_INFO(GWEN_LOGDOMAIN, "sendto(): %s", strerror(errno));
671       return GWEN_ERROR_IO;
672     }
673   }
674   *bsize=i;
675   return 0;
676 }
677 
678 
679 
GWEN_Socket_SetBlocking(GWEN_SOCKET * sp,int fl)680 int GWEN_Socket_SetBlocking(GWEN_SOCKET *sp, int fl)
681 {
682   int prevFlags;
683   int newFlags;
684 
685   assert(sp);
686   /* get current socket flags */
687   prevFlags=fcntl(sp->socket, F_GETFL);
688   if (prevFlags==-1) {
689     DBG_INFO(GWEN_LOGDOMAIN, "fcntl(): %s", strerror(errno));
690     return GWEN_ERROR_IO;
691   }
692 
693   /* set nonblocking/blocking */
694   if (fl)
695     newFlags=prevFlags&(~O_NONBLOCK);
696   else
697     newFlags=prevFlags|O_NONBLOCK;
698 
699   if (-1==fcntl(sp->socket, F_SETFL, newFlags)) {
700     DBG_INFO(GWEN_LOGDOMAIN, "fcntl(): %s", strerror(errno));
701     return GWEN_ERROR_IO;
702   }
703   prevFlags=fcntl(sp->socket, F_GETFL);
704   if (prevFlags!=newFlags) {
705     DBG_ERROR(GWEN_LOGDOMAIN,
706               "fcntl() did not set flags correctly (%08x!=%08x)",
707               prevFlags, newFlags);
708     return GWEN_ERROR_IO;
709   }
710 
711   return 0;
712 }
713 
714 
715 
GWEN_Socket_SetBroadcast(GWEN_SOCKET * sp,int fl)716 int GWEN_Socket_SetBroadcast(GWEN_SOCKET *sp, int fl)
717 {
718   assert(sp);
719   if (sp->type==GWEN_SocketTypeUnix)
720     return 0;
721   if (setsockopt(sp->socket,
722                  SOL_SOCKET,
723                  SO_BROADCAST,
724                  &fl,
725                  sizeof(fl))) {
726     DBG_INFO(GWEN_LOGDOMAIN, "setsockopt(): %s", strerror(errno));
727     return GWEN_ERROR_IO;
728   }
729   return 0;
730 }
731 
732 
733 
GWEN_Socket_SetReuseAddress(GWEN_SOCKET * sp,int fl)734 int GWEN_Socket_SetReuseAddress(GWEN_SOCKET *sp, int fl)
735 {
736   assert(sp);
737 
738   /*if (sp->type==SocketTypeUnix)
739     return 0;*/
740 
741   if (setsockopt(sp->socket,
742                  SOL_SOCKET,
743                  SO_REUSEADDR,
744                  &fl,
745                  sizeof(fl))) {
746     DBG_INFO(GWEN_LOGDOMAIN, "setsockopt(): %s", strerror(errno));
747     return GWEN_ERROR_IO;
748   }
749   return 0;
750 }
751 
752 
753 
GWEN_Socket_GetSocketError(GWEN_SOCKET * sp)754 int GWEN_Socket_GetSocketError(GWEN_SOCKET *sp)
755 {
756   int rv;
757   unsigned int rvs;
758 
759   assert(sp);
760   rvs=sizeof(rv);
761   if (-1==getsockopt(sp->socket, SOL_SOCKET, SO_ERROR, &rv, &rvs)) {
762     DBG_INFO(GWEN_LOGDOMAIN, "getsockopt(): %s", strerror(errno));
763     return GWEN_ERROR_IO;
764   }
765 
766   if (rv)
767     return GWEN_Socket_NetError2GwenError(rv);
768   return 0;
769 }
770 
771 
772 
GWEN_Socket_WaitForRead(GWEN_SOCKET * sp,int timeout)773 int GWEN_Socket_WaitForRead(GWEN_SOCKET *sp, int timeout)
774 {
775   int err;
776   GWEN_SOCKETSET *set;
777 
778   set=GWEN_SocketSet_new();
779 
780   err=GWEN_SocketSet_AddSocket(set, sp);
781   if (err) {
782     GWEN_SocketSet_free(set);
783     return err;
784   }
785   err=GWEN_Socket_Select(set, 0, 0, timeout);
786   GWEN_SocketSet_free(set);
787 
788   return err;
789 }
790 
791 
792 
GWEN_Socket_WaitForWrite(GWEN_SOCKET * sp,int timeout)793 int GWEN_Socket_WaitForWrite(GWEN_SOCKET *sp, int timeout)
794 {
795   int err;
796   GWEN_SOCKETSET *set;
797 
798   set=GWEN_SocketSet_new();
799   err=GWEN_SocketSet_AddSocket(set, sp);
800   if (err) {
801     GWEN_SocketSet_free(set);
802     return err;
803   }
804   err=GWEN_Socket_Select(0, set, 0, timeout);
805   GWEN_SocketSet_free(set);
806 
807   return err;
808 }
809 
810 
811 
GWEN_Socket_GetSocketType(GWEN_SOCKET * sp)812 GWEN_SOCKETTYPE GWEN_Socket_GetSocketType(GWEN_SOCKET *sp)
813 {
814   assert(sp);
815   return sp->type;
816 }
817 
818 
819 
GWEN_Socket_GetSocketInt(const GWEN_SOCKET * sp)820 int GWEN_Socket_GetSocketInt(const GWEN_SOCKET *sp)
821 {
822   assert(sp);
823   return sp->socket;
824 }
825 
826 
827 
828