]>
git.saurik.com Git - wxWidgets.git/blob - src/os2/gsocket.c
1 /* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
4 * Purpose: GSocket main Unix-style file
6 * -------------------------------------------------------------------------
13 #define BSD_SELECT /* use Berkley Sockets select */
16 #include <sys\types.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
23 #define HAVE_INET_ADDR
31 #if defined(__VISAGECPP__) && __IBMCPP__ < 400
36 #include <sys\socket.h>
37 #include <sys\ioctl.h>
38 #include <sys\select.h>
40 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
41 int _System
bsdselect(int,
46 int _System
soclose(int);
58 #include "wx/gsocket.h"
59 #include "wx/os2/gsockos2.h"
65 # define SOCKLEN_T socklen_t
68 # define SOCKLEN_T int
73 /* Global initialisers */
80 void GSocket_Cleanup()
84 /* Constructors / Destructors */
86 GSocket
*GSocket_new()
91 socket
= (GSocket
*)malloc(sizeof(GSocket
));
97 for (i
=0;i
<GSOCK_MAX_EVENT
;i
++)
99 socket
->m_cbacks
[i
] = NULL
;
101 socket
->m_detected
= 0;
102 socket
->m_local
= NULL
;
103 socket
->m_peer
= NULL
;
104 socket
->m_error
= GSOCK_NOERROR
;
105 socket
->m_server
= FALSE
;
106 socket
->m_stream
= TRUE
;
107 socket
->m_gui_dependent
= NULL
;
108 socket
->m_non_blocking
= FALSE
;
109 socket
->m_timeout
= 10*60*1000;
110 /* 10 minutes * 60 sec * 1000 millisec */
111 socket
->m_establishing
= FALSE
;
113 /* We initialize the GUI specific entries here */
114 _GSocket_GUI_Init(socket
);
119 void GSocket_destroy(GSocket
*socket
)
121 assert(socket
!= NULL
);
123 /* First, we check that the socket is really shutdowned */
124 if (socket
->m_fd
!= -1)
125 GSocket_Shutdown(socket
);
127 /* We destroy GUI specific variables */
128 _GSocket_GUI_Destroy(socket
);
130 /* We destroy private addresses */
132 GAddress_destroy(socket
->m_local
);
135 GAddress_destroy(socket
->m_peer
);
137 /* We destroy socket itself */
141 void GSocket_Shutdown(GSocket
*socket
)
145 assert(socket
!= NULL
);
147 /* If socket has been created, we shutdown it */
148 if (socket
->m_fd
!= -1)
150 shutdown(socket
->m_fd
, 2);
151 soclose(socket
->m_fd
);
155 /* We also disable GUI callbacks */
156 for (evt
= 0; evt
< GSOCK_MAX_EVENT
; evt
++)
157 socket
->m_cbacks
[evt
] = NULL
;
159 socket
->m_detected
= 0;
160 _GSocket_Disable_Events(socket
);
163 /* Address handling */
165 GSocketError
GSocket_SetLocal(GSocket
*socket
, GAddress
*address
)
167 assert(socket
!= NULL
);
169 if ((socket
->m_fd
!= -1 && !socket
->m_server
)) {
170 socket
->m_error
= GSOCK_INVSOCK
;
171 return GSOCK_INVSOCK
;
174 if (address
== NULL
|| address
->m_family
== GSOCK_NOFAMILY
) {
175 socket
->m_error
= GSOCK_INVADDR
;
176 return GSOCK_INVADDR
;
180 GAddress_destroy(socket
->m_local
);
182 socket
->m_local
= GAddress_copy(address
);
184 return GSOCK_NOERROR
;
187 GSocketError
GSocket_SetPeer(GSocket
*socket
, GAddress
*address
)
189 assert(socket
!= NULL
);
191 if (address
== NULL
|| address
->m_family
== GSOCK_NOFAMILY
) {
192 socket
->m_error
= GSOCK_INVADDR
;
193 return GSOCK_INVADDR
;
197 GAddress_destroy(socket
->m_peer
);
199 socket
->m_peer
= GAddress_copy(address
);
201 return GSOCK_NOERROR
;
204 GAddress
*GSocket_GetLocal(GSocket
*socket
)
207 struct sockaddr addr
;
211 assert(socket
!= NULL
);
214 return GAddress_copy(socket
->m_local
);
216 if (socket
->m_fd
== -1) {
217 socket
->m_error
= GSOCK_INVSOCK
;
223 if (getsockname(socket
->m_fd
, &addr
, &size
) < 0) {
224 socket
->m_error
= GSOCK_IOERR
;
228 address
= GAddress_new();
229 if (address
== NULL
) {
230 socket
->m_error
= GSOCK_MEMERR
;
233 socket
->m_error
= _GAddress_translate_from(address
, &addr
, size
);
234 if (socket
->m_error
!= GSOCK_NOERROR
) {
235 GAddress_destroy(address
);
242 GAddress
*GSocket_GetPeer(GSocket
*socket
)
244 assert(socket
!= NULL
);
247 return GAddress_copy(socket
->m_peer
);
252 /* Server specific parts */
254 /* GSocket_SetServer:
255 * Sets up the socket as a server. It uses the "Local" field of GSocket.
256 * "Local" must be set by GSocket_SetLocal() before GSocket_SetServer()
257 * is called. Possible error codes are: GSOCK_INVSOCK if socket has not
258 * been initialized, GSOCK_INVADDR if the local address has not been
259 * defined and GSOCK_IOERR for other internal errors.
261 GSocketError
GSocket_SetServer(GSocket
*sck
)
268 if (sck
->m_fd
!= -1) {
269 sck
->m_error
= GSOCK_INVSOCK
;
270 return GSOCK_INVSOCK
;
274 sck
->m_error
= GSOCK_INVADDR
;
275 return GSOCK_INVADDR
;
278 /* We always have a stream here */
279 sck
->m_stream
= TRUE
;
280 sck
->m_server
= TRUE
;
282 /* Create the socket */
283 sck
->m_fd
= socket(sck
->m_local
->m_realfamily
, SOCK_STREAM
, 0);
285 if (sck
->m_fd
== -1) {
286 sck
->m_error
= GSOCK_IOERR
;
290 ioctl(sck
->m_fd
, FIONBIO
, (char*)&arg
, sizeof(int));
291 _GSocket_Enable_Events(sck
);
293 /* Bind the socket to the LOCAL address */
294 if (bind(sck
->m_fd
, sck
->m_local
->m_addr
, sck
->m_local
->m_len
) < 0) {
297 sck
->m_error
= GSOCK_IOERR
;
301 /* Enable listening up to 5 connections */
302 if (listen(sck
->m_fd
, 5) < 0) {
305 sck
->m_error
= GSOCK_IOERR
;
309 return GSOCK_NOERROR
;
312 /* GSocket_WaitConnection:
313 * Waits for an incoming client connection.
315 GSocket
*GSocket_WaitConnection(GSocket
*socket
)
320 assert(socket
!= NULL
);
322 /* Reenable CONNECTION events */
323 _GSocket_Enable(socket
, GSOCK_CONNECTION
);
325 /* If the socket has already been created, we exit immediately */
326 if (socket
->m_fd
== -1 || !socket
->m_server
)
328 socket
->m_error
= GSOCK_INVSOCK
;
332 /* Create a GSocket object for the new connection */
333 connection
= GSocket_new();
336 connection
->m_error
= GSOCK_MEMERR
;
340 /* Accept the incoming connection */
341 if (_GSocket_Input_Timeout(socket
) == GSOCK_TIMEDOUT
)
343 GSocket_destroy(connection
);
344 /* socket->m_error set by _GSocket_Input_Timeout */
348 connection
->m_fd
= accept(socket
->m_fd
, NULL
, NULL
);
350 if (connection
->m_fd
== -1)
352 if (errno
== EWOULDBLOCK
)
353 socket
->m_error
= GSOCK_WOULDBLOCK
;
355 socket
->m_error
= GSOCK_IOERR
;
357 GSocket_destroy(connection
);
361 /* Initialize all fields */
362 connection
->m_server
= FALSE
;
363 connection
->m_stream
= TRUE
;
364 connection
->m_oriented
= TRUE
;
366 ioctl(connection
->m_fd
, FIONBIO
, (char*)&arg
, sizeof(int));
367 _GSocket_Enable_Events(connection
);
372 /* Non oriented connections */
374 GSocketError
GSocket_SetNonOriented(GSocket
*sck
)
380 if (sck
->m_fd
!= -1) {
381 sck
->m_error
= GSOCK_INVSOCK
;
382 return GSOCK_INVSOCK
;
386 sck
->m_error
= GSOCK_INVADDR
;
387 return GSOCK_INVADDR
;
390 sck
->m_stream
= FALSE
;
391 sck
->m_server
= FALSE
;
392 sck
->m_oriented
= FALSE
;
394 /* Create the socket */
395 sck
->m_fd
= socket(sck
->m_local
->m_realfamily
, SOCK_DGRAM
, 0);
398 sck
->m_error
= GSOCK_IOERR
;
402 ioctl(sck
->m_fd
, FIONBIO
, (char*)&arg
, sizeof(int));
403 _GSocket_Enable_Events(sck
);
405 /* Bind it to the LOCAL address */
406 if (bind(sck
->m_fd
, sck
->m_local
->m_addr
, sck
->m_local
->m_len
) < 0) {
409 sck
->m_error
= GSOCK_IOERR
;
413 return GSOCK_NOERROR
;
416 /* Client specific parts */
419 * Establishes a client connection to a server using the "Peer"
420 * field of GSocket. "Peer" must be set by GSocket_SetPeer() before
421 * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK,
422 * GSOCK_INVADDR, GSOCK_TIMEDOUT, GSOCK_WOULDBLOCK and GSOCK_IOERR.
423 * If a socket is nonblocking and Connect() returns GSOCK_WOULDBLOCK,
424 * the connection request can be completed later. Use GSocket_Select()
425 * to check or wait for a GSOCK_CONNECTION event.
427 GSocketError
GSocket_Connect(GSocket
*sck
, GSocketStream stream
)
434 /* Enable CONNECTION events (needed for nonblocking connections) */
435 _GSocket_Enable(sck
, GSOCK_CONNECTION
);
439 sck
->m_error
= GSOCK_INVSOCK
;
440 return GSOCK_INVSOCK
;
445 sck
->m_error
= GSOCK_INVADDR
;
446 return GSOCK_INVADDR
;
449 /* Test whether we want the socket to be a stream (e.g. TCP) */
450 sck
->m_stream
= (stream
== GSOCK_STREAMED
);
451 sck
->m_oriented
= TRUE
;
452 sck
->m_server
= FALSE
;
453 sck
->m_establishing
= FALSE
;
460 /* Create the socket */
461 sck
->m_fd
= socket(sck
->m_peer
->m_realfamily
, type
, 0);
463 if (sck
->m_fd
== -1) {
464 sck
->m_error
= GSOCK_IOERR
;
468 ioctl(sck
->m_fd
, FIONBIO
, (char*)&arg
, sizeof(int));
469 _GSocket_Enable_Events(sck
);
471 /* Connect it to the PEER address */
472 ret
= connect(sck
->m_fd
, sck
->m_peer
->m_addr
, sck
->m_peer
->m_len
);
478 /* If connect failed with EINPROGRESS and the GSocket object
479 * is in blocking mode, we select() for the specified timeout
480 * checking for writability to see if the connection request
483 if ((err
== EINPROGRESS
) && (!sck
->m_non_blocking
))
485 if (_GSocket_Output_Timeout(sck
) == GSOCK_TIMEDOUT
)
489 /* sck->m_error is set in _GSocket_Output_Timeout */
490 fprintf(stderr
, "Blocking connect timeouts\n");
491 return GSOCK_TIMEDOUT
;
495 fprintf(stderr
, "Blocking connect OK\n");
496 return GSOCK_NOERROR
;
500 /* If connect failed with EINPROGRESS and the GSocket object
501 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
502 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
503 * this way if the connection completes, a GSOCK_CONNECTION
504 * event will be generated, if enabled.
506 if ((err
== EINPROGRESS
) && (sck
->m_non_blocking
))
508 sck
->m_error
= GSOCK_WOULDBLOCK
;
509 sck
->m_establishing
= TRUE
;
510 fprintf(stderr
, "Nonblocking connect in progress\n");
512 return GSOCK_WOULDBLOCK
;
515 /* If connect failed with an error other than EINPROGRESS,
516 * then the call to GSocket_Connect has failed.
520 sck
->m_error
= GSOCK_IOERR
;
522 fprintf(stderr
, "Connect failed (generic err)\n");
526 fprintf(stderr
, "Connect OK\n");
527 return GSOCK_NOERROR
;
532 /* Like recv(), send(), ... */
533 int GSocket_Read(GSocket
*socket
, char *buffer
, int size
)
537 assert(socket
!= NULL
);
539 /* Reenable INPUT events */
540 _GSocket_Enable(socket
, GSOCK_INPUT
);
542 if (socket
->m_fd
== -1 || socket
->m_server
)
544 socket
->m_error
= GSOCK_INVSOCK
;
548 if (_GSocket_Input_Timeout(socket
) == GSOCK_TIMEDOUT
)
551 if (socket
->m_stream
)
552 ret
= _GSocket_Recv_Stream(socket
, buffer
, size
);
554 ret
= _GSocket_Recv_Dgram(socket
, buffer
, size
);
558 if (errno
== EWOULDBLOCK
)
559 socket
->m_error
= GSOCK_WOULDBLOCK
;
561 socket
->m_error
= GSOCK_IOERR
;
567 int GSocket_Write(GSocket
*socket
, const char *buffer
,
572 assert(socket
!= NULL
);
574 if (socket
->m_fd
== -1 || socket
->m_server
)
576 socket
->m_error
= GSOCK_INVSOCK
;
580 if (_GSocket_Output_Timeout(socket
) == GSOCK_TIMEDOUT
)
583 if (socket
->m_stream
)
584 ret
= _GSocket_Send_Stream(socket
, buffer
, size
);
586 ret
= _GSocket_Send_Dgram(socket
, buffer
, size
);
590 if (errno
== EWOULDBLOCK
)
591 socket
->m_error
= GSOCK_WOULDBLOCK
;
593 socket
->m_error
= GSOCK_IOERR
;
595 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
596 * in MSW). Once the first OUTPUT event is received, users can assume
597 * that the socket is writable until a read operation fails. Only then
598 * will further OUTPUT events be posted.
600 _GSocket_Enable(socket
, GSOCK_OUTPUT
);
607 * Polls the socket to determine its status. This function will
608 * check for the events specified in the 'flags' parameter, and
609 * it will return a mask indicating which operations can be
610 * performed. This function won't block, regardless of the
611 * mode (blocking|nonblocking) of the socket.
613 GSocketEventFlags
GSocket_Select(GSocket
*socket
, GSocketEventFlags flags
)
615 assert(socket
!= NULL
);
617 return (flags
& socket
->m_detected
);
622 /* GSocket_SetNonBlocking:
623 * Sets the socket to non-blocking mode. This is useful if
624 * we don't want to wait.
626 void GSocket_SetNonBlocking(GSocket
*socket
, bool non_block
)
628 assert(socket
!= NULL
);
630 socket
->m_non_blocking
= non_block
;
633 /* GSocket_SetTimeout:
634 * Sets the timeout for blocking calls. Time is
635 * expressed in milliseconds.
637 void GSocket_SetTimeout(GSocket
*socket
, unsigned long millisec
)
639 assert(socket
!= NULL
);
641 socket
->m_timeout
= millisec
;
645 * Returns the last error occured for this socket.
647 GSocketError
GSocket_GetError(GSocket
*socket
)
649 assert(socket
!= NULL
);
651 return socket
->m_error
;
656 /* Only one callback is possible for each event (INPUT, OUTPUT, CONNECTION
657 * and LOST). The callbacks are called in the following situations:
659 * INPUT: There is at least one byte in the input buffer
660 * OUTPUT: The system is sure that the next write call will not block
661 * CONNECTION: Two cases are possible:
662 * Client socket -> the connection is established
663 * Server socket -> a client requests a connection
664 * LOST: The connection is lost
666 * An event is generated only once and its state is reseted when the
667 * relative IO call is requested.
668 * For example: INPUT -> GSocket_Read()
669 * CONNECTION -> GSocket_Accept()
672 /* GSocket_SetCallback:
673 * Enables the callbacks specified by 'flags'. Note that 'flags'
674 * may be a combination of flags OR'ed toghether, so the same
675 * callback function can be made to accept different events.
676 * The callback function must have the following prototype:
678 * void function(GSocket *socket, GSocketEvent event, char *cdata)
680 void GSocket_SetCallback(GSocket
*socket
, GSocketEventFlags flags
,
681 GSocketCallback callback
, char *cdata
)
685 assert(socket
!= NULL
);
687 for (count
= 0; count
< GSOCK_MAX_EVENT
; count
++)
689 if ((flags
& (1 << count
)) != 0)
691 socket
->m_cbacks
[count
] = callback
;
692 socket
->m_data
[count
] = cdata
;
697 /* GSocket_UnsetCallback:
698 * Disables all callbacks specified by 'flags', which may be a
699 * combination of flags OR'ed toghether.
701 void GSocket_UnsetCallback(GSocket
*socket
, GSocketEventFlags flags
)
705 assert(socket
!= NULL
);
707 for (count
= 0; count
< GSOCK_MAX_EVENT
; count
++)
709 if ((flags
& (1 << count
)) != 0)
711 socket
->m_cbacks
[count
] = NULL
;
712 socket
->m_data
[count
] = NULL
;
717 #define CALL_CALLBACK(socket, event) { \
718 _GSocket_Disable(socket, event); \
719 if (socket->m_cbacks[event]) \
720 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
724 void _GSocket_Enable(GSocket
*socket
, GSocketEvent event
)
726 socket
->m_detected
&= ~(1 << event
);
727 _GSocket_Install_Callback(socket
, event
);
730 void _GSocket_Disable(GSocket
*socket
, GSocketEvent event
)
732 socket
->m_detected
|= (1 << event
);
733 _GSocket_Uninstall_Callback(socket
, event
);
736 /* _GSocket_Input_Timeout:
737 * For blocking sockets, wait until data is available or
738 * until timeout ellapses.
740 GSocketError
_GSocket_Input_Timeout(GSocket
*socket
)
745 tv
.tv_sec
= (socket
->m_timeout
/ 1000);
746 tv
.tv_usec
= (socket
->m_timeout
% 1000) * 1000;
748 if (!socket
->m_non_blocking
)
751 FD_SET(socket
->m_fd
, &readfds
);
752 if (select(socket
->m_fd
+ 1, &readfds
, NULL
, NULL
, &tv
) == 0)
754 socket
->m_error
= GSOCK_TIMEDOUT
;
755 return GSOCK_TIMEDOUT
;
758 return GSOCK_NOERROR
;
761 /* _GSocket_Output_Timeout:
762 * For blocking sockets, wait until data can be sent without
763 * blocking or until timeout ellapses.
765 GSocketError
_GSocket_Output_Timeout(GSocket
*socket
)
770 tv
.tv_sec
= (socket
->m_timeout
/ 1000);
771 tv
.tv_usec
= (socket
->m_timeout
% 1000) * 1000;
773 if (!socket
->m_non_blocking
)
776 FD_SET(socket
->m_fd
, &writefds
);
777 if (select(socket
->m_fd
+ 1, NULL
, &writefds
, NULL
, &tv
) == 0)
779 socket
->m_error
= GSOCK_TIMEDOUT
;
780 return GSOCK_TIMEDOUT
;
783 return GSOCK_NOERROR
;
786 int _GSocket_Recv_Stream(GSocket
*socket
, char *buffer
, int size
)
790 ret
= recv(socket
->m_fd
, buffer
, size
, 0);
795 int _GSocket_Recv_Dgram(GSocket
*socket
, char *buffer
, int size
)
797 struct sockaddr from
;
802 fromlen
= sizeof(from
);
804 ret
= recvfrom(socket
->m_fd
, buffer
, size
, 0, &from
, &fromlen
);
809 /* Translate a system address into a GSocket address */
812 socket
->m_peer
= GAddress_new();
815 socket
->m_error
= GSOCK_MEMERR
;
819 err
= _GAddress_translate_from(socket
->m_peer
, &from
, fromlen
);
820 if (err
!= GSOCK_NOERROR
)
822 GAddress_destroy(socket
->m_peer
);
823 socket
->m_peer
= NULL
;
824 socket
->m_error
= err
;
831 int _GSocket_Send_Stream(GSocket
*socket
, const char *buffer
, int size
)
836 ret
= send(socket
->m_fd
, (char*)buffer
, size
, 0);
841 int _GSocket_Send_Dgram(GSocket
*socket
, const char *buffer
, int size
)
843 struct sockaddr
*addr
;
847 if (!socket
->m_peer
) {
848 socket
->m_error
= GSOCK_INVADDR
;
852 err
= _GAddress_translate_to(socket
->m_peer
, &addr
, &len
);
853 if (err
!= GSOCK_NOERROR
) {
854 socket
->m_error
= err
;
858 ret
= sendto(socket
->m_fd
, (char*)buffer
, size
, 0, addr
, len
);
860 /* Frees memory allocated from _GAddress_translate_to */
866 void _GSocket_Detected_Read(GSocket
*socket
)
871 if (socket
->m_stream
)
873 ret
= recv(socket
->m_fd
, &c
, 1, MSG_PEEK
);
875 if (ret
< 0 && socket
->m_server
)
877 CALL_CALLBACK(socket
, GSOCK_CONNECTION
);
883 CALL_CALLBACK(socket
, GSOCK_INPUT
);
887 CALL_CALLBACK(socket
, GSOCK_LOST
);
892 void _GSocket_Detected_Write(GSocket
*socket
)
894 if (socket
->m_establishing
&& !socket
->m_server
)
898 socket
->m_establishing
= FALSE
;
901 getsockopt(socket
->m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
905 CALL_CALLBACK(socket
, GSOCK_LOST
);
909 CALL_CALLBACK(socket
, GSOCK_CONNECTION
);
910 /* We have to fire this event by hand because CONNECTION (for clients)
911 * and OUTPUT are internally the same and we just disabled CONNECTION
912 * events with the above macro.
914 CALL_CALLBACK(socket
, GSOCK_OUTPUT
);
919 CALL_CALLBACK(socket
, GSOCK_OUTPUT
);
924 * -------------------------------------------------------------------------
926 * -------------------------------------------------------------------------
929 /* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY or
930 * GSOCK_*family*. In case it is GSOCK_NOFAMILY, it initializes address to be
931 * a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
933 #define CHECK_ADDRESS(address, family, retval) \
935 if (address->m_family == GSOCK_NOFAMILY) \
936 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) {\
937 return address->m_error; \
939 if (address->m_family != GSOCK_##family) {\
940 address->m_error = GSOCK_INVADDR; \
945 GAddress
*GAddress_new()
949 address
= (GAddress
*)malloc(sizeof(GAddress
));
954 address
->m_family
= GSOCK_NOFAMILY
;
955 address
->m_addr
= NULL
;
961 GAddress
*GAddress_copy(GAddress
*address
)
965 assert(address
!= NULL
);
967 addr2
= (GAddress
*)malloc(sizeof(GAddress
));
972 memcpy(addr2
, address
, sizeof(GAddress
));
974 if (address
->m_addr
) {
975 addr2
->m_addr
= (struct sockaddr
*)malloc(addr2
->m_len
);
976 if (addr2
->m_addr
== NULL
) {
980 memcpy(addr2
->m_addr
, address
->m_addr
, addr2
->m_len
);
986 void GAddress_destroy(GAddress
*address
)
988 assert(address
!= NULL
);
993 void GAddress_SetFamily(GAddress
*address
, GAddressType type
)
995 assert(address
!= NULL
);
997 address
->m_family
= type
;
1000 GAddressType
GAddress_GetFamily(GAddress
*address
)
1002 assert(address
!= NULL
);
1004 return address
->m_family
;
1007 GSocketError
_GAddress_translate_from(GAddress
*address
, struct sockaddr
*addr
, int len
){
1008 address
->m_realfamily
= addr
->sa_family
;
1009 switch (addr
->sa_family
) {
1011 address
->m_family
= GSOCK_INET
;
1014 address
->m_family
= GSOCK_UNIX
;
1018 address
->m_family
= GSOCK_INET6
;
1023 address
->m_error
= GSOCK_INVOP
;
1028 if (address
->m_addr
)
1029 free(address
->m_addr
);
1031 address
->m_len
= len
;
1032 address
->m_addr
= (struct sockaddr
*)malloc(len
);
1033 if (address
->m_addr
== NULL
) {
1034 address
->m_error
= GSOCK_MEMERR
;
1035 return GSOCK_MEMERR
;
1037 memcpy(address
->m_addr
, addr
, len
);
1039 return GSOCK_NOERROR
;
1042 GSocketError
_GAddress_translate_to(GAddress
*address
,
1043 struct sockaddr
**addr
, int *len
)
1045 if (!address
->m_addr
) {
1046 address
->m_error
= GSOCK_INVADDR
;
1047 return GSOCK_INVADDR
;
1050 *len
= address
->m_len
;
1051 *addr
= (struct sockaddr
*)malloc(address
->m_len
);
1052 if (*addr
== NULL
) {
1053 address
->m_error
= GSOCK_MEMERR
;
1054 return GSOCK_MEMERR
;
1057 memcpy(*addr
, address
->m_addr
, address
->m_len
);
1058 return GSOCK_NOERROR
;
1062 * -------------------------------------------------------------------------
1063 * Internet address family
1064 * -------------------------------------------------------------------------
1067 GSocketError
_GAddress_Init_INET(GAddress
*address
)
1069 address
->m_addr
= (struct sockaddr
*)malloc(sizeof(struct sockaddr_in
));
1070 if (address
->m_addr
== NULL
) {
1071 address
->m_error
= GSOCK_MEMERR
;
1072 return GSOCK_MEMERR
;
1075 address
->m_len
= sizeof(struct sockaddr_in
);
1077 address
->m_family
= GSOCK_INET
;
1078 address
->m_realfamily
= PF_INET
;
1079 ((struct sockaddr_in
*)address
->m_addr
)->sin_family
= AF_INET
;
1080 ((struct sockaddr_in
*)address
->m_addr
)->sin_addr
.s_addr
= INADDR_ANY
;
1082 return GSOCK_NOERROR
;
1085 GSocketError
GAddress_INET_SetHostName(GAddress
*address
, const char *hostname
)
1088 struct in_addr
*addr
;
1090 assert(address
!= NULL
);
1092 CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
);
1094 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1096 /* If it is a numeric host name, convert it now */
1097 #if defined(HAVE_INET_ATON)
1098 if (inet_aton(hostname
, addr
) == 0) {
1099 #elif defined(HAVE_INET_ADDR)
1100 /* Fix from Guillermo Rodriguez Garcia <guille@iies.es> */
1101 if ( (addr
->s_addr
= inet_addr(hostname
)) == -1 ) {
1103 struct in_addr
*array_addr
;
1105 /* It is a real name, we solve it */
1106 he
= gethostbyname((char*)hostname
);
1108 address
->m_error
= GSOCK_NOHOST
;
1109 return GSOCK_NOHOST
;
1111 array_addr
= (struct in_addr
*) *(he
->h_addr_list
);
1112 addr
->s_addr
= array_addr
[0].s_addr
;
1113 #if defined(HAVE_INET_ATON)
1115 #elif defined(HAVE_INET_ADDR)
1118 return GSOCK_NOERROR
;
1121 GSocketError
GAddress_INET_SetHostAddress(GAddress
*address
,
1122 unsigned long hostaddr
)
1124 struct in_addr
*addr
;
1126 assert(address
!= NULL
);
1128 CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
);
1130 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1131 addr
->s_addr
= hostaddr
;
1133 return GSOCK_NOERROR
;
1136 GSocketError
GAddress_INET_SetPortName(GAddress
*address
, const char *port
,
1137 const char *protocol
)
1140 struct sockaddr_in
*addr
;
1142 assert(address
!= NULL
);
1143 CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
);
1146 address
->m_error
= GSOCK_INVPORT
;
1147 return GSOCK_INVPORT
;
1150 se
= getservbyname((char*)port
, (char*)protocol
);
1152 if (isdigit(port
[0])) {
1155 port_int
= atoi(port
);
1156 addr
= (struct sockaddr_in
*)address
->m_addr
;
1157 addr
->sin_port
= htons(port_int
);
1158 return GSOCK_NOERROR
;
1161 address
->m_error
= GSOCK_INVPORT
;
1162 return GSOCK_INVPORT
;
1165 addr
= (struct sockaddr_in
*)address
->m_addr
;
1166 addr
->sin_port
= se
->s_port
;
1168 return GSOCK_NOERROR
;
1171 GSocketError
GAddress_INET_SetPort(GAddress
*address
, unsigned short port
)
1173 struct sockaddr_in
*addr
;
1175 assert(address
!= NULL
);
1176 CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
);
1178 addr
= (struct sockaddr_in
*)address
->m_addr
;
1179 addr
->sin_port
= htons(port
);
1181 return GSOCK_NOERROR
;
1184 GSocketError
GAddress_INET_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1188 struct sockaddr_in
*addr
;
1190 assert(address
!= NULL
);
1191 CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
);
1193 addr
= (struct sockaddr_in
*)address
->m_addr
;
1194 addr_buf
= (char *)&(addr
->sin_addr
);
1196 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin_addr
), AF_INET
);
1198 address
->m_error
= GSOCK_NOHOST
;
1199 return GSOCK_NOHOST
;
1202 strncpy(hostname
, he
->h_name
, sbuf
);
1204 return GSOCK_NOERROR
;
1207 unsigned long GAddress_INET_GetHostAddress(GAddress
*address
)
1209 struct sockaddr_in
*addr
;
1211 assert(address
!= NULL
);
1212 CHECK_ADDRESS(address
, INET
, 0);
1214 addr
= (struct sockaddr_in
*)address
->m_addr
;
1216 return addr
->sin_addr
.s_addr
;
1219 unsigned short GAddress_INET_GetPort(GAddress
*address
)
1221 struct sockaddr_in
*addr
;
1223 assert(address
!= NULL
);
1224 CHECK_ADDRESS(address
, INET
, 0);
1226 addr
= (struct sockaddr_in
*)address
->m_addr
;
1227 return ntohs(addr
->sin_port
);