]> git.saurik.com Git - wxWidgets.git/blob - src/os2/gsocket.c
Integrated recent API-change
[wxWidgets.git] / src / os2 / gsocket.c
1 /* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Purpose: GSocket main Unix-style file
5 * CVSID: $Id$
6 * -------------------------------------------------------------------------
7 */
8
9 #include "wx/setup.h"
10 #ifndef __EMX__
11 /* I don't see, why this include is needed, but it seems to be necessary
12 sometimes. For EMX, including C++ headers into plain C source breaks
13 compilation, so don't do it there. */
14 #include "wx/defs.h"
15 #endif
16
17 #if wxUSE_SOCKETS
18
19 #define BSD_SELECT /* use Berkley Sockets select */
20
21 #include <assert.h>
22 #include <sys\types.h>
23 #ifdef __EMX__
24 #include <sys/time.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <netdb.h>
28 #include <errno.h>
29 #define HAVE_INET_ADDR
30 #else
31 #include <utils.h>
32 #include <sys\time.h>
33 #include <in.h>
34 #include <netdb.h>
35 #include <nerrno.h>
36 #endif
37 #if defined(__VISAGECPP__) && __IBMCPP__ < 400
38 #include <socket.h>
39 #include <ioctl.h>
40 #include <select.h>
41 #else
42 #include <sys\socket.h>
43 #include <sys\ioctl.h>
44 #include <sys\select.h>
45 #ifndef __EMX__
46 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
47 int _System bsdselect(int,
48 struct fd_set *,
49 struct fd_set *,
50 struct fd_set *,
51 struct timeval *);
52 int _System soclose(int);
53 #endif
54 #endif
55
56 #include <string.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <stddef.h>
60 #include <ctype.h>
61
62 #include <signal.h>
63
64 #include "wx/gsocket.h"
65 #include "wx/os2/gsockos2.h"
66
67 #ifndef SOCKLEN_T
68
69 #ifdef __GLIBC__
70 # if __GLIBC__ == 2
71 # define SOCKLEN_T socklen_t
72 # endif
73 #else
74 # define SOCKLEN_T int
75 #endif
76
77 #endif
78
79 /* Global initialisers */
80
81 bool GSocket_Init()
82 {
83 return TRUE;
84 }
85
86 void GSocket_Cleanup()
87 {
88 }
89
90 /* Constructors / Destructors */
91
92 GSocket *GSocket_new()
93 {
94 int i;
95 GSocket *socket;
96
97 socket = (GSocket *)malloc(sizeof(GSocket));
98
99 if (socket == NULL)
100 return NULL;
101
102 socket->m_fd = -1;
103 for (i=0;i<GSOCK_MAX_EVENT;i++)
104 {
105 socket->m_cbacks[i] = NULL;
106 }
107 socket->m_detected = 0;
108 socket->m_local = NULL;
109 socket->m_peer = NULL;
110 socket->m_error = GSOCK_NOERROR;
111 socket->m_server = FALSE;
112 socket->m_stream = TRUE;
113 socket->m_gui_dependent = NULL;
114 socket->m_non_blocking = FALSE;
115 socket->m_timeout = 10*60*1000;
116 /* 10 minutes * 60 sec * 1000 millisec */
117 socket->m_establishing = FALSE;
118
119 /* We initialize the GUI specific entries here */
120 _GSocket_GUI_Init(socket);
121
122 return socket;
123 }
124
125 void GSocket_destroy(GSocket *socket)
126 {
127 assert(socket != NULL);
128
129 /* First, we check that the socket is really shutdowned */
130 if (socket->m_fd != -1)
131 GSocket_Shutdown(socket);
132
133 /* We destroy GUI specific variables */
134 _GSocket_GUI_Destroy(socket);
135
136 /* We destroy private addresses */
137 if (socket->m_local)
138 GAddress_destroy(socket->m_local);
139
140 if (socket->m_peer)
141 GAddress_destroy(socket->m_peer);
142
143 /* We destroy socket itself */
144 free(socket);
145 }
146
147 void GSocket_Shutdown(GSocket *socket)
148 {
149 int evt;
150
151 assert(socket != NULL);
152
153 /* If socket has been created, we shutdown it */
154 if (socket->m_fd != -1)
155 {
156 shutdown(socket->m_fd, 2);
157 soclose(socket->m_fd);
158 socket->m_fd = -1;
159 }
160
161 /* We also disable GUI callbacks */
162 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
163 socket->m_cbacks[evt] = NULL;
164
165 socket->m_detected = 0;
166 _GSocket_Disable_Events(socket);
167 }
168
169 /* Address handling */
170
171 GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
172 {
173 assert(socket != NULL);
174
175 if ((socket->m_fd != -1 && !socket->m_server)) {
176 socket->m_error = GSOCK_INVSOCK;
177 return GSOCK_INVSOCK;
178 }
179
180 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
181 socket->m_error = GSOCK_INVADDR;
182 return GSOCK_INVADDR;
183 }
184
185 if (socket->m_local)
186 GAddress_destroy(socket->m_local);
187
188 socket->m_local = GAddress_copy(address);
189
190 return GSOCK_NOERROR;
191 }
192
193 GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
194 {
195 assert(socket != NULL);
196
197 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
198 socket->m_error = GSOCK_INVADDR;
199 return GSOCK_INVADDR;
200 }
201
202 if (socket->m_peer)
203 GAddress_destroy(socket->m_peer);
204
205 socket->m_peer = GAddress_copy(address);
206
207 return GSOCK_NOERROR;
208 }
209
210 GAddress *GSocket_GetLocal(GSocket *socket)
211 {
212 GAddress *address;
213 struct sockaddr addr;
214 SOCKLEN_T size;
215 GSocketError err;
216
217 assert(socket != NULL);
218
219 if (socket->m_local)
220 return GAddress_copy(socket->m_local);
221
222 if (socket->m_fd == -1) {
223 socket->m_error = GSOCK_INVSOCK;
224 return NULL;
225 }
226
227 size = sizeof(addr);
228
229 if (getsockname(socket->m_fd, &addr, &size) < 0) {
230 socket->m_error = GSOCK_IOERR;
231 return NULL;
232 }
233
234 address = GAddress_new();
235 if (address == NULL) {
236 socket->m_error = GSOCK_MEMERR;
237 return NULL;
238 }
239 socket->m_error = _GAddress_translate_from(address, &addr, size);
240 if (socket->m_error != GSOCK_NOERROR) {
241 GAddress_destroy(address);
242 return NULL;
243 }
244
245 return address;
246 }
247
248 GAddress *GSocket_GetPeer(GSocket *socket)
249 {
250 assert(socket != NULL);
251
252 if (socket->m_peer)
253 return GAddress_copy(socket->m_peer);
254
255 return NULL;
256 }
257
258 /* Server specific parts */
259
260 /* GSocket_SetServer:
261 * Sets up the socket as a server. It uses the "Local" field of GSocket.
262 * "Local" must be set by GSocket_SetLocal() before GSocket_SetServer()
263 * is called. Possible error codes are: GSOCK_INVSOCK if socket has not
264 * been initialized, GSOCK_INVADDR if the local address has not been
265 * defined and GSOCK_IOERR for other internal errors.
266 */
267 GSocketError GSocket_SetServer(GSocket *sck)
268 {
269 int type;
270 int arg = 1;
271
272 assert(sck != NULL);
273
274 if (sck->m_fd != -1) {
275 sck->m_error = GSOCK_INVSOCK;
276 return GSOCK_INVSOCK;
277 }
278
279 if (!sck->m_local) {
280 sck->m_error = GSOCK_INVADDR;
281 return GSOCK_INVADDR;
282 }
283
284 /* We always have a stream here */
285 sck->m_stream = TRUE;
286 sck->m_server = TRUE;
287
288 /* Create the socket */
289 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
290
291 if (sck->m_fd == -1) {
292 sck->m_error = GSOCK_IOERR;
293 return GSOCK_IOERR;
294 }
295
296 ioctl(sck->m_fd, FIONBIO, (char*)&arg, sizeof(int));
297 _GSocket_Enable_Events(sck);
298
299 /* Bind the socket to the LOCAL address */
300 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
301 soclose(sck->m_fd);
302 sck->m_fd = -1;
303 sck->m_error = GSOCK_IOERR;
304 return GSOCK_IOERR;
305 }
306
307 /* Enable listening up to 5 connections */
308 if (listen(sck->m_fd, 5) < 0) {
309 soclose(sck->m_fd);
310 sck->m_fd = -1;
311 sck->m_error = GSOCK_IOERR;
312 return GSOCK_IOERR;
313 }
314
315 return GSOCK_NOERROR;
316 }
317
318 /* GSocket_WaitConnection:
319 * Waits for an incoming client connection.
320 */
321 GSocket *GSocket_WaitConnection(GSocket *socket)
322 {
323 GSocket *connection;
324 int arg = 1;
325
326 assert(socket != NULL);
327
328 /* Reenable CONNECTION events */
329 _GSocket_Enable(socket, GSOCK_CONNECTION);
330
331 /* If the socket has already been created, we exit immediately */
332 if (socket->m_fd == -1 || !socket->m_server)
333 {
334 socket->m_error = GSOCK_INVSOCK;
335 return NULL;
336 }
337
338 /* Create a GSocket object for the new connection */
339 connection = GSocket_new();
340 if (!connection)
341 {
342 connection->m_error = GSOCK_MEMERR;
343 return NULL;
344 }
345
346 /* Accept the incoming connection */
347 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
348 {
349 GSocket_destroy(connection);
350 /* socket->m_error set by _GSocket_Input_Timeout */
351 return NULL;
352 }
353
354 connection->m_fd = accept(socket->m_fd, NULL, NULL);
355
356 if (connection->m_fd == -1)
357 {
358 if (errno == EWOULDBLOCK)
359 socket->m_error = GSOCK_WOULDBLOCK;
360 else
361 socket->m_error = GSOCK_IOERR;
362
363 GSocket_destroy(connection);
364 return NULL;
365 }
366
367 /* Initialize all fields */
368 connection->m_server = FALSE;
369 connection->m_stream = TRUE;
370 connection->m_oriented = TRUE;
371
372 ioctl(connection->m_fd, FIONBIO, (char*)&arg, sizeof(int));
373 _GSocket_Enable_Events(connection);
374
375 return connection;
376 }
377
378 /* Non oriented connections */
379
380 GSocketError GSocket_SetNonOriented(GSocket *sck)
381 {
382 int arg = 1;
383
384 assert(sck != NULL);
385
386 if (sck->m_fd != -1) {
387 sck->m_error = GSOCK_INVSOCK;
388 return GSOCK_INVSOCK;
389 }
390
391 if (!sck->m_local) {
392 sck->m_error = GSOCK_INVADDR;
393 return GSOCK_INVADDR;
394 }
395
396 sck->m_stream = FALSE;
397 sck->m_server = FALSE;
398 sck->m_oriented = FALSE;
399
400 /* Create the socket */
401 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
402
403 if (sck->m_fd < 0) {
404 sck->m_error = GSOCK_IOERR;
405 return GSOCK_IOERR;
406 }
407
408 ioctl(sck->m_fd, FIONBIO, (char*)&arg, sizeof(int));
409 _GSocket_Enable_Events(sck);
410
411 /* Bind it to the LOCAL address */
412 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
413 soclose(sck->m_fd);
414 sck->m_fd = -1;
415 sck->m_error = GSOCK_IOERR;
416 return GSOCK_IOERR;
417 }
418
419 return GSOCK_NOERROR;
420 }
421
422 /* Client specific parts */
423
424 /* GSocket_Connect:
425 * Establishes a client connection to a server using the "Peer"
426 * field of GSocket. "Peer" must be set by GSocket_SetPeer() before
427 * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK,
428 * GSOCK_INVADDR, GSOCK_TIMEDOUT, GSOCK_WOULDBLOCK and GSOCK_IOERR.
429 * If a socket is nonblocking and Connect() returns GSOCK_WOULDBLOCK,
430 * the connection request can be completed later. Use GSocket_Select()
431 * to check or wait for a GSOCK_CONNECTION event.
432 */
433 GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
434 {
435 int type, err, ret;
436 int arg = 1;
437
438 assert(sck != NULL);
439
440 /* Enable CONNECTION events (needed for nonblocking connections) */
441 _GSocket_Enable(sck, GSOCK_CONNECTION);
442
443 if (sck->m_fd != -1)
444 {
445 sck->m_error = GSOCK_INVSOCK;
446 return GSOCK_INVSOCK;
447 }
448
449 if (!sck->m_peer)
450 {
451 sck->m_error = GSOCK_INVADDR;
452 return GSOCK_INVADDR;
453 }
454
455 /* Test whether we want the socket to be a stream (e.g. TCP) */
456 sck->m_stream = (stream == GSOCK_STREAMED);
457 sck->m_oriented = TRUE;
458 sck->m_server = FALSE;
459 sck->m_establishing = FALSE;
460
461 if (sck->m_stream)
462 type = SOCK_STREAM;
463 else
464 type = SOCK_DGRAM;
465
466 /* Create the socket */
467 sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0);
468
469 if (sck->m_fd == -1) {
470 sck->m_error = GSOCK_IOERR;
471 return GSOCK_IOERR;
472 }
473
474 ioctl(sck->m_fd, FIONBIO, (char*)&arg, sizeof(int));
475 _GSocket_Enable_Events(sck);
476
477 /* Connect it to the PEER address */
478 ret = connect(sck->m_fd, sck->m_peer->m_addr, sck->m_peer->m_len);
479
480 if (ret == -1)
481 {
482 err = errno;
483
484 /* If connect failed with EINPROGRESS and the GSocket object
485 * is in blocking mode, we select() for the specified timeout
486 * checking for writability to see if the connection request
487 * completes.
488 */
489 if ((err == EINPROGRESS) && (!sck->m_non_blocking))
490 {
491 if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT)
492 {
493 soclose(sck->m_fd);
494 sck->m_fd = -1;
495 /* sck->m_error is set in _GSocket_Output_Timeout */
496 fprintf(stderr, "Blocking connect timeouts\n");
497 return GSOCK_TIMEDOUT;
498 }
499 else
500 {
501 fprintf(stderr, "Blocking connect OK\n");
502 return GSOCK_NOERROR;
503 }
504 }
505
506 /* If connect failed with EINPROGRESS and the GSocket object
507 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
508 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
509 * this way if the connection completes, a GSOCK_CONNECTION
510 * event will be generated, if enabled.
511 */
512 if ((err == EINPROGRESS) && (sck->m_non_blocking))
513 {
514 sck->m_error = GSOCK_WOULDBLOCK;
515 sck->m_establishing = TRUE;
516 fprintf(stderr, "Nonblocking connect in progress\n");
517
518 return GSOCK_WOULDBLOCK;
519 }
520
521 /* If connect failed with an error other than EINPROGRESS,
522 * then the call to GSocket_Connect has failed.
523 */
524 soclose(sck->m_fd);
525 sck->m_fd = -1;
526 sck->m_error = GSOCK_IOERR;
527
528 fprintf(stderr, "Connect failed (generic err)\n");
529 return GSOCK_IOERR;
530 }
531
532 fprintf(stderr, "Connect OK\n");
533 return GSOCK_NOERROR;
534 }
535
536 /* Generic IO */
537
538 /* Like recv(), send(), ... */
539 int GSocket_Read(GSocket *socket, char *buffer, int size)
540 {
541 int ret;
542
543 assert(socket != NULL);
544
545 /* Reenable INPUT events */
546 _GSocket_Enable(socket, GSOCK_INPUT);
547
548 if (socket->m_fd == -1 || socket->m_server)
549 {
550 socket->m_error = GSOCK_INVSOCK;
551 return -1;
552 }
553
554 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
555 return -1;
556
557 if (socket->m_stream)
558 ret = _GSocket_Recv_Stream(socket, buffer, size);
559 else
560 ret = _GSocket_Recv_Dgram(socket, buffer, size);
561
562 if (ret == -1)
563 {
564 if (errno == EWOULDBLOCK)
565 socket->m_error = GSOCK_WOULDBLOCK;
566 else
567 socket->m_error = GSOCK_IOERR;
568 }
569
570 return ret;
571 }
572
573 int GSocket_Write(GSocket *socket, const char *buffer,
574 int size)
575 {
576 int ret;
577
578 assert(socket != NULL);
579
580 if (socket->m_fd == -1 || socket->m_server)
581 {
582 socket->m_error = GSOCK_INVSOCK;
583 return -1;
584 }
585
586 if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
587 return -1;
588
589 if (socket->m_stream)
590 ret = _GSocket_Send_Stream(socket, buffer, size);
591 else
592 ret = _GSocket_Send_Dgram(socket, buffer, size);
593
594 if (ret == -1)
595 {
596 if (errno == EWOULDBLOCK)
597 socket->m_error = GSOCK_WOULDBLOCK;
598 else
599 socket->m_error = GSOCK_IOERR;
600
601 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
602 * in MSW). Once the first OUTPUT event is received, users can assume
603 * that the socket is writable until a read operation fails. Only then
604 * will further OUTPUT events be posted.
605 */
606 _GSocket_Enable(socket, GSOCK_OUTPUT);
607 }
608
609 return ret;
610 }
611
612 /* GSocket_Select:
613 * Polls the socket to determine its status. This function will
614 * check for the events specified in the 'flags' parameter, and
615 * it will return a mask indicating which operations can be
616 * performed. This function won't block, regardless of the
617 * mode (blocking|nonblocking) of the socket.
618 */
619 GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
620 {
621 assert(socket != NULL);
622
623 return (flags & socket->m_detected);
624 }
625
626 /* Flags */
627
628 /* GSocket_SetNonBlocking:
629 * Sets the socket to non-blocking mode. This is useful if
630 * we don't want to wait.
631 */
632 void GSocket_SetNonBlocking(GSocket *socket, bool non_block)
633 {
634 assert(socket != NULL);
635
636 socket->m_non_blocking = non_block;
637 }
638
639 /* GSocket_SetTimeout:
640 * Sets the timeout for blocking calls. Time is
641 * expressed in milliseconds.
642 */
643 void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
644 {
645 assert(socket != NULL);
646
647 socket->m_timeout = millisec;
648 }
649
650 /* GSocket_GetError:
651 * Returns the last error occured for this socket.
652 */
653 GSocketError GSocket_GetError(GSocket *socket)
654 {
655 assert(socket != NULL);
656
657 return socket->m_error;
658 }
659
660 /* Callbacks */
661
662 /* Only one callback is possible for each event (INPUT, OUTPUT, CONNECTION
663 * and LOST). The callbacks are called in the following situations:
664 *
665 * INPUT: There is at least one byte in the input buffer
666 * OUTPUT: The system is sure that the next write call will not block
667 * CONNECTION: Two cases are possible:
668 * Client socket -> the connection is established
669 * Server socket -> a client requests a connection
670 * LOST: The connection is lost
671 *
672 * An event is generated only once and its state is reseted when the
673 * relative IO call is requested.
674 * For example: INPUT -> GSocket_Read()
675 * CONNECTION -> GSocket_Accept()
676 */
677
678 /* GSocket_SetCallback:
679 * Enables the callbacks specified by 'flags'. Note that 'flags'
680 * may be a combination of flags OR'ed toghether, so the same
681 * callback function can be made to accept different events.
682 * The callback function must have the following prototype:
683 *
684 * void function(GSocket *socket, GSocketEvent event, char *cdata)
685 */
686 void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
687 GSocketCallback callback, char *cdata)
688 {
689 int count;
690
691 assert(socket != NULL);
692
693 for (count = 0; count < GSOCK_MAX_EVENT; count++)
694 {
695 if ((flags & (1 << count)) != 0)
696 {
697 socket->m_cbacks[count] = callback;
698 socket->m_data[count] = cdata;
699 }
700 }
701 }
702
703 /* GSocket_UnsetCallback:
704 * Disables all callbacks specified by 'flags', which may be a
705 * combination of flags OR'ed toghether.
706 */
707 void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
708 {
709 int count;
710
711 assert(socket != NULL);
712
713 for (count = 0; count < GSOCK_MAX_EVENT; count++)
714 {
715 if ((flags & (1 << count)) != 0)
716 {
717 socket->m_cbacks[count] = NULL;
718 socket->m_data[count] = NULL;
719 }
720 }
721 }
722
723 #define CALL_CALLBACK(socket, event) { \
724 _GSocket_Disable(socket, event); \
725 if (socket->m_cbacks[event]) \
726 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
727 }
728
729
730 void _GSocket_Enable(GSocket *socket, GSocketEvent event)
731 {
732 socket->m_detected &= ~(1 << event);
733 _GSocket_Install_Callback(socket, event);
734 }
735
736 void _GSocket_Disable(GSocket *socket, GSocketEvent event)
737 {
738 socket->m_detected |= (1 << event);
739 _GSocket_Uninstall_Callback(socket, event);
740 }
741
742 /* _GSocket_Input_Timeout:
743 * For blocking sockets, wait until data is available or
744 * until timeout ellapses.
745 */
746 GSocketError _GSocket_Input_Timeout(GSocket *socket)
747 {
748 struct timeval tv;
749 fd_set readfds;
750
751 tv.tv_sec = (socket->m_timeout / 1000);
752 tv.tv_usec = (socket->m_timeout % 1000) * 1000;
753
754 if (!socket->m_non_blocking)
755 {
756 FD_ZERO(&readfds);
757 FD_SET(socket->m_fd, &readfds);
758 if (select(socket->m_fd + 1, &readfds, NULL, NULL, &tv) == 0)
759 {
760 socket->m_error = GSOCK_TIMEDOUT;
761 return GSOCK_TIMEDOUT;
762 }
763 }
764 return GSOCK_NOERROR;
765 }
766
767 /* _GSocket_Output_Timeout:
768 * For blocking sockets, wait until data can be sent without
769 * blocking or until timeout ellapses.
770 */
771 GSocketError _GSocket_Output_Timeout(GSocket *socket)
772 {
773 struct timeval tv;
774 fd_set writefds;
775
776 tv.tv_sec = (socket->m_timeout / 1000);
777 tv.tv_usec = (socket->m_timeout % 1000) * 1000;
778
779 if (!socket->m_non_blocking)
780 {
781 FD_ZERO(&writefds);
782 FD_SET(socket->m_fd, &writefds);
783 if (select(socket->m_fd + 1, NULL, &writefds, NULL, &tv) == 0)
784 {
785 socket->m_error = GSOCK_TIMEDOUT;
786 return GSOCK_TIMEDOUT;
787 }
788 }
789 return GSOCK_NOERROR;
790 }
791
792 int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
793 {
794 int ret;
795
796 ret = recv(socket->m_fd, buffer, size, 0);
797
798 return ret;
799 }
800
801 int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
802 {
803 struct sockaddr from;
804 SOCKLEN_T fromlen;
805 int ret;
806 GSocketError err;
807
808 fromlen = sizeof(from);
809
810 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen);
811
812 if (ret == -1)
813 return -1;
814
815 /* Translate a system address into a GSocket address */
816 if (!socket->m_peer)
817 {
818 socket->m_peer = GAddress_new();
819 if (!socket->m_peer)
820 {
821 socket->m_error = GSOCK_MEMERR;
822 return -1;
823 }
824 }
825 err = _GAddress_translate_from(socket->m_peer, &from, fromlen);
826 if (err != GSOCK_NOERROR)
827 {
828 GAddress_destroy(socket->m_peer);
829 socket->m_peer = NULL;
830 socket->m_error = err;
831 return -1;
832 }
833
834 return ret;
835 }
836
837 int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
838 {
839 int ret;
840 GSocketError err;
841
842 ret = send(socket->m_fd, (char*)buffer, size, 0);
843
844 return ret;
845 }
846
847 int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
848 {
849 struct sockaddr *addr;
850 int len, ret;
851 GSocketError err;
852
853 if (!socket->m_peer) {
854 socket->m_error = GSOCK_INVADDR;
855 return -1;
856 }
857
858 err = _GAddress_translate_to(socket->m_peer, &addr, &len);
859 if (err != GSOCK_NOERROR) {
860 socket->m_error = err;
861 return -1;
862 }
863
864 ret = sendto(socket->m_fd, (char*)buffer, size, 0, addr, len);
865
866 /* Frees memory allocated from _GAddress_translate_to */
867 free(addr);
868
869 return ret;
870 }
871
872 void _GSocket_Detected_Read(GSocket *socket)
873 {
874 char c;
875 int ret;
876
877 if (socket->m_stream)
878 {
879 ret = recv(socket->m_fd, &c, 1, MSG_PEEK);
880
881 if (ret < 0 && socket->m_server)
882 {
883 CALL_CALLBACK(socket, GSOCK_CONNECTION);
884 return;
885 }
886
887 if (ret > 0)
888 {
889 CALL_CALLBACK(socket, GSOCK_INPUT);
890 }
891 else
892 {
893 CALL_CALLBACK(socket, GSOCK_LOST);
894 }
895 }
896 }
897
898 void _GSocket_Detected_Write(GSocket *socket)
899 {
900 if (socket->m_establishing && !socket->m_server)
901 {
902 int error, len;
903
904 socket->m_establishing = FALSE;
905
906 len = sizeof(error);
907 getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
908
909 if (error)
910 {
911 CALL_CALLBACK(socket, GSOCK_LOST);
912 }
913 else
914 {
915 CALL_CALLBACK(socket, GSOCK_CONNECTION);
916 /* We have to fire this event by hand because CONNECTION (for clients)
917 * and OUTPUT are internally the same and we just disabled CONNECTION
918 * events with the above macro.
919 */
920 CALL_CALLBACK(socket, GSOCK_OUTPUT);
921 }
922 }
923 else
924 {
925 CALL_CALLBACK(socket, GSOCK_OUTPUT);
926 }
927 }
928
929 /*
930 * -------------------------------------------------------------------------
931 * GAddress
932 * -------------------------------------------------------------------------
933 */
934
935 /* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY or
936 * GSOCK_*family*. In case it is GSOCK_NOFAMILY, it initializes address to be
937 * a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
938 */
939 #define CHECK_ADDRESS(address, family, retval) \
940 { \
941 if (address->m_family == GSOCK_NOFAMILY) \
942 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) {\
943 return address->m_error; \
944 }\
945 if (address->m_family != GSOCK_##family) {\
946 address->m_error = GSOCK_INVADDR; \
947 return retval; \
948 } \
949 }
950
951 GAddress *GAddress_new()
952 {
953 GAddress *address;
954
955 address = (GAddress *)malloc(sizeof(GAddress));
956
957 if (address == NULL)
958 return NULL;
959
960 address->m_family = GSOCK_NOFAMILY;
961 address->m_addr = NULL;
962 address->m_len = 0;
963
964 return address;
965 }
966
967 GAddress *GAddress_copy(GAddress *address)
968 {
969 GAddress *addr2;
970
971 assert(address != NULL);
972
973 addr2 = (GAddress *)malloc(sizeof(GAddress));
974
975 if (addr2 == NULL)
976 return NULL;
977
978 memcpy(addr2, address, sizeof(GAddress));
979
980 if (address->m_addr) {
981 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
982 if (addr2->m_addr == NULL) {
983 free(addr2);
984 return NULL;
985 }
986 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
987 }
988
989 return addr2;
990 }
991
992 void GAddress_destroy(GAddress *address)
993 {
994 assert(address != NULL);
995
996 free(address);
997 }
998
999 void GAddress_SetFamily(GAddress *address, GAddressType type)
1000 {
1001 assert(address != NULL);
1002
1003 address->m_family = type;
1004 }
1005
1006 GAddressType GAddress_GetFamily(GAddress *address)
1007 {
1008 assert(address != NULL);
1009
1010 return address->m_family;
1011 }
1012
1013 GSocketError _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){
1014 address->m_realfamily = addr->sa_family;
1015 switch (addr->sa_family) {
1016 case AF_INET:
1017 address->m_family = GSOCK_INET;
1018 break;
1019 case AF_UNIX:
1020 address->m_family = GSOCK_UNIX;
1021 break;
1022 #ifdef AF_INET6
1023 case AF_INET6:
1024 address->m_family = GSOCK_INET6;
1025 break;
1026 #endif
1027 default:
1028 {
1029 address->m_error = GSOCK_INVOP;
1030 return GSOCK_INVOP;
1031 }
1032 }
1033
1034 if (address->m_addr)
1035 free(address->m_addr);
1036
1037 address->m_len = len;
1038 address->m_addr = (struct sockaddr *)malloc(len);
1039 if (address->m_addr == NULL) {
1040 address->m_error = GSOCK_MEMERR;
1041 return GSOCK_MEMERR;
1042 }
1043 memcpy(address->m_addr, addr, len);
1044
1045 return GSOCK_NOERROR;
1046 }
1047
1048 GSocketError _GAddress_translate_to(GAddress *address,
1049 struct sockaddr **addr, int *len)
1050 {
1051 if (!address->m_addr) {
1052 address->m_error = GSOCK_INVADDR;
1053 return GSOCK_INVADDR;
1054 }
1055
1056 *len = address->m_len;
1057 *addr = (struct sockaddr *)malloc(address->m_len);
1058 if (*addr == NULL) {
1059 address->m_error = GSOCK_MEMERR;
1060 return GSOCK_MEMERR;
1061 }
1062
1063 memcpy(*addr, address->m_addr, address->m_len);
1064 return GSOCK_NOERROR;
1065 }
1066
1067 /*
1068 * -------------------------------------------------------------------------
1069 * Internet address family
1070 * -------------------------------------------------------------------------
1071 */
1072
1073 GSocketError _GAddress_Init_INET(GAddress *address)
1074 {
1075 address->m_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
1076 if (address->m_addr == NULL) {
1077 address->m_error = GSOCK_MEMERR;
1078 return GSOCK_MEMERR;
1079 }
1080
1081 address->m_len = sizeof(struct sockaddr_in);
1082
1083 address->m_family = GSOCK_INET;
1084 address->m_realfamily = PF_INET;
1085 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
1086 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
1087
1088 return GSOCK_NOERROR;
1089 }
1090
1091 GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1092 {
1093 struct hostent *he;
1094 struct in_addr *addr;
1095
1096 assert(address != NULL);
1097
1098 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1099
1100 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1101
1102 /* If it is a numeric host name, convert it now */
1103 #if defined(HAVE_INET_ATON)
1104 if (inet_aton(hostname, addr) == 0) {
1105 #elif defined(HAVE_INET_ADDR)
1106 /* Fix from Guillermo Rodriguez Garcia <guille@iies.es> */
1107 if ( (addr->s_addr = inet_addr(hostname)) == -1 ) {
1108 #endif
1109 struct in_addr *array_addr;
1110
1111 /* It is a real name, we solve it */
1112 he = gethostbyname((char*)hostname);
1113 if (he == NULL) {
1114 address->m_error = GSOCK_NOHOST;
1115 return GSOCK_NOHOST;
1116 }
1117 array_addr = (struct in_addr *) *(he->h_addr_list);
1118 addr->s_addr = array_addr[0].s_addr;
1119 #if defined(HAVE_INET_ATON)
1120 }
1121 #elif defined(HAVE_INET_ADDR)
1122 }
1123 #endif
1124 return GSOCK_NOERROR;
1125 }
1126
1127 GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1128 unsigned long hostaddr)
1129 {
1130 struct in_addr *addr;
1131
1132 assert(address != NULL);
1133
1134 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1135
1136 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1137 addr->s_addr = hostaddr;
1138
1139 return GSOCK_NOERROR;
1140 }
1141
1142 GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1143 const char *protocol)
1144 {
1145 struct servent *se;
1146 struct sockaddr_in *addr;
1147
1148 assert(address != NULL);
1149 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1150
1151 if (!port) {
1152 address->m_error = GSOCK_INVPORT;
1153 return GSOCK_INVPORT;
1154 }
1155
1156 se = getservbyname((char*)port, (char*)protocol);
1157 if (!se) {
1158 if (isdigit(port[0])) {
1159 int port_int;
1160
1161 port_int = atoi(port);
1162 addr = (struct sockaddr_in *)address->m_addr;
1163 addr->sin_port = htons(port_int);
1164 return GSOCK_NOERROR;
1165 }
1166
1167 address->m_error = GSOCK_INVPORT;
1168 return GSOCK_INVPORT;
1169 }
1170
1171 addr = (struct sockaddr_in *)address->m_addr;
1172 addr->sin_port = se->s_port;
1173
1174 return GSOCK_NOERROR;
1175 }
1176
1177 GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1178 {
1179 struct sockaddr_in *addr;
1180
1181 assert(address != NULL);
1182 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1183
1184 addr = (struct sockaddr_in *)address->m_addr;
1185 addr->sin_port = htons(port);
1186
1187 return GSOCK_NOERROR;
1188 }
1189
1190 GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1191 {
1192 struct hostent *he;
1193 char *addr_buf;
1194 struct sockaddr_in *addr;
1195
1196 assert(address != NULL);
1197 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1198
1199 addr = (struct sockaddr_in *)address->m_addr;
1200 addr_buf = (char *)&(addr->sin_addr);
1201
1202 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1203 if (he == NULL) {
1204 address->m_error = GSOCK_NOHOST;
1205 return GSOCK_NOHOST;
1206 }
1207
1208 strncpy(hostname, he->h_name, sbuf);
1209
1210 return GSOCK_NOERROR;
1211 }
1212
1213 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1214 {
1215 struct sockaddr_in *addr;
1216
1217 assert(address != NULL);
1218 CHECK_ADDRESS(address, INET, 0);
1219
1220 addr = (struct sockaddr_in *)address->m_addr;
1221
1222 return addr->sin_addr.s_addr;
1223 }
1224
1225 unsigned short GAddress_INET_GetPort(GAddress *address)
1226 {
1227 struct sockaddr_in *addr;
1228
1229 assert(address != NULL);
1230 CHECK_ADDRESS(address, INET, 0);
1231
1232 addr = (struct sockaddr_in *)address->m_addr;
1233 return ntohs(addr->sin_port);
1234 }
1235
1236 #endif
1237 /* wxUSE_SOCKETS */