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"
34 #include "wx/dynlib.h"
36 extern "C" WXDLLIMPEXP_BASE HINSTANCE
wxGetInstance();
37 #define INSTANCE wxGetInstance()
41 * As WSAAsyncSelect is not present on WinCE, it now uses WSACreateEvent,
42 * WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents. When
43 * enabling eventhandling for a socket a new thread it created that keeps track
44 * of the events and posts a messageto the hidden window to use the standard
47 #include "wx/msw/wince/net.h"
48 #include "wx/hashmap.h"
49 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash
,wxIntegerEqual
,SocketHash
);
52 #define isdigit(x) (x > 47 && x < 58)
54 #include "wx/msw/wince/net.h"
59 # pragma warning(default:4115) /* named type definition in parentheses */
62 #define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
64 /* implemented in utils.cpp */
65 extern "C" WXDLLIMPEXP_BASE HWND
66 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
);
68 /* Maximum number of different wxSocket objects at a given time.
69 * This value can be modified at will, but it CANNOT be greater
70 * than (0x7FFF - WM_USER + 1)
72 #define MAXSOCKETS 1024
74 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
75 #error "MAXSOCKETS is too big!"
79 typedef int (PASCAL
*WSAAsyncSelect_t
)(SOCKET
,HWND
,u_int
,long);
81 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
83 typedef struct _WSANETWORKEVENTS
{
86 } WSANETWORKEVENTS
, FAR
* LPWSANETWORKEVENTS
;
87 typedef HANDLE (PASCAL
*WSACreateEvent_t
)();
88 typedef int (PASCAL
*WSAEventSelect_t
)(SOCKET
,HANDLE
,long);
89 typedef int (PASCAL
*WSAWaitForMultipleEvents_t
)(long,HANDLE
,BOOL
,long,BOOL
);
90 typedef int (PASCAL
*WSAEnumNetworkEvents_t
)(SOCKET
,HANDLE
,LPWSANETWORKEVENTS
);
93 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND
, UINT
, WPARAM
, LPARAM
);
95 /* Global variables */
98 wxCRIT_SECT_DECLARE_MEMBER(gs_critical
);
99 static wxSocketImplMSW
*socketList
[MAXSOCKETS
];
100 static int firstAvailable
;
103 static WSAAsyncSelect_t gs_WSAAsyncSelect
= NULL
;
105 static SocketHash socketHash
;
106 static unsigned int currSocket
;
107 HANDLE hThread
[MAXSOCKETS
];
108 static WSACreateEvent_t gs_WSACreateEvent
= NULL
;
109 static WSAEventSelect_t gs_WSAEventSelect
= NULL
;
110 static WSAWaitForMultipleEvents_t gs_WSAWaitForMultipleEvents
= NULL
;
111 static WSAEnumNetworkEvents_t gs_WSAEnumNetworkEvents
= NULL
;
112 /* This structure will be used to pass data on to the thread that handles socket events.
114 typedef struct thread_data
{
116 unsigned long msgnumber
;
118 unsigned long lEvent
;
123 /* This thread handles socket events on WinCE using WSAEventSelect() as
124 * WSAAsyncSelect is not supported. When an event occurs for the socket, it is
125 * checked what kind of event happend and the correct message gets posted so
126 * that the hidden window can handle it as it would in other MSW builds.
128 DWORD WINAPI
SocketThread(LPVOID data
)
130 WSANETWORKEVENTS NetworkEvents
;
131 thread_data
* d
= (thread_data
*)data
;
133 HANDLE NetworkEvent
= gs_WSACreateEvent();
134 gs_WSAEventSelect(d
->fd
, NetworkEvent
, d
->lEvent
);
136 while(socketHash
[d
->fd
] == true)
138 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent
, FALSE
,INFINITE
, FALSE
)) == WAIT_FAILED
)
140 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
143 if (gs_WSAEnumNetworkEvents(d
->fd
,NetworkEvent
, &NetworkEvents
) == SOCKET_ERROR
)
145 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
149 long flags
= NetworkEvents
.lNetworkEvents
;
151 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_READ
);
152 if (flags
& FD_WRITE
)
153 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_WRITE
);
155 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_OOB
);
156 if (flags
& FD_ACCEPT
)
157 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_ACCEPT
);
158 if (flags
& FD_CONNECT
)
159 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CONNECT
);
160 if (flags
& FD_CLOSE
)
161 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CLOSE
);
164 gs_WSAEventSelect(d
->fd
, NetworkEvent
, 0);
170 // ----------------------------------------------------------------------------
171 // MSW implementation of wxSocketManager
172 // ----------------------------------------------------------------------------
174 class wxSocketMSWManager
: public wxSocketManager
177 virtual bool OnInit();
178 virtual void OnExit();
180 virtual wxSocketImpl
*CreateSocket(wxSocketBase
& wxsocket
)
182 return new wxSocketImplMSW(wxsocket
);
184 virtual void Install_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
185 virtual void Uninstall_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
188 static wxDynamicLibrary gs_wsock32dll
;
191 wxDynamicLibrary
wxSocketMSWManager::gs_wsock32dll
;
193 bool wxSocketMSWManager::OnInit()
195 static LPCTSTR pclassname
= NULL
;
198 /* Create internal window for event notifications */
199 hWin
= wxCreateHiddenWindow(&pclassname
, CLASSNAME
, wxSocket_Internal_WinProc
);
203 /* Initialize socket list */
204 for (i
= 0; i
< MAXSOCKETS
; i
++)
206 socketList
[i
] = NULL
;
210 // we don't link with wsock32.dll (or ws2 in CE case) statically to avoid
211 // dependencies on it for all the application using wx even if they don't use
214 #define WINSOCK_DLL_NAME _T("ws2.dll")
216 #define WINSOCK_DLL_NAME _T("wsock32.dll")
219 gs_wsock32dll
.Load(WINSOCK_DLL_NAME
, wxDL_VERBATIM
| wxDL_QUIET
);
220 if ( !gs_wsock32dll
.IsLoaded() )
224 wxDL_INIT_FUNC(gs_
, WSAAsyncSelect
, gs_wsock32dll
);
225 if ( !gs_WSAAsyncSelect
)
228 wxDL_INIT_FUNC(gs_
, WSAEventSelect
, gs_wsock32dll
);
229 if ( !gs_WSAEventSelect
)
232 wxDL_INIT_FUNC(gs_
, WSACreateEvent
, gs_wsock32dll
);
233 if ( !gs_WSACreateEvent
)
236 wxDL_INIT_FUNC(gs_
, WSAWaitForMultipleEvents
, gs_wsock32dll
);
237 if ( !gs_WSAWaitForMultipleEvents
)
240 wxDL_INIT_FUNC(gs_
, WSAEnumNetworkEvents
, gs_wsock32dll
);
241 if ( !gs_WSAEnumNetworkEvents
)
245 #endif // !__WXWINCE__/__WXWINCE__
247 // finally initialize WinSock
249 return WSAStartup((1 << 8) | 1, &wsaData
) == 0;
252 void wxSocketMSWManager::OnExit()
255 /* Delete the threads here */
256 for(unsigned int i
=0; i
< currSocket
; i
++)
257 CloseHandle(hThread
[i
]);
259 /* Destroy internal window */
261 UnregisterClass(CLASSNAME
, INSTANCE
);
265 gs_wsock32dll
.Unload();
268 /* Per-socket GUI initialization / cleanup */
270 wxSocketImplMSW::wxSocketImplMSW(wxSocketBase
& wxsocket
)
271 : wxSocketImpl(wxsocket
)
273 /* Allocate a new message number for this socket */
274 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
276 int i
= firstAvailable
;
277 while (socketList
[i
] != NULL
)
279 i
= (i
+ 1) % MAXSOCKETS
;
281 if (i
== firstAvailable
) /* abort! */
283 m_msgnumber
= 0; // invalid
287 socketList
[i
] = this;
288 firstAvailable
= (i
+ 1) % MAXSOCKETS
;
289 m_msgnumber
= (i
+ WM_USER
);
292 wxSocketImplMSW::~wxSocketImplMSW()
294 /* Remove the socket from the list */
295 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
299 // we need to remove any pending messages for this socket to avoid having
300 // them sent to a new socket which could reuse the same message number as
301 // soon as we destroy this one
303 while ( ::PeekMessage(&msg
, hWin
, m_msgnumber
, m_msgnumber
, PM_REMOVE
) )
306 socketList
[m_msgnumber
- WM_USER
] = NULL
;
308 //else: the socket has never been created successfully
311 /* Windows proc for asynchronous event handling */
313 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND hWnd
,
318 if ( uMsg
< WM_USER
|| uMsg
> (WM_USER
+ MAXSOCKETS
- 1))
319 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
321 wxSocketImplMSW
*socket
;
322 wxSocketNotify event
;
324 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
326 socket
= socketList
[(uMsg
- WM_USER
)];
327 event
= (wxSocketNotify
) -1;
329 /* Check that the socket still exists (it has not been
330 * destroyed) and for safety, check that the m_fd field
331 * is what we expect it to be.
333 if ((socket
!= NULL
) && ((WPARAM
)socket
->m_fd
== wParam
))
335 switch WSAGETSELECTEVENT(lParam
)
337 case FD_READ
: event
= wxSOCKET_INPUT
; break;
338 case FD_WRITE
: event
= wxSOCKET_OUTPUT
; break;
339 case FD_ACCEPT
: event
= wxSOCKET_CONNECTION
; break;
342 if (WSAGETSELECTERROR(lParam
) != 0)
343 event
= wxSOCKET_LOST
;
345 event
= wxSOCKET_CONNECTION
;
348 case FD_CLOSE
: event
= wxSOCKET_LOST
; break;
353 if (event
== wxSOCKET_LOST
)
354 socket
->m_detected
= wxSOCKET_LOST_FLAG
;
356 socket
->m_detected
|= (1 << event
);
359 } // unlock gs_critical
362 socket
->NotifyOnStateChange(event
);
368 * Enable all event notifications; we need to be notified of all
369 * events for internal processing, but we will only notify users
370 * when an appropriate callback function has been installed.
372 void wxSocketMSWManager::Install_Callback(wxSocketImpl
*socket_
,
373 wxSocketNotify
WXUNUSED(event
))
375 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
377 if (socket
->m_fd
!= INVALID_SOCKET
)
379 /* We could probably just subscribe to all events regardless
380 * of the socket type, but MS recommends to do it this way.
382 long lEvent
= socket
->m_server
?
383 FD_ACCEPT
: (FD_READ
| FD_WRITE
| FD_CONNECT
| FD_CLOSE
);
385 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, lEvent
);
388 * WinCE creates a thread for socket event handling.
389 * All needed parameters get passed through the thread_data structure.
392 thread_data
* d
= new thread_data
;
395 d
->msgnumber
= socket
->m_msgnumber
;
396 d
->fd
= socket
->m_fd
;
397 socketHash
[socket
->m_fd
] = true;
398 hThread
[currSocket
++] = CreateThread(NULL
, 0, &SocketThread
,(LPVOID
)d
, 0, NULL
);
404 * Disable event notifications (used when shutting down the socket)
406 void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl
*socket_
,
407 wxSocketNotify
WXUNUSED(event
))
409 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
411 if (socket
->m_fd
!= INVALID_SOCKET
)
414 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, 0);
417 socketHash
[socket
->m_fd
] = false;
422 // set the wxBase variable to point to our wxSocketManager implementation
424 // see comments in wx/apptrait.h for the explanation of why do we do it
426 static struct ManagerSetter
430 static wxSocketMSWManager s_manager
;
431 wxAppTraits::SetDefaultSocketManager(&s_manager
);
435 // ============================================================================
436 // wxSocketImpl implementation
437 // ============================================================================
440 wxSocketImpl
*wxSocketImpl::Create(wxSocketBase
& wxsocket
)
442 return new wxSocketImplMSW(wxsocket
);
445 void wxSocketImplMSW::DoClose()
447 wxSocketManager::Get()->
448 Uninstall_Callback(this, wxSOCKET_MAX_EVENT
/* unused anyhow */);
454 * Waits for an incoming client connection. Returns a pointer to
455 * a wxSocketImpl object, or NULL if there was an error, in which case
456 * the last error field will be updated for the calling wxSocketImpl.
458 * Error codes (set in the calling wxSocketImpl)
459 * wxSOCKET_INVSOCK - the socket is not valid or not a server.
460 * wxSOCKET_TIMEDOUT - timeout, no incoming connections.
461 * wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
462 * wxSOCKET_MEMERR - couldn't allocate memory.
463 * wxSOCKET_IOERR - low-level error.
465 wxSocketImpl
*wxSocketImplMSW::WaitConnection(wxSocketBase
& wxsocket
)
467 wxSocketImpl
*connection
;
469 WX_SOCKLEN_T fromlen
= sizeof(from
);
473 /* Reenable CONNECTION events */
474 m_detected
&= ~wxSOCKET_CONNECTION_FLAG
;
476 /* If the socket has already been created, we exit immediately */
477 if (m_fd
== INVALID_SOCKET
|| !m_server
)
479 m_error
= wxSOCKET_INVSOCK
;
483 /* Create a wxSocketImpl object for the new connection */
484 connection
= wxSocketImplMSW::Create(wxsocket
);
488 m_error
= wxSOCKET_MEMERR
;
492 /* Wait for a connection (with timeout) */
493 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
496 /* m_error set by Input_Timeout */
500 connection
->m_fd
= accept(m_fd
, (sockaddr
*)&from
, &fromlen
);
502 if (connection
->m_fd
== INVALID_SOCKET
)
504 if (WSAGetLastError() == WSAEWOULDBLOCK
)
505 m_error
= wxSOCKET_WOULDBLOCK
;
507 m_error
= wxSOCKET_IOERR
;
513 /* Initialize all fields */
514 connection
->m_server
= false;
515 connection
->m_stream
= true;
517 /* Setup the peer address field */
518 connection
->m_peer
= GAddress_new();
519 if (!connection
->m_peer
)
522 m_error
= wxSOCKET_MEMERR
;
525 err
= _GAddress_translate_from(connection
->m_peer
, (sockaddr
*)&from
, fromlen
);
526 if (err
!= wxSOCKET_NOERROR
)
528 GAddress_destroy(connection
->m_peer
);
534 ioctlsocket(connection
->m_fd
, FIONBIO
, (u_long FAR
*) &arg
);
535 wxSocketManager::Get()->Install_Callback(connection
);
540 wxSocketError
wxSocketImplMSW::DoHandleConnect(int ret
)
543 if (ret
== SOCKET_ERROR
)
545 int err
= WSAGetLastError();
547 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
548 * is in blocking mode, we select() for the specified timeout
549 * checking for writability to see if the connection request
552 if ((err
== WSAEWOULDBLOCK
) && (!m_non_blocking
))
554 err
= Connect_Timeout();
556 if (err
!= wxSOCKET_NOERROR
)
559 /* m_error is set in Connect_Timeout */
562 return (wxSocketError
) err
;
565 /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
566 * is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
567 * (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
568 * this way if the connection completes, a wxSOCKET_CONNECTION
569 * event will be generated, if enabled.
571 if ((err
== WSAEWOULDBLOCK
) && (m_non_blocking
))
573 m_establishing
= true;
574 m_error
= wxSOCKET_WOULDBLOCK
;
575 return wxSOCKET_WOULDBLOCK
;
578 /* If connect failed with an error other than EWOULDBLOCK,
579 * then the call to Connect() has failed.
582 m_error
= wxSOCKET_IOERR
;
583 return wxSOCKET_IOERR
;
586 return wxSOCKET_NOERROR
;
591 /* Like recv(), send(), ... */
592 int wxSocketImplMSW::Read(void *buffer
, int size
)
596 /* Reenable INPUT events */
597 m_detected
&= ~wxSOCKET_INPUT_FLAG
;
599 if (m_fd
== INVALID_SOCKET
|| m_server
)
601 m_error
= wxSOCKET_INVSOCK
;
605 /* If the socket is blocking, wait for data (with a timeout) */
606 if (Input_Timeout() == wxSOCKET_TIMEDOUT
)
608 m_error
= wxSOCKET_TIMEDOUT
;
614 ret
= Recv_Stream(buffer
, size
);
616 ret
= Recv_Dgram(buffer
, size
);
618 if (ret
== SOCKET_ERROR
)
620 if (WSAGetLastError() != WSAEWOULDBLOCK
)
621 m_error
= wxSOCKET_IOERR
;
623 m_error
= wxSOCKET_WOULDBLOCK
;
630 int wxSocketImplMSW::Write(const void *buffer
, int size
)
634 if (m_fd
== INVALID_SOCKET
|| m_server
)
636 m_error
= wxSOCKET_INVSOCK
;
640 /* If the socket is blocking, wait for writability (with a timeout) */
641 if (Output_Timeout() == wxSOCKET_TIMEDOUT
)
646 ret
= Send_Stream(buffer
, size
);
648 ret
= Send_Dgram(buffer
, size
);
650 if (ret
== SOCKET_ERROR
)
652 if (WSAGetLastError() != WSAEWOULDBLOCK
)
653 m_error
= wxSOCKET_IOERR
;
655 m_error
= wxSOCKET_WOULDBLOCK
;
657 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
658 * does). Once the first OUTPUT event is received, users can assume
659 * that the socket is writable until a read operation fails. Only then
660 * will further OUTPUT events be posted.
662 m_detected
&= ~wxSOCKET_OUTPUT_FLAG
;
672 * For blocking sockets, wait until data is available or
673 * until timeout ellapses.
675 wxSocketError
wxSocketImplMSW::Input_Timeout()
682 FD_SET(m_fd
, &readfds
);
683 if (select(0, &readfds
, NULL
, NULL
, &m_timeout
) == 0)
685 m_error
= wxSOCKET_TIMEDOUT
;
686 return wxSOCKET_TIMEDOUT
;
689 return wxSOCKET_NOERROR
;
693 * For blocking sockets, wait until data can be sent without
694 * blocking or until timeout ellapses.
696 wxSocketError
wxSocketImplMSW::Output_Timeout()
703 FD_SET(m_fd
, &writefds
);
704 if (select(0, NULL
, &writefds
, NULL
, &m_timeout
) == 0)
706 m_error
= wxSOCKET_TIMEDOUT
;
707 return wxSOCKET_TIMEDOUT
;
710 return wxSOCKET_NOERROR
;
714 * For blocking sockets, wait until the connection is
715 * established or fails, or until timeout ellapses.
717 wxSocketError
wxSocketImplMSW::Connect_Timeout()
724 FD_SET(m_fd
, &writefds
);
725 FD_SET(m_fd
, &exceptfds
);
726 if (select(0, NULL
, &writefds
, &exceptfds
, &m_timeout
) == 0)
728 m_error
= wxSOCKET_TIMEDOUT
;
729 return wxSOCKET_TIMEDOUT
;
731 if (!FD_ISSET(m_fd
, &writefds
))
733 m_error
= wxSOCKET_IOERR
;
734 return wxSOCKET_IOERR
;
737 return wxSOCKET_NOERROR
;
740 int wxSocketImplMSW::Recv_Stream(void *buffer
, int size
)
742 return recv(m_fd
, static_cast<char *>(buffer
), size
, 0);
745 int wxSocketImplMSW::Recv_Dgram(void *buffer
, int size
)
748 WX_SOCKLEN_T fromlen
= sizeof(from
);
752 ret
= recvfrom(m_fd
, static_cast<char *>(buffer
),
753 size
, 0, &from
, &fromlen
);
755 if (ret
== SOCKET_ERROR
)
758 /* Translate a system address into a wxSocketImpl address */
761 m_peer
= GAddress_new();
764 m_error
= wxSOCKET_MEMERR
;
768 err
= _GAddress_translate_from(m_peer
, (sockaddr
*)&from
, fromlen
);
769 if (err
!= wxSOCKET_NOERROR
)
771 GAddress_destroy(m_peer
);
780 int wxSocketImplMSW::Send_Stream(const void *buffer
, int size
)
782 return send(m_fd
, static_cast<const char *>(buffer
), size
, 0);
785 int wxSocketImplMSW::Send_Dgram(const void *buffer
, int size
)
787 struct sockaddr
*addr
;
793 m_error
= wxSOCKET_INVADDR
;
797 err
= _GAddress_translate_to(m_peer
, &addr
, &len
);
798 if (err
!= wxSOCKET_NOERROR
)
804 ret
= sendto(m_fd
, static_cast<const char *>(buffer
), size
, 0, addr
, len
);
806 /* Frees memory allocated by _GAddress_translate_to */
813 * -------------------------------------------------------------------------
815 * -------------------------------------------------------------------------
818 /* CHECK_ADDRESS verifies that the current address family is either
819 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
820 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
821 * an appropiate error code.
823 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
825 #define CHECK_ADDRESS(address, family) \
827 if (address->m_family == wxSOCKET_NOFAMILY) \
828 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
829 return address->m_error; \
830 if (address->m_family != wxSOCKET_##family) \
832 address->m_error = wxSOCKET_INVADDR; \
833 return wxSOCKET_INVADDR; \
837 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
839 if (address->m_family == wxSOCKET_NOFAMILY) \
840 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
842 if (address->m_family != wxSOCKET_##family) \
844 address->m_error = wxSOCKET_INVADDR; \
850 GAddress
*GAddress_new()
854 if ((address
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
857 address
->m_family
= wxSOCKET_NOFAMILY
;
858 address
->m_addr
= NULL
;
864 GAddress
*GAddress_copy(GAddress
*address
)
868 if ((addr2
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
871 memcpy(addr2
, address
, sizeof(GAddress
));
875 addr2
->m_addr
= (struct sockaddr
*) malloc(addr2
->m_len
);
876 if (addr2
->m_addr
== NULL
)
881 memcpy(addr2
->m_addr
, address
->m_addr
, addr2
->m_len
);
887 void GAddress_destroy(GAddress
*address
)
890 free(address
->m_addr
);
895 void GAddress_SetFamily(GAddress
*address
, GAddressType type
)
897 address
->m_family
= type
;
900 GAddressType
GAddress_GetFamily(GAddress
*address
)
902 return address
->m_family
;
905 wxSocketError
_GAddress_translate_from(GAddress
*address
,
906 struct sockaddr
*addr
, int len
)
908 address
->m_realfamily
= addr
->sa_family
;
909 switch (addr
->sa_family
)
912 address
->m_family
= wxSOCKET_INET
;
915 address
->m_family
= wxSOCKET_UNIX
;
919 address
->m_family
= wxSOCKET_INET6
;
924 address
->m_error
= wxSOCKET_INVOP
;
925 return wxSOCKET_INVOP
;
930 free(address
->m_addr
);
932 address
->m_len
= len
;
933 address
->m_addr
= (struct sockaddr
*) malloc(len
);
935 if (address
->m_addr
== NULL
)
937 address
->m_error
= wxSOCKET_MEMERR
;
938 return wxSOCKET_MEMERR
;
940 memcpy(address
->m_addr
, addr
, len
);
942 return wxSOCKET_NOERROR
;
945 wxSocketError
_GAddress_translate_to(GAddress
*address
,
946 struct sockaddr
**addr
, int *len
)
948 if (!address
->m_addr
)
950 address
->m_error
= wxSOCKET_INVADDR
;
951 return wxSOCKET_INVADDR
;
954 *len
= address
->m_len
;
955 *addr
= (struct sockaddr
*) malloc(address
->m_len
);
958 address
->m_error
= wxSOCKET_MEMERR
;
959 return wxSOCKET_MEMERR
;
962 memcpy(*addr
, address
->m_addr
, address
->m_len
);
963 return wxSOCKET_NOERROR
;
967 * -------------------------------------------------------------------------
968 * Internet address family
969 * -------------------------------------------------------------------------
972 wxSocketError
_GAddress_Init_INET(GAddress
*address
)
974 address
->m_len
= sizeof(struct sockaddr_in
);
975 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
976 if (address
->m_addr
== NULL
)
978 address
->m_error
= wxSOCKET_MEMERR
;
979 return wxSOCKET_MEMERR
;
982 address
->m_family
= wxSOCKET_INET
;
983 address
->m_realfamily
= AF_INET
;
984 ((struct sockaddr_in
*)address
->m_addr
)->sin_family
= AF_INET
;
985 ((struct sockaddr_in
*)address
->m_addr
)->sin_addr
.s_addr
= INADDR_ANY
;
987 return wxSOCKET_NOERROR
;
990 wxSocketError
GAddress_INET_SetHostName(GAddress
*address
, const char *hostname
)
993 struct in_addr
*addr
;
995 CHECK_ADDRESS(address
, INET
);
997 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
999 addr
->s_addr
= inet_addr(hostname
);
1001 /* If it is a numeric host name, convert it now */
1002 if (addr
->s_addr
== INADDR_NONE
)
1004 struct in_addr
*array_addr
;
1006 /* It is a real name, we solve it */
1007 if ((he
= gethostbyname(hostname
)) == NULL
)
1009 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
1010 address
->m_error
= wxSOCKET_NOHOST
;
1011 return wxSOCKET_NOHOST
;
1013 array_addr
= (struct in_addr
*) *(he
->h_addr_list
);
1014 addr
->s_addr
= array_addr
[0].s_addr
;
1016 return wxSOCKET_NOERROR
;
1019 wxSocketError
GAddress_INET_SetBroadcastAddress(GAddress
*address
)
1021 return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
);
1024 wxSocketError
GAddress_INET_SetAnyAddress(GAddress
*address
)
1026 return GAddress_INET_SetHostAddress(address
, INADDR_ANY
);
1029 wxSocketError
GAddress_INET_SetHostAddress(GAddress
*address
,
1030 unsigned long hostaddr
)
1032 struct in_addr
*addr
;
1034 CHECK_ADDRESS(address
, INET
);
1036 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
1037 addr
->s_addr
= htonl(hostaddr
);
1039 return wxSOCKET_NOERROR
;
1042 wxSocketError
GAddress_INET_SetPortName(GAddress
*address
, const char *port
,
1043 const char *protocol
)
1046 struct sockaddr_in
*addr
;
1048 CHECK_ADDRESS(address
, INET
);
1052 address
->m_error
= wxSOCKET_INVPORT
;
1053 return wxSOCKET_INVPORT
;
1056 se
= getservbyname(port
, protocol
);
1059 if (isdigit(port
[0]))
1063 port_int
= atoi(port
);
1064 addr
= (struct sockaddr_in
*)address
->m_addr
;
1065 addr
->sin_port
= htons((u_short
) port_int
);
1066 return wxSOCKET_NOERROR
;
1069 address
->m_error
= wxSOCKET_INVPORT
;
1070 return wxSOCKET_INVPORT
;
1073 addr
= (struct sockaddr_in
*)address
->m_addr
;
1074 addr
->sin_port
= se
->s_port
;
1076 return wxSOCKET_NOERROR
;
1079 wxSocketError
GAddress_INET_SetPort(GAddress
*address
, unsigned short port
)
1081 struct sockaddr_in
*addr
;
1083 CHECK_ADDRESS(address
, INET
);
1085 addr
= (struct sockaddr_in
*)address
->m_addr
;
1086 addr
->sin_port
= htons(port
);
1088 return wxSOCKET_NOERROR
;
1091 wxSocketError
GAddress_INET_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1095 struct sockaddr_in
*addr
;
1097 CHECK_ADDRESS(address
, INET
);
1099 addr
= (struct sockaddr_in
*)address
->m_addr
;
1100 addr_buf
= (char *)&(addr
->sin_addr
);
1102 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin_addr
), AF_INET
);
1105 address
->m_error
= wxSOCKET_NOHOST
;
1106 return wxSOCKET_NOHOST
;
1109 strncpy(hostname
, he
->h_name
, sbuf
);
1111 return wxSOCKET_NOERROR
;
1114 unsigned long GAddress_INET_GetHostAddress(GAddress
*address
)
1116 struct sockaddr_in
*addr
;
1118 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1120 addr
= (struct sockaddr_in
*)address
->m_addr
;
1122 return ntohl(addr
->sin_addr
.s_addr
);
1125 unsigned short GAddress_INET_GetPort(GAddress
*address
)
1127 struct sockaddr_in
*addr
;
1129 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
1131 addr
= (struct sockaddr_in
*)address
->m_addr
;
1132 return ntohs(addr
->sin_port
);
1138 * -------------------------------------------------------------------------
1139 * Internet IPv6 address family
1140 * -------------------------------------------------------------------------
1142 #include "ws2tcpip.h"
1145 #pragma comment(lib,"ws2_32")
1146 #endif // __VISUALC__
1148 wxSocketError
_GAddress_Init_INET6(GAddress
*address
)
1150 struct in6_addr any_address
= IN6ADDR_ANY_INIT
;
1151 address
->m_len
= sizeof(struct sockaddr_in6
);
1152 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
1153 if (address
->m_addr
== NULL
)
1155 address
->m_error
= wxSOCKET_MEMERR
;
1156 return wxSOCKET_MEMERR
;
1158 memset(address
->m_addr
,0,address
->m_len
);
1160 address
->m_family
= wxSOCKET_INET6
;
1161 address
->m_realfamily
= AF_INET6
;
1162 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_family
= AF_INET6
;
1163 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= any_address
;
1165 return wxSOCKET_NOERROR
;
1168 wxSocketError
GAddress_INET6_SetHostName(GAddress
*address
, const char *hostname
)
1170 CHECK_ADDRESS(address
, INET6
);
1173 memset( & hints
, 0, sizeof( hints
) );
1174 hints
.ai_family
= AF_INET6
;
1175 addrinfo
* info
= 0;
1176 if ( getaddrinfo( hostname
, "0", & hints
, & info
) || ! info
)
1178 address
->m_error
= wxSOCKET_NOHOST
;
1179 return wxSOCKET_NOHOST
;
1182 memcpy( address
->m_addr
, info
->ai_addr
, info
->ai_addrlen
);
1183 freeaddrinfo( info
);
1184 return wxSOCKET_NOERROR
;
1187 wxSocketError
GAddress_INET6_SetAnyAddress(GAddress
*address
)
1189 CHECK_ADDRESS(address
, INET6
);
1191 struct in6_addr addr
;
1192 memset( & addr
, 0, sizeof( addr
) );
1193 return GAddress_INET6_SetHostAddress(address
, addr
);
1195 wxSocketError
GAddress_INET6_SetHostAddress(GAddress
*address
,
1196 struct in6_addr hostaddr
)
1198 CHECK_ADDRESS(address
, INET6
);
1200 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= hostaddr
;
1202 return wxSOCKET_NOERROR
;
1205 wxSocketError
GAddress_INET6_SetPortName(GAddress
*address
, const char *port
,
1206 const char *protocol
)
1209 struct sockaddr_in6
*addr
;
1211 CHECK_ADDRESS(address
, INET6
);
1215 address
->m_error
= wxSOCKET_INVPORT
;
1216 return wxSOCKET_INVPORT
;
1219 se
= getservbyname(port
, protocol
);
1222 if (isdigit((unsigned char) port
[0]))
1226 port_int
= atoi(port
);
1227 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1228 addr
->sin6_port
= htons((u_short
) port_int
);
1229 return wxSOCKET_NOERROR
;
1232 address
->m_error
= wxSOCKET_INVPORT
;
1233 return wxSOCKET_INVPORT
;
1236 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1237 addr
->sin6_port
= se
->s_port
;
1239 return wxSOCKET_NOERROR
;
1242 wxSocketError
GAddress_INET6_SetPort(GAddress
*address
, unsigned short port
)
1244 struct sockaddr_in6
*addr
;
1246 CHECK_ADDRESS(address
, INET6
);
1248 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1249 addr
->sin6_port
= htons(port
);
1251 return wxSOCKET_NOERROR
;
1254 wxSocketError
GAddress_INET6_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1258 struct sockaddr_in6
*addr
;
1260 CHECK_ADDRESS(address
, INET6
);
1262 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1263 addr_buf
= (char *)&(addr
->sin6_addr
);
1265 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin6_addr
), AF_INET6
);
1268 address
->m_error
= wxSOCKET_NOHOST
;
1269 return wxSOCKET_NOHOST
;
1272 strncpy(hostname
, he
->h_name
, sbuf
);
1274 return wxSOCKET_NOERROR
;
1277 wxSocketError
GAddress_INET6_GetHostAddress(GAddress
*address
,struct in6_addr
*hostaddr
)
1279 CHECK_ADDRESS_RETVAL(address
, INET6
, wxSOCKET_INVADDR
);
1280 *hostaddr
= ( (struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
;
1281 return wxSOCKET_NOERROR
;
1284 unsigned short GAddress_INET6_GetPort(GAddress
*address
)
1286 CHECK_ADDRESS_RETVAL(address
, INET6
, 0);
1288 return ntohs( ((struct sockaddr_in6
*)address
->m_addr
)->sin6_port
);
1291 #endif // wxUSE_IPV6
1294 * -------------------------------------------------------------------------
1295 * Unix address family
1296 * -------------------------------------------------------------------------
1299 wxSocketError
_GAddress_Init_UNIX(GAddress
*address
)
1301 address
->m_error
= wxSOCKET_INVADDR
;
1302 return wxSOCKET_INVADDR
;
1305 wxSocketError
GAddress_UNIX_SetPath(GAddress
*address
, const char *WXUNUSED(path
))
1307 address
->m_error
= wxSOCKET_INVADDR
;
1308 return wxSOCKET_INVADDR
;
1311 wxSocketError
GAddress_UNIX_GetPath(GAddress
*address
, char *WXUNUSED(path
), size_t WXUNUSED(sbuf
))
1313 address
->m_error
= wxSOCKET_INVADDR
;
1314 return wxSOCKET_INVADDR
;
1317 #endif // wxUSE_SOCKETS