1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/sockmsw.cpp
3 // Purpose: MSW-specific socket code
4 // Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
6 // Copyright: (C) 1999-1997, Guilhem Lavaux
7 // (C) 1999-2000, Guillermo Rodriguez Garcia
8 // (C) 2008 Vadim Zeitlin
10 // License: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
23 /* including rasasync.h (included from windows.h itself included from
24 * wx/setup.h and/or winsock.h results in this warning for
25 * RPCNOTIFICATION_ROUTINE
28 # pragma warning(disable:4115) /* named type definition in parentheses */
31 #include "wx/private/socket.h"
32 #include "wx/apptrait.h"
33 #include "wx/thread.h"
35 extern "C" WXDLLIMPEXP_BASE HINSTANCE
wxGetInstance();
36 #define INSTANCE wxGetInstance()
40 #if defined(__CYGWIN__)
41 //CYGWIN gives annoying warning about runtime stuff if we don't do this
42 # define USE_SYS_TYPES_FD_SET
43 # include <sys/types.h>
48 * As WSAAsyncSelect is not present on WinCE, it now uses WSACreateEvent,
49 * WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents. When
50 * enabling eventhandling for a socket a new thread it created that keeps track
51 * of the events and posts a messageto the hidden window to use the standard
54 #include "wx/msw/wince/net.h"
55 #include "wx/hashmap.h"
56 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash
,wxIntegerEqual
,SocketHash
);
59 #define isdigit(x) (x > 47 && x < 58)
61 #include "wx/msw/wince/net.h"
66 # pragma warning(default:4115) /* named type definition in parentheses */
69 #define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
71 /* implemented in utils.cpp */
72 extern "C" WXDLLIMPEXP_BASE HWND
73 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
);
75 /* Maximum number of different wxSocket objects at a given time.
76 * This value can be modified at will, but it CANNOT be greater
77 * than (0x7FFF - WM_USER + 1)
79 #define MAXSOCKETS 1024
81 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
82 #error "MAXSOCKETS is too big!"
86 typedef int (PASCAL
*WSAAsyncSelectFunc
)(SOCKET
,HWND
,u_int
,long);
88 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
90 typedef struct _WSANETWORKEVENTS
{
93 } WSANETWORKEVENTS
, FAR
* LPWSANETWORKEVENTS
;
94 typedef HANDLE (PASCAL
*WSACreateEventFunc
)();
95 typedef int (PASCAL
*WSAEventSelectFunc
)(SOCKET
,HANDLE
,long);
96 typedef int (PASCAL
*WSAWaitForMultipleEventsFunc
)(long,HANDLE
,BOOL
,long,BOOL
);
97 typedef int (PASCAL
*WSAEnumNetworkEventsFunc
)(SOCKET
,HANDLE
,LPWSANETWORKEVENTS
);
100 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND
, UINT
, WPARAM
, LPARAM
);
102 /* Global variables */
105 wxCRIT_SECT_DECLARE_MEMBER(gs_critical
);
106 static wxSocketImplMSW
*socketList
[MAXSOCKETS
];
107 static int firstAvailable
;
110 static WSAAsyncSelectFunc gs_WSAAsyncSelect
= NULL
;
112 static SocketHash socketHash
;
113 static unsigned int currSocket
;
114 HANDLE hThread
[MAXSOCKETS
];
115 static WSACreateEventFunc gs_WSACreateEvent
= NULL
;
116 static WSAEventSelectFunc gs_WSAEventSelect
= NULL
;
117 static WSAWaitForMultipleEventsFunc gs_WSAWaitForMultipleEvents
= NULL
;
118 static WSAEnumNetworkEventsFunc gs_WSAEnumNetworkEvents
= NULL
;
119 /* This structure will be used to pass data on to the thread that handles socket events.
121 typedef struct thread_data
{
123 unsigned long msgnumber
;
125 unsigned long lEvent
;
129 static HMODULE gs_wsock32dll
= 0;
133 /* This thread handles socket events on WinCE using WSAEventSelect() as WSAAsyncSelect is not supported.
134 * When an event occures for the socket, it is checked what kind of event happend and the correct message gets posted
135 * so that the hidden window can handle it as it would in other MSW builds.
137 DWORD WINAPI
SocketThread(LPVOID data
)
139 WSANETWORKEVENTS NetworkEvents
;
140 thread_data
* d
= (thread_data
*)data
;
142 HANDLE NetworkEvent
= gs_WSACreateEvent();
143 gs_WSAEventSelect(d
->fd
, NetworkEvent
, d
->lEvent
);
145 while(socketHash
[d
->fd
] == true)
147 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent
, FALSE
,INFINITE
, FALSE
)) == WAIT_FAILED
)
149 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
152 if (gs_WSAEnumNetworkEvents(d
->fd
,NetworkEvent
, &NetworkEvents
) == SOCKET_ERROR
)
154 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
158 long flags
= NetworkEvents
.lNetworkEvents
;
160 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_READ
);
161 if (flags
& FD_WRITE
)
162 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_WRITE
);
164 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_OOB
);
165 if (flags
& FD_ACCEPT
)
166 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_ACCEPT
);
167 if (flags
& FD_CONNECT
)
168 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CONNECT
);
169 if (flags
& FD_CLOSE
)
170 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CLOSE
);
173 gs_WSAEventSelect(d
->fd
, NetworkEvent
, 0);
179 // ----------------------------------------------------------------------------
180 // MSW implementation of wxSocketManager
181 // ----------------------------------------------------------------------------
183 class wxSocketMSWManager
: public wxSocketManager
186 virtual bool OnInit();
187 virtual void OnExit();
189 virtual wxSocketImpl
*CreateSocket(wxSocketBase
& wxsocket
)
191 return new wxSocketImplMSW(wxsocket
);
193 virtual void Install_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
194 virtual void Uninstall_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
197 bool wxSocketMSWManager
::OnInit()
199 static LPCTSTR pclassname
= NULL
;
202 /* Create internal window for event notifications */
203 hWin
= wxCreateHiddenWindow(&pclassname
, CLASSNAME
, wxSocket_Internal_WinProc
);
207 /* Initialize socket list */
208 for (i
= 0; i
< MAXSOCKETS
; i
++)
210 socketList
[i
] = NULL
;
214 /* Load WSAAsyncSelect from wsock32.dll (we don't link against it
215 statically to avoid dependency on wsock32.dll for apps that don't use
218 gs_wsock32dll
= LoadLibrary(wxT("wsock32.dll"));
221 gs_WSAAsyncSelect
=(WSAAsyncSelectFunc
)GetProcAddress(gs_wsock32dll
,
223 if (!gs_WSAAsyncSelect
)
226 /* On WinCE we load ws2.dll which will provide the needed functions.
228 gs_wsock32dll
= LoadLibrary(wxT("ws2.dll"));
231 gs_WSAEventSelect
=(WSAEventSelectFunc
)GetProcAddress(gs_wsock32dll
,
232 wxT("WSAEventSelect"));
233 if (!gs_WSAEventSelect
)
236 gs_WSACreateEvent
=(WSACreateEventFunc
)GetProcAddress(gs_wsock32dll
,
237 wxT("WSACreateEvent"));
238 if (!gs_WSACreateEvent
)
241 gs_WSAWaitForMultipleEvents
=(WSAWaitForMultipleEventsFunc
)GetProcAddress(gs_wsock32dll
,
242 wxT("WSAWaitForMultipleEvents"));
243 if (!gs_WSAWaitForMultipleEvents
)
246 gs_WSAEnumNetworkEvents
=(WSAEnumNetworkEventsFunc
)GetProcAddress(gs_wsock32dll
,
247 wxT("WSAEnumNetworkEvents"));
248 if (!gs_WSAEnumNetworkEvents
)
254 // finally initialize WinSock
256 return WSAStartup((1 << 8) | 1, &wsaData
) == 0;
259 void wxSocketMSWManager
::OnExit()
262 /* Delete the threads here */
263 for(unsigned int i
=0; i
< currSocket
; i
++)
264 CloseHandle(hThread
[i
]);
266 /* Destroy internal window */
268 UnregisterClass(CLASSNAME
, INSTANCE
);
270 /* Unlock wsock32.dll */
273 FreeLibrary(gs_wsock32dll
);
280 /* Per-socket GUI initialization / cleanup */
282 wxSocketImplMSW
::wxSocketImplMSW(wxSocketBase
& wxsocket
)
283 : wxSocketImpl(wxsocket
)
285 /* Allocate a new message number for this socket */
286 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
288 int i
= firstAvailable
;
289 while (socketList
[i
] != NULL
)
291 i
= (i
+ 1) % MAXSOCKETS
;
293 if (i
== firstAvailable
) /* abort! */
295 m_msgnumber
= 0; // invalid
299 socketList
[i
] = this;
300 firstAvailable
= (i
+ 1) % MAXSOCKETS
;
301 m_msgnumber
= (i
+ WM_USER
);
304 wxSocketImplMSW
::~wxSocketImplMSW()
306 /* Remove the socket from the list */
307 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
311 // we need to remove any pending messages for this socket to avoid having
312 // them sent to a new socket which could reuse the same message number as
313 // soon as we destroy this one
315 while ( ::PeekMessage(&msg
, hWin
, m_msgnumber
, m_msgnumber
, PM_REMOVE
) )
318 socketList
[m_msgnumber
- WM_USER
] = NULL
;
320 //else: the socket has never been created successfully
323 /* Windows proc for asynchronous event handling */
325 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND hWnd
,
330 if ( uMsg
< WM_USER
|| uMsg
> (WM_USER
+ MAXSOCKETS
- 1))
331 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
333 wxSocketImplMSW
*socket
;
334 wxSocketNotify event
;
336 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
338 socket
= socketList
[(uMsg
- WM_USER
)];
339 event
= (wxSocketNotify
) -1;
341 /* Check that the socket still exists (it has not been
342 * destroyed) and for safety, check that the m_fd field
343 * is what we expect it to be.
345 if ((socket
!= NULL
) && ((WPARAM
)socket
->m_fd
== wParam
))
347 switch WSAGETSELECTEVENT(lParam
)
349 case FD_READ
: event
= wxSOCKET_INPUT
; break;
350 case FD_WRITE
: event
= wxSOCKET_OUTPUT
; break;
351 case FD_ACCEPT
: event
= wxSOCKET_CONNECTION
; break;
354 if (WSAGETSELECTERROR(lParam
) != 0)
355 event
= wxSOCKET_LOST
;
357 event
= wxSOCKET_CONNECTION
;
360 case FD_CLOSE
: event
= wxSOCKET_LOST
; break;
365 if (event
== wxSOCKET_LOST
)
366 socket
->m_detected
= wxSOCKET_LOST_FLAG
;
368 socket
->m_detected
|= (1 << event
);
371 } // unlock gs_critical
374 socket
->NotifyOnStateChange(event
);
380 * Enable all event notifications; we need to be notified of all
381 * events for internal processing, but we will only notify users
382 * when an appropriate callback function has been installed.
384 void wxSocketMSWManager
::Install_Callback(wxSocketImpl
*socket_
,
385 wxSocketNotify
WXUNUSED(event
))
387 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
389 if (socket
->m_fd
!= INVALID_SOCKET
)
391 /* We could probably just subscribe to all events regardless
392 * of the socket type, but MS recommends to do it this way.
394 long lEvent
= socket
->m_server?
395 FD_ACCEPT
: (FD_READ
| FD_WRITE
| FD_CONNECT
| FD_CLOSE
);
397 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, lEvent
);
400 * WinCE creates a thread for socket event handling.
401 * All needed parameters get passed through the thread_data structure.
404 thread_data
* d
= new thread_data
;
407 d
->msgnumber
= socket
->m_msgnumber
;
408 d
->fd
= socket
->m_fd
;
409 socketHash
[socket
->m_fd
] = true;
410 hThread
[currSocket
++] = CreateThread(NULL
, 0, &SocketThread
,(LPVOID
)d
, 0, NULL
);
416 * Disable event notifications (used when shutting down the socket)
418 void wxSocketMSWManager
::Uninstall_Callback(wxSocketImpl
*socket_
,
419 wxSocketNotify
WXUNUSED(event
))
421 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
423 if (socket
->m_fd
!= INVALID_SOCKET
)
426 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, 0);
429 socketHash
[socket
->m_fd
] = false;
434 // set the wxBase variable to point to our wxSocketManager implementation
436 // see comments in wx/apptrait.h for the explanation of why do we do it
438 static struct ManagerSetter
442 static wxSocketMSWManager s_manager
;
443 wxAppTraits
::SetDefaultSocketManager(&s_manager
);
447 // ============================================================================
448 // wxSocketImpl implementation
449 // ============================================================================
452 wxSocketImpl
*wxSocketImpl
::Create(wxSocketBase
& wxsocket
)
454 return new wxSocketImplMSW(wxsocket
);
457 void wxSocketImplMSW
::DoClose()
459 wxSocketManager
::Get()->
460 Uninstall_Callback(this, wxSOCKET_MAX_EVENT
/* unused anyhow */);
466 * Waits for an incoming client connection. Returns a pointer to
467 * a wxSocketImpl object, or NULL if there was an error, in which case
468 * the last error field will be updated for the calling wxSocketImpl.
470 * Error codes (set in the calling wxSocketImpl)
471 * wxSOCKET_INVSOCK - the socket is not valid or not a server.
472 * wxSOCKET_TIMEDOUT - timeout, no incoming connections.
473 * wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
474 * wxSOCKET_MEMERR - couldn't allocate memory.
475 * wxSOCKET_IOERR - low-level error.
477 wxSocketImpl
*wxSocketImplMSW
::WaitConnection(wxSocketBase
& wxsocket
)
479 wxSocketImpl
*connection
;
481 WX_SOCKLEN_T fromlen
= sizeof(from
);
485 /* Reenable CONNECTION events */
486 m_detected
&= ~wxSOCKET_CONNECTION_FLAG
;
488 /* If the socket has already been created, we exit immediately */
489 if (m_fd
== INVALID_SOCKET
|| !m_server
)
491 m_error
= wxSOCKET_INVSOCK
;
495 /* Create a wxSocketImpl object for the new connection */
496 connection
= wxSocketImplMSW
::Create(wxsocket
);
500 m_error
= wxSOCKET_MEMERR
;
504 /* Wait for a connection (with timeout) */
505 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
508 /* m_error set by Input_Timeout */
512 connection
->m_fd
= accept(m_fd
, (sockaddr
*)&from
, &fromlen
);
514 if (connection
->m_fd
== INVALID_SOCKET
)
516 if (WSAGetLastError() == WSAEWOULDBLOCK
)
517 m_error
= wxSOCKET_WOULDBLOCK
;
519 m_error
= wxSOCKET_IOERR
;
525 /* Initialize all fields */
526 connection
->m_server
= false;
527 connection
->m_stream
= true;
529 /* Setup the peer address field */
530 connection
->m_peer
= GAddress_new();
531 if (!connection
->m_peer
)
534 m_error
= wxSOCKET_MEMERR
;
537 err
= _GAddress_translate_from(connection
->m_peer
, (sockaddr
*)&from
, fromlen
);
538 if (err
!= wxSOCKET_NOERROR
)
540 GAddress_destroy(connection
->m_peer
);
546 ioctlsocket(connection
->m_fd
, FIONBIO
, (u_long FAR
*) &arg
);
547 wxSocketManager
::Get()->Install_Callback(connection
);
552 wxSocketError wxSocketImplMSW
::DoHandleConnect(int ret
)
555 if (ret
== SOCKET_ERROR
)
557 int err
= WSAGetLastError();
559 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
560 * is in blocking mode, we select() for the specified timeout
561 * checking for writability to see if the connection request
564 if ((err
== WSAEWOULDBLOCK
) && (!m_non_blocking
))
566 err
= Connect_Timeout();
568 if (err
!= wxSOCKET_NOERROR
)
571 /* m_error is set in Connect_Timeout */
574 return (wxSocketError
) err
;
577 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
578 * is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
579 * (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
580 * this way if the connection completes, a wxSOCKET_CONNECTION
581 * event will be generated, if enabled.
583 if ((err
== WSAEWOULDBLOCK
) && (m_non_blocking
))
585 m_establishing
= true;
586 m_error
= wxSOCKET_WOULDBLOCK
;
587 return wxSOCKET_WOULDBLOCK
;
590 /* If connect failed with an error other than EWOULDBLOCK,
591 * then the call to Connect() has failed.
594 m_error
= wxSOCKET_IOERR
;
595 return wxSOCKET_IOERR
;
598 return wxSOCKET_NOERROR
;
603 /* Like recv(), send(), ... */
604 int wxSocketImplMSW
::Read(void *buffer
, int size
)
608 /* Reenable INPUT events */
609 m_detected
&= ~wxSOCKET_INPUT_FLAG
;
611 if (m_fd
== INVALID_SOCKET
|| m_server
)
613 m_error
= wxSOCKET_INVSOCK
;
617 /* If the socket is blocking, wait for data (with a timeout) */
618 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
620 m_error
= wxSOCKET_TIMEDOUT
;
626 ret
= Recv_Stream(buffer
, size
);
628 ret
= Recv_Dgram(buffer
, size
);
630 if (ret
== SOCKET_ERROR
)
632 if (WSAGetLastError() != WSAEWOULDBLOCK
)
633 m_error
= wxSOCKET_IOERR
;
635 m_error
= wxSOCKET_WOULDBLOCK
;
642 int wxSocketImplMSW
::Write(const void *buffer
, int size
)
646 if (m_fd
== INVALID_SOCKET
|| m_server
)
648 m_error
= wxSOCKET_INVSOCK
;
652 /* If the socket is blocking, wait for writability (with a timeout) */
653 if (Output_Timeout() == wxSOCKET_TIMEDOUT
)
658 ret
= Send_Stream(buffer
, size
);
660 ret
= Send_Dgram(buffer
, size
);
662 if (ret
== SOCKET_ERROR
)
664 if (WSAGetLastError() != WSAEWOULDBLOCK
)
665 m_error
= wxSOCKET_IOERR
;
667 m_error
= wxSOCKET_WOULDBLOCK
;
669 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
670 * does). Once the first OUTPUT event is received, users can assume
671 * that the socket is writable until a read operation fails. Only then
672 * will further OUTPUT events be posted.
674 m_detected
&= ~wxSOCKET_OUTPUT_FLAG
;
684 * For blocking sockets, wait until data is available or
685 * until timeout ellapses.
687 wxSocketError wxSocketImplMSW
::Input_Timeout()
694 FD_SET(m_fd
, &readfds
);
695 if (select(0, &readfds
, NULL
, NULL
, &m_timeout
) == 0)
697 m_error
= wxSOCKET_TIMEDOUT
;
698 return wxSOCKET_TIMEDOUT
;
701 return wxSOCKET_NOERROR
;
705 * For blocking sockets, wait until data can be sent without
706 * blocking or until timeout ellapses.
708 wxSocketError wxSocketImplMSW
::Output_Timeout()
715 FD_SET(m_fd
, &writefds
);
716 if (select(0, NULL
, &writefds
, NULL
, &m_timeout
) == 0)
718 m_error
= wxSOCKET_TIMEDOUT
;
719 return wxSOCKET_TIMEDOUT
;
722 return wxSOCKET_NOERROR
;
726 * For blocking sockets, wait until the connection is
727 * established or fails, or until timeout ellapses.
729 wxSocketError wxSocketImplMSW
::Connect_Timeout()
736 FD_SET(m_fd
, &writefds
);
737 FD_SET(m_fd
, &exceptfds
);
738 if (select(0, NULL
, &writefds
, &exceptfds
, &m_timeout
) == 0)
740 m_error
= wxSOCKET_TIMEDOUT
;
741 return wxSOCKET_TIMEDOUT
;
743 if (!FD_ISSET(m_fd
, &writefds
))
745 m_error
= wxSOCKET_IOERR
;
746 return wxSOCKET_IOERR
;
749 return wxSOCKET_NOERROR
;
752 int wxSocketImplMSW
::Recv_Stream(void *buffer
, int size
)
754 return recv(m_fd
, static_cast<char *>(buffer
), size
, 0);
757 int wxSocketImplMSW
::Recv_Dgram(void *buffer
, int size
)
760 WX_SOCKLEN_T fromlen
= sizeof(from
);
764 ret
= recvfrom(m_fd
, static_cast<char *>(buffer
),
765 size
, 0, &from
, &fromlen
);
767 if (ret
== SOCKET_ERROR
)
770 /* Translate a system address into a wxSocketImpl address */
773 m_peer
= GAddress_new();
776 m_error
= wxSOCKET_MEMERR
;
780 err
= _GAddress_translate_from(m_peer
, (sockaddr
*)&from
, fromlen
);
781 if (err
!= wxSOCKET_NOERROR
)
783 GAddress_destroy(m_peer
);
792 int wxSocketImplMSW
::Send_Stream(const void *buffer
, int size
)
794 return send(m_fd
, static_cast<const char *>(buffer
), size
, 0);
797 int wxSocketImplMSW
::Send_Dgram(const void *buffer
, int size
)
799 struct sockaddr
*addr
;
805 m_error
= wxSOCKET_INVADDR
;
809 err
= _GAddress_translate_to(m_peer
, &addr
, &len
);
810 if (err
!= wxSOCKET_NOERROR
)
816 ret
= sendto(m_fd
, static_cast<const char *>(buffer
), size
, 0, addr
, len
);
818 /* Frees memory allocated by _GAddress_translate_to */
825 * -------------------------------------------------------------------------
827 * -------------------------------------------------------------------------
830 /* CHECK_ADDRESS verifies that the current address family is either
831 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
832 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
833 * an appropiate error code.
835 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
837 #define CHECK_ADDRESS(address, family) \
839 if (address->m_family == wxSOCKET_NOFAMILY) \
840 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
841 return address->m_error; \
842 if (address->m_family != wxSOCKET_##family) \
844 address->m_error = wxSOCKET_INVADDR; \
845 return wxSOCKET_INVADDR; \
849 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
851 if (address->m_family == wxSOCKET_NOFAMILY) \
852 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
854 if (address->m_family != wxSOCKET_##family) \
856 address->m_error = wxSOCKET_INVADDR; \
862 GAddress
*GAddress_new()
866 if ((address
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
869 address
->m_family
= wxSOCKET_NOFAMILY
;
870 address
->m_addr
= NULL
;
876 GAddress
*GAddress_copy(GAddress
*address
)
880 if ((addr2
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
883 memcpy(addr2
, address
, sizeof(GAddress
));
887 addr2
->m_addr
= (struct sockaddr
*) malloc(addr2
->m_len
);
888 if (addr2
->m_addr
== NULL
)
893 memcpy(addr2
->m_addr
, address
->m_addr
, addr2
->m_len
);
899 void GAddress_destroy(GAddress
*address
)
902 free(address
->m_addr
);
907 void GAddress_SetFamily(GAddress
*address
, GAddressType type
)
909 address
->m_family
= type
;
912 GAddressType
GAddress_GetFamily(GAddress
*address
)
914 return address
->m_family
;
917 wxSocketError
_GAddress_translate_from(GAddress
*address
,
918 struct sockaddr
*addr
, int len
)
920 address
->m_realfamily
= addr
->sa_family
;
921 switch (addr
->sa_family
)
924 address
->m_family
= wxSOCKET_INET
;
927 address
->m_family
= wxSOCKET_UNIX
;
931 address
->m_family
= wxSOCKET_INET6
;
936 address
->m_error
= wxSOCKET_INVOP
;
937 return wxSOCKET_INVOP
;
942 free(address
->m_addr
);
944 address
->m_len
= len
;
945 address
->m_addr
= (struct sockaddr
*) malloc(len
);
947 if (address
->m_addr
== NULL
)
949 address
->m_error
= wxSOCKET_MEMERR
;
950 return wxSOCKET_MEMERR
;
952 memcpy(address
->m_addr
, addr
, len
);
954 return wxSOCKET_NOERROR
;
957 wxSocketError
_GAddress_translate_to(GAddress
*address
,
958 struct sockaddr
**addr
, int *len
)
960 if (!address
->m_addr
)
962 address
->m_error
= wxSOCKET_INVADDR
;
963 return wxSOCKET_INVADDR
;
966 *len
= address
->m_len
;
967 *addr
= (struct sockaddr
*) malloc(address
->m_len
);
970 address
->m_error
= wxSOCKET_MEMERR
;
971 return wxSOCKET_MEMERR
;
974 memcpy(*addr
, address
->m_addr
, address
->m_len
);
975 return wxSOCKET_NOERROR
;
979 * -------------------------------------------------------------------------
980 * Internet address family
981 * -------------------------------------------------------------------------
984 wxSocketError
_GAddress_Init_INET(GAddress
*address
)
986 address
->m_len
= sizeof(struct sockaddr_in
);
987 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
988 if (address
->m_addr
== NULL
)
990 address
->m_error
= wxSOCKET_MEMERR
;
991 return wxSOCKET_MEMERR
;
994 address
->m_family
= wxSOCKET_INET
;
995 address
->m_realfamily
= AF_INET
;
996 ((struct sockaddr_in
*)address
->m_addr
)->sin_family
= AF_INET
;
997 ((struct sockaddr_in
*)address
->m_addr
)->sin_addr
.s_addr
= INADDR_ANY
;
999 return wxSOCKET_NOERROR
;
1002 wxSocketError
GAddress_INET_SetHostName(GAddress
*address
, const char *hostname
)
1005 struct in_addr
*addr
;
1007 CHECK_ADDRESS(address
, INET
);
1009 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1011 addr
->s_addr
= inet_addr(hostname
);
1013 /* If it is a numeric host name, convert it now */
1014 if (addr
->s_addr
== INADDR_NONE
)
1016 struct in_addr
*array_addr
;
1018 /* It is a real name, we solve it */
1019 if ((he
= gethostbyname(hostname
)) == NULL
)
1021 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
1022 address
->m_error
= wxSOCKET_NOHOST
;
1023 return wxSOCKET_NOHOST
;
1025 array_addr
= (struct in_addr
*) *(he
->h_addr_list
);
1026 addr
->s_addr
= array_addr
[0].s_addr
;
1028 return wxSOCKET_NOERROR
;
1031 wxSocketError
GAddress_INET_SetBroadcastAddress(GAddress
*address
)
1033 return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
);
1036 wxSocketError
GAddress_INET_SetAnyAddress(GAddress
*address
)
1038 return GAddress_INET_SetHostAddress(address
, INADDR_ANY
);
1041 wxSocketError
GAddress_INET_SetHostAddress(GAddress
*address
,
1042 unsigned long hostaddr
)
1044 struct in_addr
*addr
;
1046 CHECK_ADDRESS(address
, INET
);
1048 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1049 addr
->s_addr
= htonl(hostaddr
);
1051 return wxSOCKET_NOERROR
;
1054 wxSocketError
GAddress_INET_SetPortName(GAddress
*address
, const char *port
,
1055 const char *protocol
)
1058 struct sockaddr_in
*addr
;
1060 CHECK_ADDRESS(address
, INET
);
1064 address
->m_error
= wxSOCKET_INVPORT
;
1065 return wxSOCKET_INVPORT
;
1068 se
= getservbyname(port
, protocol
);
1071 if (isdigit(port
[0]))
1075 port_int
= atoi(port
);
1076 addr
= (struct sockaddr_in
*)address
->m_addr
;
1077 addr
->sin_port
= htons((u_short
) port_int
);
1078 return wxSOCKET_NOERROR
;
1081 address
->m_error
= wxSOCKET_INVPORT
;
1082 return wxSOCKET_INVPORT
;
1085 addr
= (struct sockaddr_in
*)address
->m_addr
;
1086 addr
->sin_port
= se
->s_port
;
1088 return wxSOCKET_NOERROR
;
1091 wxSocketError
GAddress_INET_SetPort(GAddress
*address
, unsigned short port
)
1093 struct sockaddr_in
*addr
;
1095 CHECK_ADDRESS(address
, INET
);
1097 addr
= (struct sockaddr_in
*)address
->m_addr
;
1098 addr
->sin_port
= htons(port
);
1100 return wxSOCKET_NOERROR
;
1103 wxSocketError
GAddress_INET_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1107 struct sockaddr_in
*addr
;
1109 CHECK_ADDRESS(address
, INET
);
1111 addr
= (struct sockaddr_in
*)address
->m_addr
;
1112 addr_buf
= (char *)&(addr
->sin_addr
);
1114 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin_addr
), AF_INET
);
1117 address
->m_error
= wxSOCKET_NOHOST
;
1118 return wxSOCKET_NOHOST
;
1121 strncpy(hostname
, he
->h_name
, sbuf
);
1123 return wxSOCKET_NOERROR
;
1126 unsigned long GAddress_INET_GetHostAddress(GAddress
*address
)
1128 struct sockaddr_in
*addr
;
1130 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1132 addr
= (struct sockaddr_in
*)address
->m_addr
;
1134 return ntohl(addr
->sin_addr
.s_addr
);
1137 unsigned short GAddress_INET_GetPort(GAddress
*address
)
1139 struct sockaddr_in
*addr
;
1141 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1143 addr
= (struct sockaddr_in
*)address
->m_addr
;
1144 return ntohs(addr
->sin_port
);
1150 * -------------------------------------------------------------------------
1151 * Internet IPv6 address family
1152 * -------------------------------------------------------------------------
1154 #include "ws2tcpip.h"
1157 #pragma comment(lib,"ws2_32")
1158 #endif // __VISUALC__
1160 wxSocketError
_GAddress_Init_INET6(GAddress
*address
)
1162 struct in6_addr any_address
= IN6ADDR_ANY_INIT
;
1163 address
->m_len
= sizeof(struct sockaddr_in6
);
1164 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
1165 if (address
->m_addr
== NULL
)
1167 address
->m_error
= wxSOCKET_MEMERR
;
1168 return wxSOCKET_MEMERR
;
1170 memset(address
->m_addr
,0,address
->m_len
);
1172 address
->m_family
= wxSOCKET_INET6
;
1173 address
->m_realfamily
= AF_INET6
;
1174 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_family
= AF_INET6
;
1175 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= any_address
;
1177 return wxSOCKET_NOERROR
;
1180 wxSocketError
GAddress_INET6_SetHostName(GAddress
*address
, const char *hostname
)
1182 CHECK_ADDRESS(address
, INET6
);
1185 memset( & hints
, 0, sizeof( hints
) );
1186 hints
.ai_family
= AF_INET6
;
1187 addrinfo
* info
= 0;
1188 if ( getaddrinfo( hostname
, "0", & hints
, & info
) || ! info
)
1190 address
->m_error
= wxSOCKET_NOHOST
;
1191 return wxSOCKET_NOHOST
;
1194 memcpy( address
->m_addr
, info
->ai_addr
, info
->ai_addrlen
);
1195 freeaddrinfo( info
);
1196 return wxSOCKET_NOERROR
;
1199 wxSocketError
GAddress_INET6_SetAnyAddress(GAddress
*address
)
1201 CHECK_ADDRESS(address
, INET6
);
1203 struct in6_addr addr
;
1204 memset( & addr
, 0, sizeof( addr
) );
1205 return GAddress_INET6_SetHostAddress(address
, addr
);
1207 wxSocketError
GAddress_INET6_SetHostAddress(GAddress
*address
,
1208 struct in6_addr hostaddr
)
1210 CHECK_ADDRESS(address
, INET6
);
1212 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= hostaddr
;
1214 return wxSOCKET_NOERROR
;
1217 wxSocketError
GAddress_INET6_SetPortName(GAddress
*address
, const char *port
,
1218 const char *protocol
)
1221 struct sockaddr_in6
*addr
;
1223 CHECK_ADDRESS(address
, INET6
);
1227 address
->m_error
= wxSOCKET_INVPORT
;
1228 return wxSOCKET_INVPORT
;
1231 se
= getservbyname(port
, protocol
);
1234 if (isdigit((unsigned char) port
[0]))
1238 port_int
= atoi(port
);
1239 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1240 addr
->sin6_port
= htons((u_short
) port_int
);
1241 return wxSOCKET_NOERROR
;
1244 address
->m_error
= wxSOCKET_INVPORT
;
1245 return wxSOCKET_INVPORT
;
1248 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1249 addr
->sin6_port
= se
->s_port
;
1251 return wxSOCKET_NOERROR
;
1254 wxSocketError
GAddress_INET6_SetPort(GAddress
*address
, unsigned short port
)
1256 struct sockaddr_in6
*addr
;
1258 CHECK_ADDRESS(address
, INET6
);
1260 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1261 addr
->sin6_port
= htons(port
);
1263 return wxSOCKET_NOERROR
;
1266 wxSocketError
GAddress_INET6_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1270 struct sockaddr_in6
*addr
;
1272 CHECK_ADDRESS(address
, INET6
);
1274 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1275 addr_buf
= (char *)&(addr
->sin6_addr
);
1277 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin6_addr
), AF_INET6
);
1280 address
->m_error
= wxSOCKET_NOHOST
;
1281 return wxSOCKET_NOHOST
;
1284 strncpy(hostname
, he
->h_name
, sbuf
);
1286 return wxSOCKET_NOERROR
;
1289 wxSocketError
GAddress_INET6_GetHostAddress(GAddress
*address
,struct in6_addr
*hostaddr
)
1291 CHECK_ADDRESS_RETVAL(address
, INET6
, wxSOCKET_INVADDR
);
1292 *hostaddr
= ( (struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
;
1293 return wxSOCKET_NOERROR
;
1296 unsigned short GAddress_INET6_GetPort(GAddress
*address
)
1298 CHECK_ADDRESS_RETVAL(address
, INET6
, 0);
1300 return ntohs( ((struct sockaddr_in6
*)address
->m_addr
)->sin6_port
);
1303 #endif // wxUSE_IPV6
1306 * -------------------------------------------------------------------------
1307 * Unix address family
1308 * -------------------------------------------------------------------------
1311 wxSocketError
_GAddress_Init_UNIX(GAddress
*address
)
1313 address
->m_error
= wxSOCKET_INVADDR
;
1314 return wxSOCKET_INVADDR
;
1317 wxSocketError
GAddress_UNIX_SetPath(GAddress
*address
, const char *WXUNUSED(path
))
1319 address
->m_error
= wxSOCKET_INVADDR
;
1320 return wxSOCKET_INVADDR
;
1323 wxSocketError
GAddress_UNIX_GetPath(GAddress
*address
, char *WXUNUSED(path
), size_t WXUNUSED(sbuf
))
1325 address
->m_error
= wxSOCKET_INVADDR
;
1326 return wxSOCKET_INVADDR
;
1329 #endif // wxUSE_SOCKETS