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