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