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