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"
34 extern "C" WXDLLIMPEXP_BASE HINSTANCE
wxGetInstance();
35 #define INSTANCE wxGetInstance()
39 #if defined(__CYGWIN__)
40 //CYGWIN gives annoying warning about runtime stuff if we don't do this
41 # define USE_SYS_TYPES_FD_SET
42 # include <sys/types.h>
47 * As WSAAsyncSelect is not present on WinCE, it now uses WSACreateEvent,
48 * WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents. When
49 * enabling eventhandling for a socket a new thread it created that keeps track
50 * of the events and posts a messageto the hidden window to use the standard
53 #include "wx/msw/wince/net.h"
54 #include "wx/hashmap.h"
55 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash
,wxIntegerEqual
,SocketHash
);
58 #define isdigit(x) (x > 47 && x < 58)
60 #include "wx/msw/wince/net.h"
65 # pragma warning(default:4115) /* named type definition in parentheses */
68 #define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
70 /* implemented in utils.cpp */
71 extern "C" WXDLLIMPEXP_BASE HWND
72 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
);
74 /* Maximum number of different wxSocket objects at a given time.
75 * This value can be modified at will, but it CANNOT be greater
76 * than (0x7FFF - WM_USER + 1)
78 #define MAXSOCKETS 1024
80 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
81 #error "MAXSOCKETS is too big!"
85 typedef int (PASCAL
*WSAAsyncSelectFunc
)(SOCKET
,HWND
,u_int
,long);
87 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
89 typedef struct _WSANETWORKEVENTS
{
92 } WSANETWORKEVENTS
, FAR
* LPWSANETWORKEVENTS
;
93 typedef HANDLE (PASCAL
*WSACreateEventFunc
)();
94 typedef int (PASCAL
*WSAEventSelectFunc
)(SOCKET
,HANDLE
,long);
95 typedef int (PASCAL
*WSAWaitForMultipleEventsFunc
)(long,HANDLE
,BOOL
,long,BOOL
);
96 typedef int (PASCAL
*WSAEnumNetworkEventsFunc
)(SOCKET
,HANDLE
,LPWSANETWORKEVENTS
);
99 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND
, UINT
, WPARAM
, LPARAM
);
101 /* Global variables */
104 static CRITICAL_SECTION critical
;
105 static wxSocketImplMSW
*socketList
[MAXSOCKETS
];
106 static int firstAvailable
;
109 static WSAAsyncSelectFunc gs_WSAAsyncSelect
= NULL
;
111 static SocketHash socketHash
;
112 static unsigned int currSocket
;
113 HANDLE hThread
[MAXSOCKETS
];
114 static WSACreateEventFunc gs_WSACreateEvent
= NULL
;
115 static WSAEventSelectFunc gs_WSAEventSelect
= NULL
;
116 static WSAWaitForMultipleEventsFunc gs_WSAWaitForMultipleEvents
= NULL
;
117 static WSAEnumNetworkEventsFunc gs_WSAEnumNetworkEvents
= NULL
;
118 /* This structure will be used to pass data on to the thread that handles socket events.
120 typedef struct thread_data
{
122 unsigned long msgnumber
;
124 unsigned long lEvent
;
128 static HMODULE gs_wsock32dll
= 0;
132 /* This thread handles socket events on WinCE using WSAEventSelect() as WSAAsyncSelect is not supported.
133 * When an event occures for the socket, it is checked what kind of event happend and the correct message gets posted
134 * so that the hidden window can handle it as it would in other MSW builds.
136 DWORD WINAPI
SocketThread(LPVOID data
)
138 WSANETWORKEVENTS NetworkEvents
;
139 thread_data
* d
= (thread_data
*)data
;
141 HANDLE NetworkEvent
= gs_WSACreateEvent();
142 gs_WSAEventSelect(d
->fd
, NetworkEvent
, d
->lEvent
);
144 while(socketHash
[d
->fd
] == true)
146 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent
, FALSE
,INFINITE
, FALSE
)) == WAIT_FAILED
)
148 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
151 if (gs_WSAEnumNetworkEvents(d
->fd
,NetworkEvent
, &NetworkEvents
) == SOCKET_ERROR
)
153 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
157 long flags
= NetworkEvents
.lNetworkEvents
;
159 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_READ
);
160 if (flags
& FD_WRITE
)
161 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_WRITE
);
163 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_OOB
);
164 if (flags
& FD_ACCEPT
)
165 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_ACCEPT
);
166 if (flags
& FD_CONNECT
)
167 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CONNECT
);
168 if (flags
& FD_CLOSE
)
169 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CLOSE
);
172 gs_WSAEventSelect(d
->fd
, NetworkEvent
, 0);
178 // ----------------------------------------------------------------------------
179 // MSW implementation of wxSocketManager
180 // ----------------------------------------------------------------------------
182 class wxSocketMSWManager
: public wxSocketManager
185 virtual bool OnInit();
186 virtual void OnExit();
188 virtual wxSocketImpl
*CreateSocket(wxSocketBase
& wxsocket
)
190 return new wxSocketImplMSW(wxsocket
);
192 virtual void Install_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
193 virtual void Uninstall_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
196 /* Global initializers */
198 bool wxSocketMSWManager::OnInit()
200 static LPCTSTR pclassname
= NULL
;
203 /* Create internal window for event notifications */
204 hWin
= wxCreateHiddenWindow(&pclassname
, CLASSNAME
, wxSocket_Internal_WinProc
);
208 /* Initialize socket list */
209 InitializeCriticalSection(&critical
);
211 for (i
= 0; i
< MAXSOCKETS
; i
++)
213 socketList
[i
] = NULL
;
217 /* Load WSAAsyncSelect from wsock32.dll (we don't link against it
218 statically to avoid dependency on wsock32.dll for apps that don't use
221 gs_wsock32dll
= LoadLibrary(wxT("wsock32.dll"));
224 gs_WSAAsyncSelect
=(WSAAsyncSelectFunc
)GetProcAddress(gs_wsock32dll
,
226 if (!gs_WSAAsyncSelect
)
229 /* On WinCE we load ws2.dll which will provide the needed functions.
231 gs_wsock32dll
= LoadLibrary(wxT("ws2.dll"));
234 gs_WSAEventSelect
=(WSAEventSelectFunc
)GetProcAddress(gs_wsock32dll
,
235 wxT("WSAEventSelect"));
236 if (!gs_WSAEventSelect
)
239 gs_WSACreateEvent
=(WSACreateEventFunc
)GetProcAddress(gs_wsock32dll
,
240 wxT("WSACreateEvent"));
241 if (!gs_WSACreateEvent
)
244 gs_WSAWaitForMultipleEvents
=(WSAWaitForMultipleEventsFunc
)GetProcAddress(gs_wsock32dll
,
245 wxT("WSAWaitForMultipleEvents"));
246 if (!gs_WSAWaitForMultipleEvents
)
249 gs_WSAEnumNetworkEvents
=(WSAEnumNetworkEventsFunc
)GetProcAddress(gs_wsock32dll
,
250 wxT("WSAEnumNetworkEvents"));
251 if (!gs_WSAEnumNetworkEvents
)
257 // finally initialize WinSock
259 return WSAStartup((1 << 8) | 1, &wsaData
) == 0;
262 void wxSocketMSWManager::OnExit()
265 /* Delete the threads here */
266 for(unsigned int i
=0; i
< currSocket
; i
++)
267 CloseHandle(hThread
[i
]);
269 /* Destroy internal window */
271 UnregisterClass(CLASSNAME
, INSTANCE
);
273 /* Unlock wsock32.dll */
276 FreeLibrary(gs_wsock32dll
);
280 /* Delete critical section */
281 DeleteCriticalSection(&critical
);
286 /* Per-socket GUI initialization / cleanup */
288 wxSocketImplMSW::wxSocketImplMSW(wxSocketBase
& wxsocket
)
289 : wxSocketImpl(wxsocket
)
291 /* Allocate a new message number for this socket */
292 EnterCriticalSection(&critical
);
294 int i
= firstAvailable
;
295 while (socketList
[i
] != NULL
)
297 i
= (i
+ 1) % MAXSOCKETS
;
299 if (i
== firstAvailable
) /* abort! */
301 LeaveCriticalSection(&critical
);
302 m_msgnumber
= 0; // invalid
306 socketList
[i
] = this;
307 firstAvailable
= (i
+ 1) % MAXSOCKETS
;
308 m_msgnumber
= (i
+ WM_USER
);
310 LeaveCriticalSection(&critical
);
313 wxSocketImplMSW::~wxSocketImplMSW()
315 /* Remove the socket from the list */
316 EnterCriticalSection(&critical
);
320 // we need to remove any pending messages for this socket to avoid having
321 // them sent to a new socket which could reuse the same message number as
322 // soon as we destroy this one
324 while ( ::PeekMessage(&msg
, hWin
, m_msgnumber
, m_msgnumber
, PM_REMOVE
) )
327 socketList
[m_msgnumber
- WM_USER
] = NULL
;
329 //else: the socket has never been created successfully
331 LeaveCriticalSection(&critical
);
334 /* Windows proc for asynchronous event handling */
336 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND hWnd
,
341 wxSocketImplMSW
*socket
;
342 wxSocketNotify event
;
344 if (uMsg
>= WM_USER
&& uMsg
<= (WM_USER
+ MAXSOCKETS
- 1))
346 EnterCriticalSection(&critical
);
347 socket
= socketList
[(uMsg
- WM_USER
)];
348 event
= (wxSocketNotify
) -1;
350 /* Check that the socket still exists (it has not been
351 * destroyed) and for safety, check that the m_fd field
352 * is what we expect it to be.
354 if ((socket
!= NULL
) && ((WPARAM
)socket
->m_fd
== wParam
))
356 switch WSAGETSELECTEVENT(lParam
)
358 case FD_READ
: event
= wxSOCKET_INPUT
; break;
359 case FD_WRITE
: event
= wxSOCKET_OUTPUT
; break;
360 case FD_ACCEPT
: event
= wxSOCKET_CONNECTION
; break;
363 if (WSAGETSELECTERROR(lParam
) != 0)
364 event
= wxSOCKET_LOST
;
366 event
= wxSOCKET_CONNECTION
;
369 case FD_CLOSE
: event
= wxSOCKET_LOST
; break;
374 if (event
== wxSOCKET_LOST
)
375 socket
->m_detected
= wxSOCKET_LOST_FLAG
;
377 socket
->m_detected
|= (1 << event
);
381 LeaveCriticalSection(&critical
);
384 socket
->NotifyOnStateChange(event
);
389 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
393 * Enable all event notifications; we need to be notified of all
394 * events for internal processing, but we will only notify users
395 * when an appropriate callback function has been installed.
397 void wxSocketMSWManager::Install_Callback(wxSocketImpl
*socket_
,
398 wxSocketNotify
WXUNUSED(event
))
400 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
402 if (socket
->m_fd
!= INVALID_SOCKET
)
404 /* We could probably just subscribe to all events regardless
405 * of the socket type, but MS recommends to do it this way.
407 long lEvent
= socket
->m_server
?
408 FD_ACCEPT
: (FD_READ
| FD_WRITE
| FD_CONNECT
| FD_CLOSE
);
410 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, lEvent
);
413 * WinCE creates a thread for socket event handling.
414 * All needed parameters get passed through the thread_data structure.
417 thread_data
* d
= new thread_data
;
420 d
->msgnumber
= socket
->m_msgnumber
;
421 d
->fd
= socket
->m_fd
;
422 socketHash
[socket
->m_fd
] = true;
423 hThread
[currSocket
++] = CreateThread(NULL
, 0, &SocketThread
,(LPVOID
)d
, 0, NULL
);
429 * Disable event notifications (used when shutting down the socket)
431 void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl
*socket_
,
432 wxSocketNotify
WXUNUSED(event
))
434 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
436 if (socket
->m_fd
!= INVALID_SOCKET
)
439 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, 0);
442 socketHash
[socket
->m_fd
] = false;
447 // set the wxBase variable to point to our wxSocketManager implementation
449 // see comments in wx/apptrait.h for the explanation of why do we do it
451 static struct ManagerSetter
455 static wxSocketMSWManager s_manager
;
456 wxAppTraits::SetDefaultSocketManager(&s_manager
);
460 // ============================================================================
461 // wxSocketImpl implementation
462 // ============================================================================
465 wxSocketImpl
*wxSocketImpl::Create(wxSocketBase
& wxsocket
)
467 return new wxSocketImplMSW(wxsocket
);
470 void wxSocketImplMSW::DoClose()
472 wxSocketManager::Get()->
473 Uninstall_Callback(this, wxSOCKET_MAX_EVENT
/* unused anyhow */);
479 * Waits for an incoming client connection. Returns a pointer to
480 * a wxSocketImpl object, or NULL if there was an error, in which case
481 * the last error field will be updated for the calling wxSocketImpl.
483 * Error codes (set in the calling wxSocketImpl)
484 * wxSOCKET_INVSOCK - the socket is not valid or not a server.
485 * wxSOCKET_TIMEDOUT - timeout, no incoming connections.
486 * wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
487 * wxSOCKET_MEMERR - couldn't allocate memory.
488 * wxSOCKET_IOERR - low-level error.
490 wxSocketImpl
*wxSocketImplMSW::WaitConnection(wxSocketBase
& wxsocket
)
492 wxSocketImpl
*connection
;
494 WX_SOCKLEN_T fromlen
= sizeof(from
);
498 /* Reenable CONNECTION events */
499 m_detected
&= ~wxSOCKET_CONNECTION_FLAG
;
501 /* If the socket has already been created, we exit immediately */
502 if (m_fd
== INVALID_SOCKET
|| !m_server
)
504 m_error
= wxSOCKET_INVSOCK
;
508 /* Create a wxSocketImpl object for the new connection */
509 connection
= wxSocketImplMSW::Create(wxsocket
);
513 m_error
= wxSOCKET_MEMERR
;
517 /* Wait for a connection (with timeout) */
518 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
521 /* m_error set by Input_Timeout */
525 connection
->m_fd
= accept(m_fd
, (sockaddr
*)&from
, &fromlen
);
527 if (connection
->m_fd
== INVALID_SOCKET
)
529 if (WSAGetLastError() == WSAEWOULDBLOCK
)
530 m_error
= wxSOCKET_WOULDBLOCK
;
532 m_error
= wxSOCKET_IOERR
;
538 /* Initialize all fields */
539 connection
->m_server
= false;
540 connection
->m_stream
= true;
542 /* Setup the peer address field */
543 connection
->m_peer
= GAddress_new();
544 if (!connection
->m_peer
)
547 m_error
= wxSOCKET_MEMERR
;
550 err
= _GAddress_translate_from(connection
->m_peer
, (sockaddr
*)&from
, fromlen
);
551 if (err
!= wxSOCKET_NOERROR
)
553 GAddress_destroy(connection
->m_peer
);
559 ioctlsocket(connection
->m_fd
, FIONBIO
, (u_long FAR
*) &arg
);
560 wxSocketManager::Get()->Install_Callback(connection
);
565 wxSocketError
wxSocketImplMSW::DoHandleConnect(int ret
)
568 if (ret
== SOCKET_ERROR
)
570 int err
= WSAGetLastError();
572 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
573 * is in blocking mode, we select() for the specified timeout
574 * checking for writability to see if the connection request
577 if ((err
== WSAEWOULDBLOCK
) && (!m_non_blocking
))
579 err
= Connect_Timeout();
581 if (err
!= wxSOCKET_NOERROR
)
584 /* m_error is set in Connect_Timeout */
587 return (wxSocketError
) err
;
590 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
591 * is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
592 * (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
593 * this way if the connection completes, a wxSOCKET_CONNECTION
594 * event will be generated, if enabled.
596 if ((err
== WSAEWOULDBLOCK
) && (m_non_blocking
))
598 m_establishing
= true;
599 m_error
= wxSOCKET_WOULDBLOCK
;
600 return wxSOCKET_WOULDBLOCK
;
603 /* If connect failed with an error other than EWOULDBLOCK,
604 * then the call to Connect() has failed.
607 m_error
= wxSOCKET_IOERR
;
608 return wxSOCKET_IOERR
;
611 return wxSOCKET_NOERROR
;
616 /* Like recv(), send(), ... */
617 int wxSocketImplMSW::Read(void *buffer
, int size
)
621 /* Reenable INPUT events */
622 m_detected
&= ~wxSOCKET_INPUT_FLAG
;
624 if (m_fd
== INVALID_SOCKET
|| m_server
)
626 m_error
= wxSOCKET_INVSOCK
;
630 /* If the socket is blocking, wait for data (with a timeout) */
631 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
633 m_error
= wxSOCKET_TIMEDOUT
;
639 ret
= Recv_Stream(buffer
, size
);
641 ret
= Recv_Dgram(buffer
, size
);
643 if (ret
== SOCKET_ERROR
)
645 if (WSAGetLastError() != WSAEWOULDBLOCK
)
646 m_error
= wxSOCKET_IOERR
;
648 m_error
= wxSOCKET_WOULDBLOCK
;
655 int wxSocketImplMSW::Write(const void *buffer
, int size
)
659 if (m_fd
== INVALID_SOCKET
|| m_server
)
661 m_error
= wxSOCKET_INVSOCK
;
665 /* If the socket is blocking, wait for writability (with a timeout) */
666 if (Output_Timeout() == wxSOCKET_TIMEDOUT
)
671 ret
= Send_Stream(buffer
, size
);
673 ret
= Send_Dgram(buffer
, size
);
675 if (ret
== SOCKET_ERROR
)
677 if (WSAGetLastError() != WSAEWOULDBLOCK
)
678 m_error
= wxSOCKET_IOERR
;
680 m_error
= wxSOCKET_WOULDBLOCK
;
682 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
683 * does). Once the first OUTPUT event is received, users can assume
684 * that the socket is writable until a read operation fails. Only then
685 * will further OUTPUT events be posted.
687 m_detected
&= ~wxSOCKET_OUTPUT_FLAG
;
697 * For blocking sockets, wait until data is available or
698 * until timeout ellapses.
700 wxSocketError
wxSocketImplMSW::Input_Timeout()
707 FD_SET(m_fd
, &readfds
);
708 if (select(0, &readfds
, NULL
, NULL
, &m_timeout
) == 0)
710 m_error
= wxSOCKET_TIMEDOUT
;
711 return wxSOCKET_TIMEDOUT
;
714 return wxSOCKET_NOERROR
;
718 * For blocking sockets, wait until data can be sent without
719 * blocking or until timeout ellapses.
721 wxSocketError
wxSocketImplMSW::Output_Timeout()
728 FD_SET(m_fd
, &writefds
);
729 if (select(0, NULL
, &writefds
, NULL
, &m_timeout
) == 0)
731 m_error
= wxSOCKET_TIMEDOUT
;
732 return wxSOCKET_TIMEDOUT
;
735 return wxSOCKET_NOERROR
;
739 * For blocking sockets, wait until the connection is
740 * established or fails, or until timeout ellapses.
742 wxSocketError
wxSocketImplMSW::Connect_Timeout()
749 FD_SET(m_fd
, &writefds
);
750 FD_SET(m_fd
, &exceptfds
);
751 if (select(0, NULL
, &writefds
, &exceptfds
, &m_timeout
) == 0)
753 m_error
= wxSOCKET_TIMEDOUT
;
754 return wxSOCKET_TIMEDOUT
;
756 if (!FD_ISSET(m_fd
, &writefds
))
758 m_error
= wxSOCKET_IOERR
;
759 return wxSOCKET_IOERR
;
762 return wxSOCKET_NOERROR
;
765 int wxSocketImplMSW::Recv_Stream(void *buffer
, int size
)
767 return recv(m_fd
, static_cast<char *>(buffer
), size
, 0);
770 int wxSocketImplMSW::Recv_Dgram(void *buffer
, int size
)
773 WX_SOCKLEN_T fromlen
= sizeof(from
);
777 ret
= recvfrom(m_fd
, static_cast<char *>(buffer
),
778 size
, 0, &from
, &fromlen
);
780 if (ret
== SOCKET_ERROR
)
783 /* Translate a system address into a wxSocketImpl address */
786 m_peer
= GAddress_new();
789 m_error
= wxSOCKET_MEMERR
;
793 err
= _GAddress_translate_from(m_peer
, (sockaddr
*)&from
, fromlen
);
794 if (err
!= wxSOCKET_NOERROR
)
796 GAddress_destroy(m_peer
);
805 int wxSocketImplMSW::Send_Stream(const void *buffer
, int size
)
807 return send(m_fd
, static_cast<const char *>(buffer
), size
, 0);
810 int wxSocketImplMSW::Send_Dgram(const void *buffer
, int size
)
812 struct sockaddr
*addr
;
818 m_error
= wxSOCKET_INVADDR
;
822 err
= _GAddress_translate_to(m_peer
, &addr
, &len
);
823 if (err
!= wxSOCKET_NOERROR
)
829 ret
= sendto(m_fd
, static_cast<const char *>(buffer
), size
, 0, addr
, len
);
831 /* Frees memory allocated by _GAddress_translate_to */
838 * -------------------------------------------------------------------------
840 * -------------------------------------------------------------------------
843 /* CHECK_ADDRESS verifies that the current address family is either
844 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
845 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
846 * an appropiate error code.
848 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
850 #define CHECK_ADDRESS(address, family) \
852 if (address->m_family == wxSOCKET_NOFAMILY) \
853 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
854 return address->m_error; \
855 if (address->m_family != wxSOCKET_##family) \
857 address->m_error = wxSOCKET_INVADDR; \
858 return wxSOCKET_INVADDR; \
862 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
864 if (address->m_family == wxSOCKET_NOFAMILY) \
865 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
867 if (address->m_family != wxSOCKET_##family) \
869 address->m_error = wxSOCKET_INVADDR; \
875 GAddress
*GAddress_new()
879 if ((address
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
882 address
->m_family
= wxSOCKET_NOFAMILY
;
883 address
->m_addr
= NULL
;
889 GAddress
*GAddress_copy(GAddress
*address
)
893 if ((addr2
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
896 memcpy(addr2
, address
, sizeof(GAddress
));
900 addr2
->m_addr
= (struct sockaddr
*) malloc(addr2
->m_len
);
901 if (addr2
->m_addr
== NULL
)
906 memcpy(addr2
->m_addr
, address
->m_addr
, addr2
->m_len
);
912 void GAddress_destroy(GAddress
*address
)
915 free(address
->m_addr
);
920 void GAddress_SetFamily(GAddress
*address
, GAddressType type
)
922 address
->m_family
= type
;
925 GAddressType
GAddress_GetFamily(GAddress
*address
)
927 return address
->m_family
;
930 wxSocketError
_GAddress_translate_from(GAddress
*address
,
931 struct sockaddr
*addr
, int len
)
933 address
->m_realfamily
= addr
->sa_family
;
934 switch (addr
->sa_family
)
937 address
->m_family
= wxSOCKET_INET
;
940 address
->m_family
= wxSOCKET_UNIX
;
944 address
->m_family
= wxSOCKET_INET6
;
949 address
->m_error
= wxSOCKET_INVOP
;
950 return wxSOCKET_INVOP
;
955 free(address
->m_addr
);
957 address
->m_len
= len
;
958 address
->m_addr
= (struct sockaddr
*) malloc(len
);
960 if (address
->m_addr
== NULL
)
962 address
->m_error
= wxSOCKET_MEMERR
;
963 return wxSOCKET_MEMERR
;
965 memcpy(address
->m_addr
, addr
, len
);
967 return wxSOCKET_NOERROR
;
970 wxSocketError
_GAddress_translate_to(GAddress
*address
,
971 struct sockaddr
**addr
, int *len
)
973 if (!address
->m_addr
)
975 address
->m_error
= wxSOCKET_INVADDR
;
976 return wxSOCKET_INVADDR
;
979 *len
= address
->m_len
;
980 *addr
= (struct sockaddr
*) malloc(address
->m_len
);
983 address
->m_error
= wxSOCKET_MEMERR
;
984 return wxSOCKET_MEMERR
;
987 memcpy(*addr
, address
->m_addr
, address
->m_len
);
988 return wxSOCKET_NOERROR
;
992 * -------------------------------------------------------------------------
993 * Internet address family
994 * -------------------------------------------------------------------------
997 wxSocketError
_GAddress_Init_INET(GAddress
*address
)
999 address
->m_len
= sizeof(struct sockaddr_in
);
1000 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
1001 if (address
->m_addr
== NULL
)
1003 address
->m_error
= wxSOCKET_MEMERR
;
1004 return wxSOCKET_MEMERR
;
1007 address
->m_family
= wxSOCKET_INET
;
1008 address
->m_realfamily
= AF_INET
;
1009 ((struct sockaddr_in
*)address
->m_addr
)->sin_family
= AF_INET
;
1010 ((struct sockaddr_in
*)address
->m_addr
)->sin_addr
.s_addr
= INADDR_ANY
;
1012 return wxSOCKET_NOERROR
;
1015 wxSocketError
GAddress_INET_SetHostName(GAddress
*address
, const char *hostname
)
1018 struct in_addr
*addr
;
1020 CHECK_ADDRESS(address
, INET
);
1022 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1024 addr
->s_addr
= inet_addr(hostname
);
1026 /* If it is a numeric host name, convert it now */
1027 if (addr
->s_addr
== INADDR_NONE
)
1029 struct in_addr
*array_addr
;
1031 /* It is a real name, we solve it */
1032 if ((he
= gethostbyname(hostname
)) == NULL
)
1034 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
1035 address
->m_error
= wxSOCKET_NOHOST
;
1036 return wxSOCKET_NOHOST
;
1038 array_addr
= (struct in_addr
*) *(he
->h_addr_list
);
1039 addr
->s_addr
= array_addr
[0].s_addr
;
1041 return wxSOCKET_NOERROR
;
1044 wxSocketError
GAddress_INET_SetBroadcastAddress(GAddress
*address
)
1046 return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
);
1049 wxSocketError
GAddress_INET_SetAnyAddress(GAddress
*address
)
1051 return GAddress_INET_SetHostAddress(address
, INADDR_ANY
);
1054 wxSocketError
GAddress_INET_SetHostAddress(GAddress
*address
,
1055 unsigned long hostaddr
)
1057 struct in_addr
*addr
;
1059 CHECK_ADDRESS(address
, INET
);
1061 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1062 addr
->s_addr
= htonl(hostaddr
);
1064 return wxSOCKET_NOERROR
;
1067 wxSocketError
GAddress_INET_SetPortName(GAddress
*address
, const char *port
,
1068 const char *protocol
)
1071 struct sockaddr_in
*addr
;
1073 CHECK_ADDRESS(address
, INET
);
1077 address
->m_error
= wxSOCKET_INVPORT
;
1078 return wxSOCKET_INVPORT
;
1081 se
= getservbyname(port
, protocol
);
1084 if (isdigit(port
[0]))
1088 port_int
= atoi(port
);
1089 addr
= (struct sockaddr_in
*)address
->m_addr
;
1090 addr
->sin_port
= htons((u_short
) port_int
);
1091 return wxSOCKET_NOERROR
;
1094 address
->m_error
= wxSOCKET_INVPORT
;
1095 return wxSOCKET_INVPORT
;
1098 addr
= (struct sockaddr_in
*)address
->m_addr
;
1099 addr
->sin_port
= se
->s_port
;
1101 return wxSOCKET_NOERROR
;
1104 wxSocketError
GAddress_INET_SetPort(GAddress
*address
, unsigned short port
)
1106 struct sockaddr_in
*addr
;
1108 CHECK_ADDRESS(address
, INET
);
1110 addr
= (struct sockaddr_in
*)address
->m_addr
;
1111 addr
->sin_port
= htons(port
);
1113 return wxSOCKET_NOERROR
;
1116 wxSocketError
GAddress_INET_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1120 struct sockaddr_in
*addr
;
1122 CHECK_ADDRESS(address
, INET
);
1124 addr
= (struct sockaddr_in
*)address
->m_addr
;
1125 addr_buf
= (char *)&(addr
->sin_addr
);
1127 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin_addr
), AF_INET
);
1130 address
->m_error
= wxSOCKET_NOHOST
;
1131 return wxSOCKET_NOHOST
;
1134 strncpy(hostname
, he
->h_name
, sbuf
);
1136 return wxSOCKET_NOERROR
;
1139 unsigned long GAddress_INET_GetHostAddress(GAddress
*address
)
1141 struct sockaddr_in
*addr
;
1143 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1145 addr
= (struct sockaddr_in
*)address
->m_addr
;
1147 return ntohl(addr
->sin_addr
.s_addr
);
1150 unsigned short GAddress_INET_GetPort(GAddress
*address
)
1152 struct sockaddr_in
*addr
;
1154 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1156 addr
= (struct sockaddr_in
*)address
->m_addr
;
1157 return ntohs(addr
->sin_port
);
1163 * -------------------------------------------------------------------------
1164 * Internet IPv6 address family
1165 * -------------------------------------------------------------------------
1167 #include "ws2tcpip.h"
1170 #pragma comment(lib,"ws2_32")
1171 #endif // __VISUALC__
1173 wxSocketError
_GAddress_Init_INET6(GAddress
*address
)
1175 struct in6_addr any_address
= IN6ADDR_ANY_INIT
;
1176 address
->m_len
= sizeof(struct sockaddr_in6
);
1177 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
1178 if (address
->m_addr
== NULL
)
1180 address
->m_error
= wxSOCKET_MEMERR
;
1181 return wxSOCKET_MEMERR
;
1183 memset(address
->m_addr
,0,address
->m_len
);
1185 address
->m_family
= wxSOCKET_INET6
;
1186 address
->m_realfamily
= AF_INET6
;
1187 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_family
= AF_INET6
;
1188 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= any_address
;
1190 return wxSOCKET_NOERROR
;
1193 wxSocketError
GAddress_INET6_SetHostName(GAddress
*address
, const char *hostname
)
1195 CHECK_ADDRESS(address
, INET6
);
1198 memset( & hints
, 0, sizeof( hints
) );
1199 hints
.ai_family
= AF_INET6
;
1200 addrinfo
* info
= 0;
1201 if ( getaddrinfo( hostname
, "0", & hints
, & info
) || ! info
)
1203 address
->m_error
= wxSOCKET_NOHOST
;
1204 return wxSOCKET_NOHOST
;
1207 memcpy( address
->m_addr
, info
->ai_addr
, info
->ai_addrlen
);
1208 freeaddrinfo( info
);
1209 return wxSOCKET_NOERROR
;
1212 wxSocketError
GAddress_INET6_SetAnyAddress(GAddress
*address
)
1214 CHECK_ADDRESS(address
, INET6
);
1216 struct in6_addr addr
;
1217 memset( & addr
, 0, sizeof( addr
) );
1218 return GAddress_INET6_SetHostAddress(address
, addr
);
1220 wxSocketError
GAddress_INET6_SetHostAddress(GAddress
*address
,
1221 struct in6_addr hostaddr
)
1223 CHECK_ADDRESS(address
, INET6
);
1225 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= hostaddr
;
1227 return wxSOCKET_NOERROR
;
1230 wxSocketError
GAddress_INET6_SetPortName(GAddress
*address
, const char *port
,
1231 const char *protocol
)
1234 struct sockaddr_in6
*addr
;
1236 CHECK_ADDRESS(address
, INET6
);
1240 address
->m_error
= wxSOCKET_INVPORT
;
1241 return wxSOCKET_INVPORT
;
1244 se
= getservbyname(port
, protocol
);
1247 if (isdigit((unsigned char) port
[0]))
1251 port_int
= atoi(port
);
1252 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1253 addr
->sin6_port
= htons((u_short
) port_int
);
1254 return wxSOCKET_NOERROR
;
1257 address
->m_error
= wxSOCKET_INVPORT
;
1258 return wxSOCKET_INVPORT
;
1261 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1262 addr
->sin6_port
= se
->s_port
;
1264 return wxSOCKET_NOERROR
;
1267 wxSocketError
GAddress_INET6_SetPort(GAddress
*address
, unsigned short port
)
1269 struct sockaddr_in6
*addr
;
1271 CHECK_ADDRESS(address
, INET6
);
1273 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1274 addr
->sin6_port
= htons(port
);
1276 return wxSOCKET_NOERROR
;
1279 wxSocketError
GAddress_INET6_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1283 struct sockaddr_in6
*addr
;
1285 CHECK_ADDRESS(address
, INET6
);
1287 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1288 addr_buf
= (char *)&(addr
->sin6_addr
);
1290 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin6_addr
), AF_INET6
);
1293 address
->m_error
= wxSOCKET_NOHOST
;
1294 return wxSOCKET_NOHOST
;
1297 strncpy(hostname
, he
->h_name
, sbuf
);
1299 return wxSOCKET_NOERROR
;
1302 wxSocketError
GAddress_INET6_GetHostAddress(GAddress
*address
,struct in6_addr
*hostaddr
)
1304 CHECK_ADDRESS_RETVAL(address
, INET6
, wxSOCKET_INVADDR
);
1305 *hostaddr
= ( (struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
;
1306 return wxSOCKET_NOERROR
;
1309 unsigned short GAddress_INET6_GetPort(GAddress
*address
)
1311 CHECK_ADDRESS_RETVAL(address
, INET6
, 0);
1313 return ntohs( ((struct sockaddr_in6
*)address
->m_addr
)->sin6_port
);
1316 #endif // wxUSE_IPV6
1319 * -------------------------------------------------------------------------
1320 * Unix address family
1321 * -------------------------------------------------------------------------
1324 wxSocketError
_GAddress_Init_UNIX(GAddress
*address
)
1326 address
->m_error
= wxSOCKET_INVADDR
;
1327 return wxSOCKET_INVADDR
;
1330 wxSocketError
GAddress_UNIX_SetPath(GAddress
*address
, const char *WXUNUSED(path
))
1332 address
->m_error
= wxSOCKET_INVADDR
;
1333 return wxSOCKET_INVADDR
;
1336 wxSocketError
GAddress_UNIX_GetPath(GAddress
*address
, char *WXUNUSED(path
), size_t WXUNUSED(sbuf
))
1338 address
->m_error
= wxSOCKET_INVADDR
;
1339 return wxSOCKET_INVADDR
;
1342 #endif // wxUSE_SOCKETS