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