1 /* -------------------------------------------------------------------------
2  * Project:     GSocket (Generic Socket)
3  * Name:        src/msw/gsocket.cpp
4  * Copyright:   (c) Guilhem Lavaux
5  * Licence:     wxWindows Licence
6  * Author:      Guillermo Rodriguez Garcia <guille@iies.es>
7  * Purpose:     GSocket main MSW file
8  * Licence:     The wxWindows licence
9  * CVSID:       $Id: gsocket.cpp 52492 2008-03-14 14:17:14Z JS $
10  * -------------------------------------------------------------------------
11  */
12 
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15 
16 #ifdef __BORLANDC__
17     #pragma hdrstop
18 #endif
19 
20 #ifdef _MSC_VER
21    /* RPCNOTIFICATION_ROUTINE in rasasync.h (included from winsock.h),
22     * warning: conditional expression is constant.
23     */
24 #  pragma warning(disable:4115)
25    /* FD_SET,
26     * warning: named type definition in parentheses.
27     */
28 #  pragma warning(disable:4127)
29    /* GAddress_UNIX_GetPath,
30     * warning: unreferenced formal parameter.
31     */
32 #  pragma warning(disable:4100)
33 
34 #ifdef __WXWINCE__
35     /* windows.h results in tons of warnings at max warning level */
36 #   ifdef _MSC_VER
37 #       pragma warning(push, 1)
38 #   endif
39 #   include <windows.h>
40 #   ifdef _MSC_VER
41 #       pragma warning(pop)
42 #       pragma warning(disable:4514)
43 #   endif
44 #endif
45 
46 #endif /* _MSC_VER */
47 
48 #if defined(__CYGWIN__)
49     //CYGWIN gives annoying warning about runtime stuff if we don't do this
50 #   define USE_SYS_TYPES_FD_SET
51 #   include <sys/types.h>
52 #endif
53 
54 #include <winsock.h>
55 
56 #ifndef __GSOCKET_STANDALONE__
57 #   include "wx/platform.h"
58 #endif
59 
60 #if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
61 
62 #ifndef __GSOCKET_STANDALONE__
63 #  include "wx/msw/gsockmsw.h"
64 #  include "wx/gsocket.h"
65 #else
66 #  include "gsockmsw.h"
67 #  include "gsocket.h"
68 #endif /* __GSOCKET_STANDALONE__ */
69 
70 #ifndef __WXWINCE__
71 #include <assert.h>
72 #else
73 #define assert(x)
74 #ifndef isdigit
75 #define isdigit(x) (x > 47 && x < 58)
76 #endif
77 #include "wx/msw/wince/net.h"
78 #endif
79 
80 #include <string.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <stddef.h>
84 #include <ctype.h>
85 
86 /* if we use configure for MSW WX_SOCKLEN_T will be already defined */
87 #ifndef WX_SOCKLEN_T
88 #  define WX_SOCKLEN_T int
89 #endif
90 
91 /* Table of GUI-related functions. We must call them indirectly because
92  * of wxBase and GUI separation: */
93 
94 static GSocketGUIFunctionsTable *gs_gui_functions;
95 
96 class GSocketGUIFunctionsTableNull: public GSocketGUIFunctionsTable
97 {
98 public:
99     virtual bool OnInit();
100     virtual void OnExit();
101     virtual bool CanUseEventLoop();
102     virtual bool Init_Socket(GSocket *socket);
103     virtual void Destroy_Socket(GSocket *socket);
104     virtual void Enable_Events(GSocket *socket);
105     virtual void Disable_Events(GSocket *socket);
106 };
107 
OnInit()108 bool GSocketGUIFunctionsTableNull::OnInit()
109 {   return true; }
OnExit()110 void GSocketGUIFunctionsTableNull::OnExit()
111 {}
CanUseEventLoop()112 bool GSocketGUIFunctionsTableNull::CanUseEventLoop()
113 {   return false; }
Init_Socket(GSocket * WXUNUSED (socket))114 bool GSocketGUIFunctionsTableNull::Init_Socket(GSocket *WXUNUSED(socket))
115 {   return true; }
Destroy_Socket(GSocket * WXUNUSED (socket))116 void GSocketGUIFunctionsTableNull::Destroy_Socket(GSocket *WXUNUSED(socket))
117 {}
Enable_Events(GSocket * WXUNUSED (socket))118 void GSocketGUIFunctionsTableNull::Enable_Events(GSocket *WXUNUSED(socket))
119 {}
Disable_Events(GSocket * WXUNUSED (socket))120 void GSocketGUIFunctionsTableNull::Disable_Events(GSocket *WXUNUSED(socket))
121 {}
122 /* Global initialisers */
123 
GSocket_SetGUIFunctions(GSocketGUIFunctionsTable * guifunc)124 void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable *guifunc)
125 {
126   gs_gui_functions = guifunc;
127 }
128 
GSocket_Init(void)129 int GSocket_Init(void)
130 {
131   WSADATA wsaData;
132 
133   if (!gs_gui_functions)
134   {
135     static GSocketGUIFunctionsTableNull table;
136     gs_gui_functions = &table;
137   }
138   if ( !gs_gui_functions->OnInit() )
139   {
140     return 0;
141   }
142 
143   /* Initialize WinSocket */
144   return (WSAStartup((1 << 8) | 1, &wsaData) == 0);
145 }
146 
GSocket_Cleanup(void)147 void GSocket_Cleanup(void)
148 {
149   if (gs_gui_functions)
150   {
151       gs_gui_functions->OnExit();
152   }
153 
154   /* Cleanup WinSocket */
155   WSACleanup();
156 }
157 
158 /* Constructors / Destructors for GSocket */
159 
GSocket()160 GSocket::GSocket()
161 {
162   int i;
163 
164   m_fd              = INVALID_SOCKET;
165   for (i = 0; i < GSOCK_MAX_EVENT; i++)
166   {
167     m_cbacks[i]     = NULL;
168   }
169   m_detected        = 0;
170   m_local           = NULL;
171   m_peer            = NULL;
172   m_error           = GSOCK_NOERROR;
173   m_server          = false;
174   m_stream          = true;
175   m_non_blocking    = false;
176   m_timeout.tv_sec  = 10 * 60;  /* 10 minutes */
177   m_timeout.tv_usec = 0;
178   m_establishing    = false;
179   m_reusable        = false;
180 
181   assert(gs_gui_functions);
182   /* Per-socket GUI-specific initialization */
183   m_ok = gs_gui_functions->Init_Socket(this);
184 }
185 
Close()186 void GSocket::Close()
187 {
188     gs_gui_functions->Disable_Events(this);
189     closesocket(m_fd);
190     m_fd = INVALID_SOCKET;
191 }
192 
~GSocket()193 GSocket::~GSocket()
194 {
195   assert(this);
196 
197   /* Per-socket GUI-specific cleanup */
198   gs_gui_functions->Destroy_Socket(this);
199 
200   /* Check that the socket is really shutdowned */
201   if (m_fd != INVALID_SOCKET)
202     Shutdown();
203 
204   /* Destroy private addresses */
205   if (m_local)
206     GAddress_destroy(m_local);
207 
208   if (m_peer)
209     GAddress_destroy(m_peer);
210 }
211 
212 /* GSocket_Shutdown:
213  *  Disallow further read/write operations on this socket, close
214  *  the fd and disable all callbacks.
215  */
Shutdown()216 void GSocket::Shutdown()
217 {
218   int evt;
219 
220   assert(this);
221 
222   /* If socket has been created, shutdown it */
223   if (m_fd != INVALID_SOCKET)
224   {
225     shutdown(m_fd, 1 /* SD_SEND */);
226     Close();
227   }
228 
229   /* Disable GUI callbacks */
230   for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
231     m_cbacks[evt] = NULL;
232 
233   m_detected = GSOCK_LOST_FLAG;
234 }
235 
236 /* Address handling */
237 
238 /* GSocket_SetLocal:
239  * GSocket_GetLocal:
240  * GSocket_SetPeer:
241  * GSocket_GetPeer:
242  *  Set or get the local or peer address for this socket. The 'set'
243  *  functions return GSOCK_NOERROR on success, an error code otherwise.
244  *  The 'get' functions return a pointer to a GAddress object on success,
245  *  or NULL otherwise, in which case they set the error code of the
246  *  corresponding GSocket.
247  *
248  *  Error codes:
249  *    GSOCK_INVSOCK - the socket is not valid.
250  *    GSOCK_INVADDR - the address is not valid.
251  */
SetLocal(GAddress * address)252 GSocketError GSocket::SetLocal(GAddress *address)
253 {
254   assert(this);
255 
256   /* the socket must be initialized, or it must be a server */
257   if (m_fd != INVALID_SOCKET && !m_server)
258   {
259     m_error = GSOCK_INVSOCK;
260     return GSOCK_INVSOCK;
261   }
262 
263   /* check address */
264   if (address == NULL || address->m_family == GSOCK_NOFAMILY)
265   {
266     m_error = GSOCK_INVADDR;
267     return GSOCK_INVADDR;
268   }
269 
270   if (m_local)
271     GAddress_destroy(m_local);
272 
273   m_local = GAddress_copy(address);
274 
275   return GSOCK_NOERROR;
276 }
277 
SetPeer(GAddress * address)278 GSocketError GSocket::SetPeer(GAddress *address)
279 {
280   assert(this);
281 
282   /* check address */
283   if (address == NULL || address->m_family == GSOCK_NOFAMILY)
284   {
285     m_error = GSOCK_INVADDR;
286     return GSOCK_INVADDR;
287   }
288 
289   if (m_peer)
290     GAddress_destroy(m_peer);
291 
292   m_peer = GAddress_copy(address);
293 
294   return GSOCK_NOERROR;
295 }
296 
GetLocal()297 GAddress *GSocket::GetLocal()
298 {
299   GAddress *address;
300   struct sockaddr addr;
301   WX_SOCKLEN_T size = sizeof(addr);
302   GSocketError err;
303 
304   assert(this);
305 
306   /* try to get it from the m_local var first */
307   if (m_local)
308     return GAddress_copy(m_local);
309 
310   /* else, if the socket is initialized, try getsockname */
311   if (m_fd == INVALID_SOCKET)
312   {
313     m_error = GSOCK_INVSOCK;
314     return NULL;
315   }
316 
317   if (getsockname(m_fd, &addr, &size) == SOCKET_ERROR)
318   {
319     m_error = GSOCK_IOERR;
320     return NULL;
321   }
322 
323   /* got a valid address from getsockname, create a GAddress object */
324   if ((address = GAddress_new()) == NULL)
325   {
326      m_error = GSOCK_MEMERR;
327      return NULL;
328   }
329 
330   if ((err = _GAddress_translate_from(address, &addr, size)) != GSOCK_NOERROR)
331   {
332      GAddress_destroy(address);
333      m_error = err;
334      return NULL;
335   }
336 
337   return address;
338 }
339 
GetPeer()340 GAddress *GSocket::GetPeer()
341 {
342   assert(this);
343 
344   /* try to get it from the m_peer var */
345   if (m_peer)
346     return GAddress_copy(m_peer);
347 
348   return NULL;
349 }
350 
351 /* Server specific parts */
352 
353 /* GSocket_SetServer:
354  *  Sets up this socket as a server. The local address must have been
355  *  set with GSocket_SetLocal() before GSocket_SetServer() is called.
356  *  Returns GSOCK_NOERROR on success, one of the following otherwise:
357  *
358  *  Error codes:
359  *    GSOCK_INVSOCK - the socket is in use.
360  *    GSOCK_INVADDR - the local address has not been set.
361  *    GSOCK_IOERR   - low-level error.
362  */
SetServer()363 GSocketError GSocket::SetServer()
364 {
365   u_long arg = 1;
366 
367   assert(this);
368 
369   /* must not be in use */
370   if (m_fd != INVALID_SOCKET)
371   {
372     m_error = GSOCK_INVSOCK;
373     return GSOCK_INVSOCK;
374   }
375 
376   /* the local addr must have been set */
377   if (!m_local)
378   {
379     m_error = GSOCK_INVADDR;
380     return GSOCK_INVADDR;
381   }
382 
383   /* Initialize all fields */
384   m_server   = true;
385   m_stream   = true;
386 
387   /* Create the socket */
388   m_fd = socket(m_local->m_realfamily, SOCK_STREAM, 0);
389 
390   if (m_fd == INVALID_SOCKET)
391   {
392     m_error = GSOCK_IOERR;
393     return GSOCK_IOERR;
394   }
395 
396   ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
397   gs_gui_functions->Enable_Events(this);
398 
399   /* allow a socket to re-bind if the socket is in the TIME_WAIT
400      state after being previously closed.
401    */
402   if (m_reusable)
403   {
404     setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
405   }
406 
407   /* Bind to the local address,
408    * retrieve the actual address bound,
409    * and listen up to 5 connections.
410    */
411   if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
412       (getsockname(m_fd,
413                    m_local->m_addr,
414                    (WX_SOCKLEN_T *)&m_local->m_len) != 0) ||
415       (listen(m_fd, 5) != 0))
416   {
417     Close();
418     m_error = GSOCK_IOERR;
419     return GSOCK_IOERR;
420   }
421 
422   return GSOCK_NOERROR;
423 }
424 
425 /* GSocket_WaitConnection:
426  *  Waits for an incoming client connection. Returns a pointer to
427  *  a GSocket object, or NULL if there was an error, in which case
428  *  the last error field will be updated for the calling GSocket.
429  *
430  *  Error codes (set in the calling GSocket)
431  *    GSOCK_INVSOCK    - the socket is not valid or not a server.
432  *    GSOCK_TIMEDOUT   - timeout, no incoming connections.
433  *    GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
434  *    GSOCK_MEMERR     - couldn't allocate memory.
435  *    GSOCK_IOERR      - low-level error.
436  */
WaitConnection()437 GSocket *GSocket::WaitConnection()
438 {
439   GSocket *connection;
440   struct sockaddr from;
441   WX_SOCKLEN_T fromlen = sizeof(from);
442   GSocketError err;
443   u_long arg = 1;
444 
445   assert(this);
446 
447   /* Reenable CONNECTION events */
448   m_detected &= ~GSOCK_CONNECTION_FLAG;
449 
450   /* If the socket has already been created, we exit immediately */
451   if (m_fd == INVALID_SOCKET || !m_server)
452   {
453     m_error = GSOCK_INVSOCK;
454     return NULL;
455   }
456 
457   /* Create a GSocket object for the new connection */
458   connection = GSocket_new();
459 
460   if (!connection)
461   {
462     m_error = GSOCK_MEMERR;
463     return NULL;
464   }
465 
466   /* Wait for a connection (with timeout) */
467   if (Input_Timeout() == GSOCK_TIMEDOUT)
468   {
469     delete connection;
470     /* m_error set by _GSocket_Input_Timeout */
471     return NULL;
472   }
473 
474   connection->m_fd = accept(m_fd, &from, &fromlen);
475 
476   if (connection->m_fd == INVALID_SOCKET)
477   {
478     if (WSAGetLastError() == WSAEWOULDBLOCK)
479       m_error = GSOCK_WOULDBLOCK;
480     else
481       m_error = GSOCK_IOERR;
482 
483     delete connection;
484     return NULL;
485   }
486 
487   /* Initialize all fields */
488   connection->m_server   = false;
489   connection->m_stream   = true;
490 
491   /* Setup the peer address field */
492   connection->m_peer = GAddress_new();
493   if (!connection->m_peer)
494   {
495     delete connection;
496     m_error = GSOCK_MEMERR;
497     return NULL;
498   }
499   err = _GAddress_translate_from(connection->m_peer, &from, fromlen);
500   if (err != GSOCK_NOERROR)
501   {
502     GAddress_destroy(connection->m_peer);
503     delete connection;
504     m_error = err;
505     return NULL;
506   }
507 
508   ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
509   gs_gui_functions->Enable_Events(connection);
510 
511   return connection;
512 }
513 
514 /* GSocket_SetReusable:
515 *  Simply sets the m_resuable flag on the socket. GSocket_SetServer will
516 *  make the appropriate setsockopt() call.
517 *  Implemented as a GSocket function because clients (ie, wxSocketServer)
518 *  don't have access to the GSocket struct information.
519 *  Returns true if the flag was set correctly, false if an error occurred
520 *  (ie, if the parameter was NULL)
521 */
SetReusable()522 bool GSocket::SetReusable()
523 {
524     /* socket must not be null, and must not be in use/already bound */
525     if (this && m_fd == INVALID_SOCKET) {
526         m_reusable = true;
527         return true;
528     }
529     return false;
530 }
531 
532 /* Client specific parts */
533 
534 /* GSocket_Connect:
535  *  For stream (connection oriented) sockets, GSocket_Connect() tries
536  *  to establish a client connection to a server using the peer address
537  *  as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the
538  *  connection has been successfully established, or one of the error
539  *  codes listed below. Note that for nonblocking sockets, a return
540  *  value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection
541  *  request can be completed later; you should use GSocket_Select()
542  *  to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the
543  *  corresponding asynchronous events.
544  *
545  *  For datagram (non connection oriented) sockets, GSocket_Connect()
546  *  just sets the peer address established with GSocket_SetPeer() as
547  *  default destination.
548  *
549  *  Error codes:
550  *    GSOCK_INVSOCK    - the socket is in use or not valid.
551  *    GSOCK_INVADDR    - the peer address has not been established.
552  *    GSOCK_TIMEDOUT   - timeout, the connection failed.
553  *    GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
554  *    GSOCK_MEMERR     - couldn't allocate memory.
555  *    GSOCK_IOERR      - low-level error.
556  */
Connect(GSocketStream stream)557 GSocketError GSocket::Connect(GSocketStream stream)
558 {
559   int ret, err;
560   u_long arg = 1;
561 
562   assert(this);
563 
564   /* Enable CONNECTION events (needed for nonblocking connections) */
565   m_detected &= ~GSOCK_CONNECTION_FLAG;
566 
567   if (m_fd != INVALID_SOCKET)
568   {
569     m_error = GSOCK_INVSOCK;
570     return GSOCK_INVSOCK;
571   }
572 
573   if (!m_peer)
574   {
575     m_error = GSOCK_INVADDR;
576     return GSOCK_INVADDR;
577   }
578 
579   /* Streamed or dgram socket? */
580   m_stream   = (stream == GSOCK_STREAMED);
581   m_server   = false;
582   m_establishing = false;
583 
584   /* Create the socket */
585   m_fd = socket(m_peer->m_realfamily,
586                      m_stream? SOCK_STREAM : SOCK_DGRAM, 0);
587 
588   if (m_fd == INVALID_SOCKET)
589   {
590     m_error = GSOCK_IOERR;
591     return GSOCK_IOERR;
592   }
593 
594   ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
595   gs_gui_functions->Enable_Events(this);
596 
597   // If the reuse flag is set, use the applicable socket reuse flag
598   if (m_reusable)
599   {
600      setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
601   }
602 
603   // If a local address has been set, then we need to bind to it before calling connect
604   if (m_local && m_local->m_addr)
605   {
606     bind(m_fd, m_local->m_addr, m_local->m_len);
607   }
608 
609   /* Connect it to the peer address, with a timeout (see below) */
610   ret = connect(m_fd, m_peer->m_addr, m_peer->m_len);
611 
612   if (ret == SOCKET_ERROR)
613   {
614     err = WSAGetLastError();
615 
616     /* If connect failed with EWOULDBLOCK and the GSocket object
617      * is in blocking mode, we select() for the specified timeout
618      * checking for writability to see if the connection request
619      * completes.
620      */
621     if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
622     {
623       err = Connect_Timeout();
624 
625       if (err != GSOCK_NOERROR)
626       {
627         Close();
628         /* m_error is set in _GSocket_Connect_Timeout */
629       }
630 
631       return (GSocketError) err;
632     }
633 
634     /* If connect failed with EWOULDBLOCK and the GSocket object
635      * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
636      * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
637      * this way if the connection completes, a GSOCK_CONNECTION
638      * event will be generated, if enabled.
639      */
640     if ((err == WSAEWOULDBLOCK) && (m_non_blocking))
641     {
642       m_establishing = true;
643       m_error = GSOCK_WOULDBLOCK;
644       return GSOCK_WOULDBLOCK;
645     }
646 
647     /* If connect failed with an error other than EWOULDBLOCK,
648      * then the call to GSocket_Connect() has failed.
649      */
650     Close();
651     m_error = GSOCK_IOERR;
652     return GSOCK_IOERR;
653   }
654 
655   return GSOCK_NOERROR;
656 }
657 
658 /* Datagram sockets */
659 
660 /* GSocket_SetNonOriented:
661  *  Sets up this socket as a non-connection oriented (datagram) socket.
662  *  Before using this function, the local address must have been set
663  *  with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR
664  *  on success, or one of the following otherwise.
665  *
666  *  Error codes:
667  *    GSOCK_INVSOCK - the socket is in use.
668  *    GSOCK_INVADDR - the local address has not been set.
669  *    GSOCK_IOERR   - low-level error.
670  */
SetNonOriented()671 GSocketError GSocket::SetNonOriented()
672 {
673   u_long arg = 1;
674 
675   assert(this);
676 
677   if (m_fd != INVALID_SOCKET)
678   {
679     m_error = GSOCK_INVSOCK;
680     return GSOCK_INVSOCK;
681   }
682 
683   if (!m_local)
684   {
685     m_error = GSOCK_INVADDR;
686     return GSOCK_INVADDR;
687   }
688 
689   /* Initialize all fields */
690   m_stream   = false;
691   m_server   = false;
692 
693   /* Create the socket */
694   m_fd = socket(m_local->m_realfamily, SOCK_DGRAM, 0);
695 
696   if (m_fd == INVALID_SOCKET)
697   {
698     m_error = GSOCK_IOERR;
699     return GSOCK_IOERR;
700   }
701 
702   ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
703   gs_gui_functions->Enable_Events(this);
704 
705   if (m_reusable)
706   {
707     setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
708   }
709 
710   /* Bind to the local address,
711    * and retrieve the actual address bound.
712    */
713   if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
714       (getsockname(m_fd,
715                    m_local->m_addr,
716                    (WX_SOCKLEN_T *)&m_local->m_len) != 0))
717   {
718     Close();
719     m_error = GSOCK_IOERR;
720     return GSOCK_IOERR;
721   }
722 
723   return GSOCK_NOERROR;
724 }
725 
726 /* Generic IO */
727 
728 /* Like recv(), send(), ... */
Read(char * buffer,int size)729 int GSocket::Read(char *buffer, int size)
730 {
731   int ret;
732 
733   assert(this);
734 
735   /* Reenable INPUT events */
736   m_detected &= ~GSOCK_INPUT_FLAG;
737 
738   if (m_fd == INVALID_SOCKET || m_server)
739   {
740     m_error = GSOCK_INVSOCK;
741     return -1;
742   }
743 
744   /* If the socket is blocking, wait for data (with a timeout) */
745   if (Input_Timeout() == GSOCK_TIMEDOUT)
746   {
747     m_error = GSOCK_TIMEDOUT;
748     return -1;
749   }
750 
751   /* Read the data */
752   if (m_stream)
753     ret = Recv_Stream(buffer, size);
754   else
755     ret = Recv_Dgram(buffer, size);
756 
757   if (ret == SOCKET_ERROR)
758   {
759     if (WSAGetLastError() != WSAEWOULDBLOCK)
760       m_error = GSOCK_IOERR;
761     else
762       m_error = GSOCK_WOULDBLOCK;
763     return -1;
764   }
765 
766   return ret;
767 }
768 
Write(const char * buffer,int size)769 int GSocket::Write(const char *buffer, int size)
770 {
771   int ret;
772 
773   assert(this);
774 
775   if (m_fd == INVALID_SOCKET || m_server)
776   {
777     m_error = GSOCK_INVSOCK;
778     return -1;
779   }
780 
781   /* If the socket is blocking, wait for writability (with a timeout) */
782   if (Output_Timeout() == GSOCK_TIMEDOUT)
783     return -1;
784 
785   /* Write the data */
786   if (m_stream)
787     ret = Send_Stream(buffer, size);
788   else
789     ret = Send_Dgram(buffer, size);
790 
791   if (ret == SOCKET_ERROR)
792   {
793     if (WSAGetLastError() != WSAEWOULDBLOCK)
794       m_error = GSOCK_IOERR;
795     else
796       m_error = GSOCK_WOULDBLOCK;
797 
798     /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
799      * does). Once the first OUTPUT event is received, users can assume
800      * that the socket is writable until a read operation fails. Only then
801      * will further OUTPUT events be posted.
802      */
803     m_detected &= ~GSOCK_OUTPUT_FLAG;
804     return -1;
805   }
806 
807   return ret;
808 }
809 
810 /* GSocket_Select:
811  *  Polls the socket to determine its status. This function will
812  *  check for the events specified in the 'flags' parameter, and
813  *  it will return a mask indicating which operations can be
814  *  performed. This function won't block, regardless of the
815  *  mode (blocking | nonblocking) of the socket.
816  */
Select(GSocketEventFlags flags)817 GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
818 {
819   if (!gs_gui_functions->CanUseEventLoop())
820   {
821     GSocketEventFlags result = 0;
822     fd_set readfds;
823     fd_set writefds;
824     fd_set exceptfds;
825 
826     assert(this);
827 
828     FD_ZERO(&readfds);
829     FD_ZERO(&writefds);
830     FD_ZERO(&exceptfds);
831     FD_SET(m_fd, &readfds);
832     if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
833       FD_SET(m_fd, &writefds);
834     FD_SET(m_fd, &exceptfds);
835 
836     /* Check 'sticky' CONNECTION flag first */
837     result |= (GSOCK_CONNECTION_FLAG & m_detected);
838 
839     /* If we have already detected a LOST event, then don't try
840      * to do any further processing.
841      */
842     if ((m_detected & GSOCK_LOST_FLAG) != 0)
843     {
844       m_establishing = false;
845 
846       return (GSOCK_LOST_FLAG & flags);
847     }
848 
849     /* Try select now */
850     if (select(m_fd + 1, &readfds, &writefds, &exceptfds,
851         &m_timeout) <= 0)
852     {
853       /* What to do here? */
854       return (result & flags);
855     }
856 
857     /* Check for exceptions and errors */
858     if (FD_ISSET(m_fd, &exceptfds))
859     {
860       m_establishing = false;
861       m_detected = GSOCK_LOST_FLAG;
862 
863       /* LOST event: Abort any further processing */
864       return (GSOCK_LOST_FLAG & flags);
865     }
866 
867     /* Check for readability */
868     if (FD_ISSET(m_fd, &readfds))
869     {
870       result |= GSOCK_INPUT_FLAG;
871 
872       if (m_server && m_stream)
873       {
874         /* This is a TCP server socket that detected a connection.
875            While the INPUT_FLAG is also set, it doesn't matter on
876            this kind of  sockets, as we can only Accept() from them. */
877         result |= GSOCK_CONNECTION_FLAG;
878         m_detected |= GSOCK_CONNECTION_FLAG;
879       }
880     }
881 
882     /* Check for writability */
883     if (FD_ISSET(m_fd, &writefds))
884     {
885       if (m_establishing && !m_server)
886       {
887         int error;
888         WX_SOCKLEN_T len = sizeof(error);
889 
890         m_establishing = false;
891 
892         getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
893 
894         if (error)
895         {
896           m_detected = GSOCK_LOST_FLAG;
897 
898           /* LOST event: Abort any further processing */
899           return (GSOCK_LOST_FLAG & flags);
900         }
901         else
902         {
903           result |= GSOCK_CONNECTION_FLAG;
904           m_detected |= GSOCK_CONNECTION_FLAG;
905         }
906       }
907       else
908       {
909         result |= GSOCK_OUTPUT_FLAG;
910       }
911     }
912 
913     return (result & flags);
914   }
915   else /* USE_GUI() */
916   {
917     assert(this);
918     return flags & m_detected;
919   }
920 }
921 
922 /* Attributes */
923 
924 /* GSocket_SetNonBlocking:
925  *  Sets the socket to non-blocking mode. All IO calls will return
926  *  immediately.
927  */
SetNonBlocking(bool non_block)928 void GSocket::SetNonBlocking(bool non_block)
929 {
930   assert(this);
931 
932   m_non_blocking = non_block;
933 }
934 
935 /* GSocket_SetTimeout:
936  *  Sets the timeout for blocking calls. Time is expressed in
937  *  milliseconds.
938  */
SetTimeout(unsigned long millis)939 void GSocket::SetTimeout(unsigned long millis)
940 {
941   assert(this);
942 
943   m_timeout.tv_sec  = (millis / 1000);
944   m_timeout.tv_usec = (millis % 1000) * 1000;
945 }
946 
947 /* GSocket_GetError:
948  *  Returns the last error occurred for this socket. Note that successful
949  *  operations do not clear this back to GSOCK_NOERROR, so use it only
950  *  after an error.
951  */
GetError()952 GSocketError WXDLLIMPEXP_NET GSocket::GetError()
953 {
954   assert(this);
955 
956   return m_error;
957 }
958 
959 /* Callbacks */
960 
961 /* GSOCK_INPUT:
962  *   There is data to be read in the input buffer. If, after a read
963  *   operation, there is still data available, the callback function will
964  *   be called again.
965  * GSOCK_OUTPUT:
966  *   The socket is available for writing. That is, the next write call
967  *   won't block. This event is generated only once, when the connection is
968  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK,
969  *   when the output buffer empties again. This means that the app should
970  *   assume that it can write since the first OUTPUT event, and no more
971  *   OUTPUT events will be generated unless an error occurs.
972  * GSOCK_CONNECTION:
973  *   Connection successfully established, for client sockets, or incoming
974  *   client connection, for server sockets. Wait for this event (also watch
975  *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
976  * GSOCK_LOST:
977  *   The connection is lost (or a connection request failed); this could
978  *   be due to a failure, or due to the peer closing it gracefully.
979  */
980 
981 /* GSocket_SetCallback:
982  *  Enables the callbacks specified by 'flags'. Note that 'flags'
983  *  may be a combination of flags OR'ed toghether, so the same
984  *  callback function can be made to accept different events.
985  *  The callback function must have the following prototype:
986  *
987  *  void function(GSocket *socket, GSocketEvent event, char *cdata)
988  */
SetCallback(GSocketEventFlags flags,GSocketCallback callback,char * cdata)989 void GSocket::SetCallback(GSocketEventFlags flags,
990                          GSocketCallback callback, char *cdata)
991 {
992   int count;
993 
994   assert(this);
995 
996   for (count = 0; count < GSOCK_MAX_EVENT; count++)
997   {
998     if ((flags & (1 << count)) != 0)
999     {
1000       m_cbacks[count] = callback;
1001       m_data[count] = cdata;
1002     }
1003   }
1004 }
1005 
1006 /* GSocket_UnsetCallback:
1007  *  Disables all callbacks specified by 'flags', which may be a
1008  *  combination of flags OR'ed toghether.
1009  */
UnsetCallback(GSocketEventFlags flags)1010 void GSocket::UnsetCallback(GSocketEventFlags flags)
1011 {
1012   int count;
1013 
1014   assert(this);
1015 
1016   for (count = 0; count < GSOCK_MAX_EVENT; count++)
1017   {
1018     if ((flags & (1 << count)) != 0)
1019     {
1020       m_cbacks[count] = NULL;
1021       m_data[count] = NULL;
1022     }
1023   }
1024 }
1025 
GetSockOpt(int level,int optname,void * optval,int * optlen)1026 GSocketError GSocket::GetSockOpt(int level, int optname,
1027                                 void *optval, int *optlen)
1028 {
1029     if (getsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
1030     {
1031         return GSOCK_NOERROR;
1032     }
1033     return GSOCK_OPTERR;
1034 }
1035 
SetSockOpt(int level,int optname,const void * optval,int optlen)1036 GSocketError GSocket::SetSockOpt(int level, int optname,
1037                                 const void *optval, int optlen)
1038 {
1039     if (setsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
1040     {
1041         return GSOCK_NOERROR;
1042     }
1043     return GSOCK_OPTERR;
1044 }
1045 
1046 /* Internals (IO) */
1047 
1048 /* _GSocket_Input_Timeout:
1049  *  For blocking sockets, wait until data is available or
1050  *  until timeout ellapses.
1051  */
Input_Timeout()1052 GSocketError GSocket::Input_Timeout()
1053 {
1054   fd_set readfds;
1055 
1056   if (!m_non_blocking)
1057   {
1058     FD_ZERO(&readfds);
1059     FD_SET(m_fd, &readfds);
1060     if (select(0, &readfds, NULL, NULL, &m_timeout) == 0)
1061     {
1062       m_error = GSOCK_TIMEDOUT;
1063       return GSOCK_TIMEDOUT;
1064     }
1065   }
1066   return GSOCK_NOERROR;
1067 }
1068 
1069 /* _GSocket_Output_Timeout:
1070  *  For blocking sockets, wait until data can be sent without
1071  *  blocking or until timeout ellapses.
1072  */
Output_Timeout()1073 GSocketError GSocket::Output_Timeout()
1074 {
1075   fd_set writefds;
1076 
1077   if (!m_non_blocking)
1078   {
1079     FD_ZERO(&writefds);
1080     FD_SET(m_fd, &writefds);
1081     if (select(0, NULL, &writefds, NULL, &m_timeout) == 0)
1082     {
1083       m_error = GSOCK_TIMEDOUT;
1084       return GSOCK_TIMEDOUT;
1085     }
1086   }
1087   return GSOCK_NOERROR;
1088 }
1089 
1090 /* _GSocket_Connect_Timeout:
1091  *  For blocking sockets, wait until the connection is
1092  *  established or fails, or until timeout ellapses.
1093  */
Connect_Timeout()1094 GSocketError GSocket::Connect_Timeout()
1095 {
1096   fd_set writefds;
1097   fd_set exceptfds;
1098 
1099   FD_ZERO(&writefds);
1100   FD_ZERO(&exceptfds);
1101   FD_SET(m_fd, &writefds);
1102   FD_SET(m_fd, &exceptfds);
1103   if (select(0, NULL, &writefds, &exceptfds, &m_timeout) == 0)
1104   {
1105     m_error = GSOCK_TIMEDOUT;
1106     return GSOCK_TIMEDOUT;
1107   }
1108   if (!FD_ISSET(m_fd, &writefds))
1109   {
1110     m_error = GSOCK_IOERR;
1111     return GSOCK_IOERR;
1112   }
1113 
1114   return GSOCK_NOERROR;
1115 }
1116 
Recv_Stream(char * buffer,int size)1117 int GSocket::Recv_Stream(char *buffer, int size)
1118 {
1119   return recv(m_fd, buffer, size, 0);
1120 }
1121 
Recv_Dgram(char * buffer,int size)1122 int GSocket::Recv_Dgram(char *buffer, int size)
1123 {
1124   struct sockaddr from;
1125   WX_SOCKLEN_T fromlen = sizeof(from);
1126   int ret;
1127   GSocketError err;
1128 
1129   ret = recvfrom(m_fd, buffer, size, 0, &from, &fromlen);
1130 
1131   if (ret == SOCKET_ERROR)
1132     return SOCKET_ERROR;
1133 
1134   /* Translate a system address into a GSocket address */
1135   if (!m_peer)
1136   {
1137     m_peer = GAddress_new();
1138     if (!m_peer)
1139     {
1140       m_error = GSOCK_MEMERR;
1141       return -1;
1142     }
1143   }
1144   err = _GAddress_translate_from(m_peer, &from, fromlen);
1145   if (err != GSOCK_NOERROR)
1146   {
1147     GAddress_destroy(m_peer);
1148     m_peer  = NULL;
1149     m_error = err;
1150     return -1;
1151   }
1152 
1153   return ret;
1154 }
1155 
Send_Stream(const char * buffer,int size)1156 int GSocket::Send_Stream(const char *buffer, int size)
1157 {
1158   return send(m_fd, buffer, size, 0);
1159 }
1160 
Send_Dgram(const char * buffer,int size)1161 int GSocket::Send_Dgram(const char *buffer, int size)
1162 {
1163   struct sockaddr *addr;
1164   int len, ret;
1165   GSocketError err;
1166 
1167   if (!m_peer)
1168   {
1169     m_error = GSOCK_INVADDR;
1170     return -1;
1171   }
1172 
1173   err = _GAddress_translate_to(m_peer, &addr, &len);
1174   if (err != GSOCK_NOERROR)
1175   {
1176     m_error = err;
1177     return -1;
1178   }
1179 
1180   ret = sendto(m_fd, buffer, size, 0, addr, len);
1181 
1182   /* Frees memory allocated by _GAddress_translate_to */
1183   free(addr);
1184 
1185   return ret;
1186 }
1187 
1188 /* Compatibility functions for GSocket */
GSocket_new(void)1189 GSocket *GSocket_new(void)
1190 {
1191     GSocket *newsocket = new GSocket();
1192     if(newsocket->IsOk())
1193         return newsocket;
1194     delete newsocket;
1195     return NULL;
1196 }
1197 
1198 
1199 /*
1200  * -------------------------------------------------------------------------
1201  * GAddress
1202  * -------------------------------------------------------------------------
1203  */
1204 
1205 /* CHECK_ADDRESS verifies that the current address family is either
1206  * GSOCK_NOFAMILY or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it
1207  * initalizes it to be a GSOCK_*family*. In other cases, it returns
1208  * an appropiate error code.
1209  *
1210  * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
1211  */
1212 #define CHECK_ADDRESS(address, family)                              \
1213 {                                                                   \
1214   if (address->m_family == GSOCK_NOFAMILY)                          \
1215     if (_GAddress_Init_##family(address) != GSOCK_NOERROR)          \
1216       return address->m_error;                                      \
1217   if (address->m_family != GSOCK_##family)                          \
1218   {                                                                 \
1219     address->m_error = GSOCK_INVADDR;                               \
1220     return GSOCK_INVADDR;                                           \
1221   }                                                                 \
1222 }
1223 
1224 #define CHECK_ADDRESS_RETVAL(address, family, retval)               \
1225 {                                                                   \
1226   if (address->m_family == GSOCK_NOFAMILY)                          \
1227     if (_GAddress_Init_##family(address) != GSOCK_NOERROR)          \
1228       return retval;                                                \
1229   if (address->m_family != GSOCK_##family)                          \
1230   {                                                                 \
1231     address->m_error = GSOCK_INVADDR;                               \
1232     return retval;                                                  \
1233   }                                                                 \
1234 }
1235 
1236 
GAddress_new(void)1237 GAddress *GAddress_new(void)
1238 {
1239   GAddress *address;
1240 
1241   if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1242     return NULL;
1243 
1244   address->m_family = GSOCK_NOFAMILY;
1245   address->m_addr   = NULL;
1246   address->m_len    = 0;
1247 
1248   return address;
1249 }
1250 
GAddress_copy(GAddress * address)1251 GAddress *GAddress_copy(GAddress *address)
1252 {
1253   GAddress *addr2;
1254 
1255   assert(address != NULL);
1256 
1257   if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1258     return NULL;
1259 
1260   memcpy(addr2, address, sizeof(GAddress));
1261 
1262   if (address->m_addr)
1263   {
1264     addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
1265     if (addr2->m_addr == NULL)
1266     {
1267       free(addr2);
1268       return NULL;
1269     }
1270     memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1271   }
1272 
1273   return addr2;
1274 }
1275 
GAddress_destroy(GAddress * address)1276 void GAddress_destroy(GAddress *address)
1277 {
1278   assert(address != NULL);
1279 
1280   if (address->m_addr)
1281     free(address->m_addr);
1282 
1283   free(address);
1284 }
1285 
GAddress_SetFamily(GAddress * address,GAddressType type)1286 void GAddress_SetFamily(GAddress *address, GAddressType type)
1287 {
1288   assert(address != NULL);
1289 
1290   address->m_family = type;
1291 }
1292 
GAddress_GetFamily(GAddress * address)1293 GAddressType GAddress_GetFamily(GAddress *address)
1294 {
1295   assert(address != NULL);
1296 
1297   return address->m_family;
1298 }
1299 
_GAddress_translate_from(GAddress * address,struct sockaddr * addr,int len)1300 GSocketError _GAddress_translate_from(GAddress *address,
1301                                       struct sockaddr *addr, int len)
1302 {
1303   address->m_realfamily = addr->sa_family;
1304   switch (addr->sa_family)
1305   {
1306     case AF_INET:
1307       address->m_family = GSOCK_INET;
1308       break;
1309     case AF_UNIX:
1310       address->m_family = GSOCK_UNIX;
1311       break;
1312 #ifdef AF_INET6
1313     case AF_INET6:
1314       address->m_family = GSOCK_INET6;
1315       break;
1316 #endif
1317     default:
1318     {
1319       address->m_error = GSOCK_INVOP;
1320       return GSOCK_INVOP;
1321     }
1322   }
1323 
1324   if (address->m_addr)
1325     free(address->m_addr);
1326 
1327   address->m_len = len;
1328   address->m_addr = (struct sockaddr *) malloc(len);
1329 
1330   if (address->m_addr == NULL)
1331   {
1332     address->m_error = GSOCK_MEMERR;
1333     return GSOCK_MEMERR;
1334   }
1335   memcpy(address->m_addr, addr, len);
1336 
1337   return GSOCK_NOERROR;
1338 }
1339 
_GAddress_translate_to(GAddress * address,struct sockaddr ** addr,int * len)1340 GSocketError _GAddress_translate_to(GAddress *address,
1341                                     struct sockaddr **addr, int *len)
1342 {
1343   if (!address->m_addr)
1344   {
1345     address->m_error = GSOCK_INVADDR;
1346     return GSOCK_INVADDR;
1347   }
1348 
1349   *len = address->m_len;
1350   *addr = (struct sockaddr *) malloc(address->m_len);
1351   if (*addr == NULL)
1352   {
1353     address->m_error = GSOCK_MEMERR;
1354     return GSOCK_MEMERR;
1355   }
1356 
1357   memcpy(*addr, address->m_addr, address->m_len);
1358   return GSOCK_NOERROR;
1359 }
1360 
1361 /*
1362  * -------------------------------------------------------------------------
1363  * Internet address family
1364  * -------------------------------------------------------------------------
1365  */
1366 
_GAddress_Init_INET(GAddress * address)1367 GSocketError _GAddress_Init_INET(GAddress *address)
1368 {
1369   address->m_len  = sizeof(struct sockaddr_in);
1370   address->m_addr = (struct sockaddr *) malloc(address->m_len);
1371   if (address->m_addr == NULL)
1372   {
1373     address->m_error = GSOCK_MEMERR;
1374     return GSOCK_MEMERR;
1375   }
1376 
1377   address->m_family = GSOCK_INET;
1378   address->m_realfamily = AF_INET;
1379   ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
1380   ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
1381 
1382   return GSOCK_NOERROR;
1383 }
1384 
GAddress_INET_SetHostName(GAddress * address,const char * hostname)1385 GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1386 {
1387   struct hostent *he;
1388   struct in_addr *addr;
1389 
1390   assert(address != NULL);
1391 
1392   CHECK_ADDRESS(address, INET);
1393 
1394   addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1395 
1396   addr->s_addr = inet_addr(hostname);
1397 
1398   /* If it is a numeric host name, convert it now */
1399   if (addr->s_addr == INADDR_NONE)
1400   {
1401     struct in_addr *array_addr;
1402 
1403     /* It is a real name, we solve it */
1404     if ((he = gethostbyname(hostname)) == NULL)
1405     {
1406       /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
1407       address->m_error = GSOCK_NOHOST;
1408       return GSOCK_NOHOST;
1409     }
1410     array_addr = (struct in_addr *) *(he->h_addr_list);
1411     addr->s_addr = array_addr[0].s_addr;
1412   }
1413   return GSOCK_NOERROR;
1414 }
1415 
GAddress_INET_SetAnyAddress(GAddress * address)1416 GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1417 {
1418   return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1419 }
1420 
GAddress_INET_SetHostAddress(GAddress * address,unsigned long hostaddr)1421 GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1422                                           unsigned long hostaddr)
1423 {
1424   struct in_addr *addr;
1425 
1426   assert(address != NULL);
1427 
1428   CHECK_ADDRESS(address, INET);
1429 
1430   addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1431   addr->s_addr = htonl(hostaddr);
1432 
1433   return GSOCK_NOERROR;
1434 }
1435 
GAddress_INET_SetPortName(GAddress * address,const char * port,const char * protocol)1436 GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1437                                        const char *protocol)
1438 {
1439   struct servent *se;
1440   struct sockaddr_in *addr;
1441 
1442   assert(address != NULL);
1443   CHECK_ADDRESS(address, INET);
1444 
1445   if (!port)
1446   {
1447     address->m_error = GSOCK_INVPORT;
1448     return GSOCK_INVPORT;
1449   }
1450 
1451   se = getservbyname(port, protocol);
1452   if (!se)
1453   {
1454     if (isdigit((unsigned char) port[0]))
1455     {
1456       int port_int;
1457 
1458       port_int = atoi(port);
1459       addr = (struct sockaddr_in *)address->m_addr;
1460       addr->sin_port = htons((u_short) port_int);
1461       return GSOCK_NOERROR;
1462     }
1463 
1464     address->m_error = GSOCK_INVPORT;
1465     return GSOCK_INVPORT;
1466   }
1467 
1468   addr = (struct sockaddr_in *)address->m_addr;
1469   addr->sin_port = se->s_port;
1470 
1471   return GSOCK_NOERROR;
1472 }
1473 
GAddress_INET_SetPort(GAddress * address,unsigned short port)1474 GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1475 {
1476   struct sockaddr_in *addr;
1477 
1478   assert(address != NULL);
1479   CHECK_ADDRESS(address, INET);
1480 
1481   addr = (struct sockaddr_in *)address->m_addr;
1482   addr->sin_port = htons(port);
1483 
1484   return GSOCK_NOERROR;
1485 }
1486 
GAddress_INET_GetHostName(GAddress * address,char * hostname,size_t sbuf)1487 GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1488 {
1489   struct hostent *he;
1490   char *addr_buf;
1491   struct sockaddr_in *addr;
1492 
1493   assert(address != NULL);
1494   CHECK_ADDRESS(address, INET);
1495 
1496   addr = (struct sockaddr_in *)address->m_addr;
1497   addr_buf = (char *)&(addr->sin_addr);
1498 
1499   he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1500   if (he == NULL)
1501   {
1502     address->m_error = GSOCK_NOHOST;
1503     return GSOCK_NOHOST;
1504   }
1505 
1506   strncpy(hostname, he->h_name, sbuf);
1507 
1508   return GSOCK_NOERROR;
1509 }
1510 
GAddress_INET_GetHostAddress(GAddress * address)1511 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1512 {
1513   struct sockaddr_in *addr;
1514 
1515   assert(address != NULL);
1516   CHECK_ADDRESS_RETVAL(address, INET, 0);
1517 
1518   addr = (struct sockaddr_in *)address->m_addr;
1519 
1520   return ntohl(addr->sin_addr.s_addr);
1521 }
1522 
GAddress_INET_GetPort(GAddress * address)1523 unsigned short GAddress_INET_GetPort(GAddress *address)
1524 {
1525   struct sockaddr_in *addr;
1526 
1527   assert(address != NULL);
1528   CHECK_ADDRESS_RETVAL(address, INET, 0);
1529 
1530   addr = (struct sockaddr_in *)address->m_addr;
1531   return ntohs(addr->sin_port);
1532 }
1533 
1534 /*
1535  * -------------------------------------------------------------------------
1536  * Unix address family
1537  * -------------------------------------------------------------------------
1538  */
1539 
_GAddress_Init_UNIX(GAddress * address)1540 GSocketError _GAddress_Init_UNIX(GAddress *address)
1541 {
1542   assert (address != NULL);
1543   address->m_error = GSOCK_INVADDR;
1544   return GSOCK_INVADDR;
1545 }
1546 
GAddress_UNIX_SetPath(GAddress * address,const char * WXUNUSED (path))1547 GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
1548 {
1549   assert (address != NULL);
1550   address->m_error = GSOCK_INVADDR;
1551   return GSOCK_INVADDR;
1552 }
1553 
GAddress_UNIX_GetPath(GAddress * address,char * WXUNUSED (path),size_t WXUNUSED (sbuf))1554 GSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
1555 {
1556   assert (address != NULL);
1557   address->m_error = GSOCK_INVADDR;
1558   return GSOCK_INVADDR;
1559 }
1560 
1561 #else /* !wxUSE_SOCKETS */
1562 
1563 /*
1564  * Translation unit shouldn't be empty, so include this typedef to make the
1565  * compiler (VC++ 6.0, for example) happy
1566  */
1567 typedef void (*wxDummy)();
1568 
1569 #endif  /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */
1570