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