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/msw/private.h" // for wxGetInstance()
33 #include "wx/apptrait.h"
34 #include "wx/thread.h"
35 #include "wx/dynlib.h"
39 * As WSAAsyncSelect is not present on WinCE, it now uses WSACreateEvent,
40 * WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents. When
41 * enabling eventhandling for a socket a new thread it created that keeps track
42 * of the events and posts a messageto the hidden window to use the standard
45 #include "wx/msw/wince/net.h"
46 #include "wx/hashmap.h"
47 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash
,wxIntegerEqual
,SocketHash
);
50 #define isdigit(x) (x > 47 && x < 58)
52 #include "wx/msw/wince/net.h"
57 # pragma warning(default:4115) /* named type definition in parentheses */
60 #define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
62 /* implemented in utils.cpp */
63 extern "C" WXDLLIMPEXP_BASE HWND
64 wxCreateHiddenWindow(LPCTSTR
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
);
66 /* Maximum number of different wxSocket objects at a given time.
67 * This value can be modified at will, but it CANNOT be greater
68 * than (0x7FFF - WM_USER + 1)
70 #define MAXSOCKETS 1024
72 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
73 #error "MAXSOCKETS is too big!"
77 typedef int (PASCAL
*WSAAsyncSelect_t
)(SOCKET
,HWND
,u_int
,long);
79 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
81 typedef struct _WSANETWORKEVENTS
{
84 } WSANETWORKEVENTS
, FAR
* LPWSANETWORKEVENTS
;
85 typedef HANDLE (PASCAL
*WSACreateEvent_t
)();
86 typedef int (PASCAL
*WSAEventSelect_t
)(SOCKET
,HANDLE
,long);
87 typedef int (PASCAL
*WSAWaitForMultipleEvents_t
)(long,HANDLE
,BOOL
,long,BOOL
);
88 typedef int (PASCAL
*WSAEnumNetworkEvents_t
)(SOCKET
,HANDLE
,LPWSANETWORKEVENTS
);
91 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND
, UINT
, WPARAM
, LPARAM
);
93 /* Global variables */
96 wxCRIT_SECT_DECLARE_MEMBER(gs_critical
);
97 static wxSocketImplMSW
*socketList
[MAXSOCKETS
];
98 static int firstAvailable
;
101 static WSAAsyncSelect_t gs_WSAAsyncSelect
= NULL
;
103 static SocketHash socketHash
;
104 static unsigned int currSocket
;
105 HANDLE hThread
[MAXSOCKETS
];
106 static WSACreateEvent_t gs_WSACreateEvent
= NULL
;
107 static WSAEventSelect_t gs_WSAEventSelect
= NULL
;
108 static WSAWaitForMultipleEvents_t gs_WSAWaitForMultipleEvents
= NULL
;
109 static WSAEnumNetworkEvents_t gs_WSAEnumNetworkEvents
= NULL
;
110 /* This structure will be used to pass data on to the thread that handles socket events.
112 typedef struct thread_data
{
114 unsigned long msgnumber
;
116 unsigned long lEvent
;
121 /* This thread handles socket events on WinCE using WSAEventSelect() as
122 * WSAAsyncSelect is not supported. When an event occurs for the socket, it is
123 * checked what kind of event happend and the correct message gets posted so
124 * that the hidden window can handle it as it would in other MSW builds.
126 DWORD WINAPI
SocketThread(LPVOID data
)
128 WSANETWORKEVENTS NetworkEvents
;
129 thread_data
* d
= (thread_data
*)data
;
131 HANDLE NetworkEvent
= gs_WSACreateEvent();
132 gs_WSAEventSelect(d
->fd
, NetworkEvent
, d
->lEvent
);
134 while(socketHash
[d
->fd
] == true)
136 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent
, FALSE
,INFINITE
, FALSE
)) == WAIT_FAILED
)
138 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
141 if (gs_WSAEnumNetworkEvents(d
->fd
,NetworkEvent
, &NetworkEvents
) == SOCKET_ERROR
)
143 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
147 long flags
= NetworkEvents
.lNetworkEvents
;
149 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_READ
);
150 if (flags
& FD_WRITE
)
151 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_WRITE
);
153 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_OOB
);
154 if (flags
& FD_ACCEPT
)
155 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_ACCEPT
);
156 if (flags
& FD_CONNECT
)
157 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CONNECT
);
158 if (flags
& FD_CLOSE
)
159 ::PostMessage(d
->hEvtWin
, d
->msgnumber
,d
->fd
, FD_CLOSE
);
162 gs_WSAEventSelect(d
->fd
, NetworkEvent
, 0);
168 // ----------------------------------------------------------------------------
169 // MSW implementation of wxSocketManager
170 // ----------------------------------------------------------------------------
172 class wxSocketMSWManager
: public wxSocketManager
175 virtual bool OnInit();
176 virtual void OnExit();
178 virtual wxSocketImpl
*CreateSocket(wxSocketBase
& wxsocket
)
180 return new wxSocketImplMSW(wxsocket
);
182 virtual void Install_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
183 virtual void Uninstall_Callback(wxSocketImpl
*socket
, wxSocketNotify event
);
186 static wxDynamicLibrary gs_wsock32dll
;
189 wxDynamicLibrary
wxSocketMSWManager::gs_wsock32dll
;
191 bool wxSocketMSWManager::OnInit()
193 static LPCTSTR pclassname
= NULL
;
196 /* Create internal window for event notifications */
197 hWin
= wxCreateHiddenWindow(&pclassname
, CLASSNAME
, wxSocket_Internal_WinProc
);
201 /* Initialize socket list */
202 for (i
= 0; i
< MAXSOCKETS
; i
++)
204 socketList
[i
] = NULL
;
208 // we don't link with wsock32.dll (or ws2 in CE case) statically to avoid
209 // dependencies on it for all the application using wx even if they don't use
212 #define WINSOCK_DLL_NAME _T("ws2.dll")
214 #define WINSOCK_DLL_NAME _T("wsock32.dll")
217 gs_wsock32dll
.Load(WINSOCK_DLL_NAME
, wxDL_VERBATIM
| wxDL_QUIET
);
218 if ( !gs_wsock32dll
.IsLoaded() )
222 wxDL_INIT_FUNC(gs_
, WSAAsyncSelect
, gs_wsock32dll
);
223 if ( !gs_WSAAsyncSelect
)
226 wxDL_INIT_FUNC(gs_
, WSAEventSelect
, gs_wsock32dll
);
227 if ( !gs_WSAEventSelect
)
230 wxDL_INIT_FUNC(gs_
, WSACreateEvent
, gs_wsock32dll
);
231 if ( !gs_WSACreateEvent
)
234 wxDL_INIT_FUNC(gs_
, WSAWaitForMultipleEvents
, gs_wsock32dll
);
235 if ( !gs_WSAWaitForMultipleEvents
)
238 wxDL_INIT_FUNC(gs_
, WSAEnumNetworkEvents
, gs_wsock32dll
);
239 if ( !gs_WSAEnumNetworkEvents
)
243 #endif // !__WXWINCE__/__WXWINCE__
245 // finally initialize WinSock
247 return WSAStartup((1 << 8) | 1, &wsaData
) == 0;
250 void wxSocketMSWManager::OnExit()
253 /* Delete the threads here */
254 for(unsigned int i
=0; i
< currSocket
; i
++)
255 CloseHandle(hThread
[i
]);
257 /* Destroy internal window */
259 UnregisterClass(CLASSNAME
, wxGetInstance());
263 gs_wsock32dll
.Unload();
266 /* Per-socket GUI initialization / cleanup */
268 wxSocketImplMSW::wxSocketImplMSW(wxSocketBase
& wxsocket
)
269 : wxSocketImpl(wxsocket
)
271 /* Allocate a new message number for this socket */
272 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
274 int i
= firstAvailable
;
275 while (socketList
[i
] != NULL
)
277 i
= (i
+ 1) % MAXSOCKETS
;
279 if (i
== firstAvailable
) /* abort! */
281 m_msgnumber
= 0; // invalid
285 socketList
[i
] = this;
286 firstAvailable
= (i
+ 1) % MAXSOCKETS
;
287 m_msgnumber
= (i
+ WM_USER
);
290 wxSocketImplMSW::~wxSocketImplMSW()
292 /* Remove the socket from the list */
293 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
297 // we need to remove any pending messages for this socket to avoid having
298 // them sent to a new socket which could reuse the same message number as
299 // soon as we destroy this one
301 while ( ::PeekMessage(&msg
, hWin
, m_msgnumber
, m_msgnumber
, PM_REMOVE
) )
304 socketList
[m_msgnumber
- WM_USER
] = NULL
;
306 //else: the socket has never been created successfully
309 /* Windows proc for asynchronous event handling */
311 LRESULT CALLBACK
wxSocket_Internal_WinProc(HWND hWnd
,
316 if ( uMsg
< WM_USER
|| uMsg
> (WM_USER
+ MAXSOCKETS
- 1))
317 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
319 wxSocketImplMSW
*socket
;
320 wxSocketNotify event
;
322 wxCRIT_SECT_LOCKER(lock
, gs_critical
);
324 socket
= socketList
[(uMsg
- WM_USER
)];
325 event
= (wxSocketNotify
) -1;
327 /* Check that the socket still exists (it has not been
328 * destroyed) and for safety, check that the m_fd field
329 * is what we expect it to be.
331 if ((socket
!= NULL
) && ((WPARAM
)socket
->m_fd
== wParam
))
333 switch WSAGETSELECTEVENT(lParam
)
335 case FD_READ
: event
= wxSOCKET_INPUT
; break;
336 case FD_WRITE
: event
= wxSOCKET_OUTPUT
; break;
337 case FD_ACCEPT
: event
= wxSOCKET_CONNECTION
; break;
340 if (WSAGETSELECTERROR(lParam
) != 0)
341 event
= wxSOCKET_LOST
;
343 event
= wxSOCKET_CONNECTION
;
346 case FD_CLOSE
: event
= wxSOCKET_LOST
; break;
351 if (event
== wxSOCKET_LOST
)
352 socket
->m_detected
= wxSOCKET_LOST_FLAG
;
354 socket
->m_detected
|= (1 << event
);
357 } // unlock gs_critical
360 socket
->NotifyOnStateChange(event
);
366 * Enable all event notifications; we need to be notified of all
367 * events for internal processing, but we will only notify users
368 * when an appropriate callback function has been installed.
370 void wxSocketMSWManager::Install_Callback(wxSocketImpl
*socket_
,
371 wxSocketNotify
WXUNUSED(event
))
373 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
375 if (socket
->m_fd
!= INVALID_SOCKET
)
377 /* We could probably just subscribe to all events regardless
378 * of the socket type, but MS recommends to do it this way.
380 long lEvent
= socket
->m_server
?
381 FD_ACCEPT
: (FD_READ
| FD_WRITE
| FD_CONNECT
| FD_CLOSE
);
383 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, lEvent
);
386 * WinCE creates a thread for socket event handling.
387 * All needed parameters get passed through the thread_data structure.
390 thread_data
* d
= new thread_data
;
393 d
->msgnumber
= socket
->m_msgnumber
;
394 d
->fd
= socket
->m_fd
;
395 socketHash
[socket
->m_fd
] = true;
396 hThread
[currSocket
++] = CreateThread(NULL
, 0, &SocketThread
,(LPVOID
)d
, 0, NULL
);
402 * Disable event notifications (used when shutting down the socket)
404 void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl
*socket_
,
405 wxSocketNotify
WXUNUSED(event
))
407 wxSocketImplMSW
* const socket
= static_cast<wxSocketImplMSW
*>(socket_
);
409 if (socket
->m_fd
!= INVALID_SOCKET
)
412 gs_WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, 0);
415 socketHash
[socket
->m_fd
] = false;
420 // set the wxBase variable to point to our wxSocketManager implementation
422 // see comments in wx/apptrait.h for the explanation of why do we do it
424 static struct ManagerSetter
428 static wxSocketMSWManager s_manager
;
429 wxAppTraits::SetDefaultSocketManager(&s_manager
);
433 // ============================================================================
434 // wxSocketImpl implementation
435 // ============================================================================
438 wxSocketImpl
*wxSocketImpl::Create(wxSocketBase
& wxsocket
)
440 return new wxSocketImplMSW(wxsocket
);
443 void wxSocketImplMSW::DoClose()
445 wxSocketManager::Get()->
446 Uninstall_Callback(this, wxSOCKET_MAX_EVENT
/* unused anyhow */);
451 wxSocketError
wxSocketImplMSW::GetLastError() const
453 switch ( WSAGetLastError() )
456 return wxSOCKET_NOERROR
;
459 return wxSOCKET_INVSOCK
;
462 return wxSOCKET_WOULDBLOCK
;
465 return wxSOCKET_IOERR
;
471 /* Like recv(), send(), ... */
472 int wxSocketImplMSW::Read(void *buffer
, int size
)
476 /* Reenable INPUT events */
477 m_detected
&= ~wxSOCKET_INPUT_FLAG
;
479 if (m_fd
== INVALID_SOCKET
|| m_server
)
481 m_error
= wxSOCKET_INVSOCK
;
487 ret
= Recv_Stream(buffer
, size
);
489 ret
= Recv_Dgram(buffer
, size
);
491 if (ret
== SOCKET_ERROR
)
493 if (WSAGetLastError() != WSAEWOULDBLOCK
)
494 m_error
= wxSOCKET_IOERR
;
496 m_error
= wxSOCKET_WOULDBLOCK
;
503 int wxSocketImplMSW::Write(const void *buffer
, int size
)
507 if (m_fd
== INVALID_SOCKET
|| m_server
)
509 m_error
= wxSOCKET_INVSOCK
;
515 ret
= Send_Stream(buffer
, size
);
517 ret
= Send_Dgram(buffer
, size
);
519 if (ret
== SOCKET_ERROR
)
521 if (WSAGetLastError() != WSAEWOULDBLOCK
)
522 m_error
= wxSOCKET_IOERR
;
524 m_error
= wxSOCKET_WOULDBLOCK
;
526 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
527 * does). Once the first OUTPUT event is received, users can assume
528 * that the socket is writable until a read operation fails. Only then
529 * will further OUTPUT events be posted.
531 m_detected
&= ~wxSOCKET_OUTPUT_FLAG
;
541 * For blocking sockets, wait until the connection is
542 * established or fails, or until timeout ellapses.
544 wxSocketError
wxSocketImplMSW::Connect_Timeout()
551 FD_SET(m_fd
, &writefds
);
552 FD_SET(m_fd
, &exceptfds
);
553 if (select(0, NULL
, &writefds
, &exceptfds
, &m_timeout
) == 0)
555 m_error
= wxSOCKET_TIMEDOUT
;
556 return wxSOCKET_TIMEDOUT
;
558 if (!FD_ISSET(m_fd
, &writefds
))
560 m_error
= wxSOCKET_IOERR
;
561 return wxSOCKET_IOERR
;
564 return wxSOCKET_NOERROR
;
567 int wxSocketImplMSW::Recv_Stream(void *buffer
, int size
)
569 return recv(m_fd
, static_cast<char *>(buffer
), size
, 0);
572 int wxSocketImplMSW::Recv_Dgram(void *buffer
, int size
)
575 WX_SOCKLEN_T fromlen
= sizeof(from
);
579 ret
= recvfrom(m_fd
, static_cast<char *>(buffer
),
580 size
, 0, &from
, &fromlen
);
582 if (ret
== SOCKET_ERROR
)
585 /* Translate a system address into a wxSocketImpl address */
588 m_peer
= GAddress_new();
591 m_error
= wxSOCKET_MEMERR
;
595 err
= _GAddress_translate_from(m_peer
, (sockaddr
*)&from
, fromlen
);
596 if (err
!= wxSOCKET_NOERROR
)
598 GAddress_destroy(m_peer
);
607 int wxSocketImplMSW::Send_Stream(const void *buffer
, int size
)
609 return send(m_fd
, static_cast<const char *>(buffer
), size
, 0);
612 int wxSocketImplMSW::Send_Dgram(const void *buffer
, int size
)
614 struct sockaddr
*addr
;
620 m_error
= wxSOCKET_INVADDR
;
624 err
= _GAddress_translate_to(m_peer
, &addr
, &len
);
625 if (err
!= wxSOCKET_NOERROR
)
631 ret
= sendto(m_fd
, static_cast<const char *>(buffer
), size
, 0, addr
, len
);
633 /* Frees memory allocated by _GAddress_translate_to */
640 * -------------------------------------------------------------------------
642 * -------------------------------------------------------------------------
645 /* CHECK_ADDRESS verifies that the current address family is either
646 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
647 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
648 * an appropiate error code.
650 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
652 #define CHECK_ADDRESS(address, family) \
654 if (address->m_family == wxSOCKET_NOFAMILY) \
655 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
656 return address->m_error; \
657 if (address->m_family != wxSOCKET_##family) \
659 address->m_error = wxSOCKET_INVADDR; \
660 return wxSOCKET_INVADDR; \
664 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
666 if (address->m_family == wxSOCKET_NOFAMILY) \
667 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
669 if (address->m_family != wxSOCKET_##family) \
671 address->m_error = wxSOCKET_INVADDR; \
677 GAddress
*GAddress_new()
681 if ((address
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
684 address
->m_family
= wxSOCKET_NOFAMILY
;
685 address
->m_addr
= NULL
;
691 GAddress
*GAddress_copy(GAddress
*address
)
695 if ((addr2
= (GAddress
*) malloc(sizeof(GAddress
))) == NULL
)
698 memcpy(addr2
, address
, sizeof(GAddress
));
702 addr2
->m_addr
= (struct sockaddr
*) malloc(addr2
->m_len
);
703 if (addr2
->m_addr
== NULL
)
708 memcpy(addr2
->m_addr
, address
->m_addr
, addr2
->m_len
);
714 void GAddress_destroy(GAddress
*address
)
717 free(address
->m_addr
);
722 void GAddress_SetFamily(GAddress
*address
, GAddressType type
)
724 address
->m_family
= type
;
727 GAddressType
GAddress_GetFamily(GAddress
*address
)
729 return address
->m_family
;
732 wxSocketError
_GAddress_translate_from(GAddress
*address
,
733 struct sockaddr
*addr
, int len
)
735 address
->m_realfamily
= addr
->sa_family
;
736 switch (addr
->sa_family
)
739 address
->m_family
= wxSOCKET_INET
;
742 address
->m_family
= wxSOCKET_UNIX
;
746 address
->m_family
= wxSOCKET_INET6
;
751 address
->m_error
= wxSOCKET_INVOP
;
752 return wxSOCKET_INVOP
;
757 free(address
->m_addr
);
759 address
->m_len
= len
;
760 address
->m_addr
= (struct sockaddr
*) malloc(len
);
762 if (address
->m_addr
== NULL
)
764 address
->m_error
= wxSOCKET_MEMERR
;
765 return wxSOCKET_MEMERR
;
767 memcpy(address
->m_addr
, addr
, len
);
769 return wxSOCKET_NOERROR
;
772 wxSocketError
_GAddress_translate_to(GAddress
*address
,
773 struct sockaddr
**addr
, int *len
)
775 if (!address
->m_addr
)
777 address
->m_error
= wxSOCKET_INVADDR
;
778 return wxSOCKET_INVADDR
;
781 *len
= address
->m_len
;
782 *addr
= (struct sockaddr
*) malloc(address
->m_len
);
785 address
->m_error
= wxSOCKET_MEMERR
;
786 return wxSOCKET_MEMERR
;
789 memcpy(*addr
, address
->m_addr
, address
->m_len
);
790 return wxSOCKET_NOERROR
;
794 * -------------------------------------------------------------------------
795 * Internet address family
796 * -------------------------------------------------------------------------
799 wxSocketError
_GAddress_Init_INET(GAddress
*address
)
801 address
->m_len
= sizeof(struct sockaddr_in
);
802 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
803 if (address
->m_addr
== NULL
)
805 address
->m_error
= wxSOCKET_MEMERR
;
806 return wxSOCKET_MEMERR
;
809 address
->m_family
= wxSOCKET_INET
;
810 address
->m_realfamily
= AF_INET
;
811 ((struct sockaddr_in
*)address
->m_addr
)->sin_family
= AF_INET
;
812 ((struct sockaddr_in
*)address
->m_addr
)->sin_addr
.s_addr
= INADDR_ANY
;
814 return wxSOCKET_NOERROR
;
817 wxSocketError
GAddress_INET_SetHostName(GAddress
*address
, const char *hostname
)
820 struct in_addr
*addr
;
822 CHECK_ADDRESS(address
, INET
);
824 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
826 addr
->s_addr
= inet_addr(hostname
);
828 /* If it is a numeric host name, convert it now */
829 if (addr
->s_addr
== INADDR_NONE
)
831 struct in_addr
*array_addr
;
833 /* It is a real name, we solve it */
834 if ((he
= gethostbyname(hostname
)) == NULL
)
836 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
837 address
->m_error
= wxSOCKET_NOHOST
;
838 return wxSOCKET_NOHOST
;
840 array_addr
= (struct in_addr
*) *(he
->h_addr_list
);
841 addr
->s_addr
= array_addr
[0].s_addr
;
843 return wxSOCKET_NOERROR
;
846 wxSocketError
GAddress_INET_SetBroadcastAddress(GAddress
*address
)
848 return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
);
851 wxSocketError
GAddress_INET_SetAnyAddress(GAddress
*address
)
853 return GAddress_INET_SetHostAddress(address
, INADDR_ANY
);
856 wxSocketError
GAddress_INET_SetHostAddress(GAddress
*address
,
857 unsigned long hostaddr
)
859 struct in_addr
*addr
;
861 CHECK_ADDRESS(address
, INET
);
863 addr
= &(((struct sockaddr_in
*)address
->m_addr
)->sin_addr
);
864 addr
->s_addr
= htonl(hostaddr
);
866 return wxSOCKET_NOERROR
;
869 wxSocketError
GAddress_INET_SetPortName(GAddress
*address
, const char *port
,
870 const char *protocol
)
873 struct sockaddr_in
*addr
;
875 CHECK_ADDRESS(address
, INET
);
879 address
->m_error
= wxSOCKET_INVPORT
;
880 return wxSOCKET_INVPORT
;
883 se
= getservbyname(port
, protocol
);
886 if (isdigit(port
[0]))
890 port_int
= atoi(port
);
891 addr
= (struct sockaddr_in
*)address
->m_addr
;
892 addr
->sin_port
= htons((u_short
) port_int
);
893 return wxSOCKET_NOERROR
;
896 address
->m_error
= wxSOCKET_INVPORT
;
897 return wxSOCKET_INVPORT
;
900 addr
= (struct sockaddr_in
*)address
->m_addr
;
901 addr
->sin_port
= se
->s_port
;
903 return wxSOCKET_NOERROR
;
906 wxSocketError
GAddress_INET_SetPort(GAddress
*address
, unsigned short port
)
908 struct sockaddr_in
*addr
;
910 CHECK_ADDRESS(address
, INET
);
912 addr
= (struct sockaddr_in
*)address
->m_addr
;
913 addr
->sin_port
= htons(port
);
915 return wxSOCKET_NOERROR
;
918 wxSocketError
GAddress_INET_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
922 struct sockaddr_in
*addr
;
924 CHECK_ADDRESS(address
, INET
);
926 addr
= (struct sockaddr_in
*)address
->m_addr
;
927 addr_buf
= (char *)&(addr
->sin_addr
);
929 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin_addr
), AF_INET
);
932 address
->m_error
= wxSOCKET_NOHOST
;
933 return wxSOCKET_NOHOST
;
936 strncpy(hostname
, he
->h_name
, sbuf
);
938 return wxSOCKET_NOERROR
;
941 unsigned long GAddress_INET_GetHostAddress(GAddress
*address
)
943 struct sockaddr_in
*addr
;
945 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
947 addr
= (struct sockaddr_in
*)address
->m_addr
;
949 return ntohl(addr
->sin_addr
.s_addr
);
952 unsigned short GAddress_INET_GetPort(GAddress
*address
)
954 struct sockaddr_in
*addr
;
956 CHECK_ADDRESS_RETVAL(address
, INET
, 0);
958 addr
= (struct sockaddr_in
*)address
->m_addr
;
959 return ntohs(addr
->sin_port
);
965 * -------------------------------------------------------------------------
966 * Internet IPv6 address family
967 * -------------------------------------------------------------------------
969 #include "ws2tcpip.h"
972 #pragma comment(lib,"ws2_32")
973 #endif // __VISUALC__
975 wxSocketError
_GAddress_Init_INET6(GAddress
*address
)
977 struct in6_addr any_address
= IN6ADDR_ANY_INIT
;
978 address
->m_len
= sizeof(struct sockaddr_in6
);
979 address
->m_addr
= (struct sockaddr
*) malloc(address
->m_len
);
980 if (address
->m_addr
== NULL
)
982 address
->m_error
= wxSOCKET_MEMERR
;
983 return wxSOCKET_MEMERR
;
985 memset(address
->m_addr
,0,address
->m_len
);
987 address
->m_family
= wxSOCKET_INET6
;
988 address
->m_realfamily
= AF_INET6
;
989 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_family
= AF_INET6
;
990 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= any_address
;
992 return wxSOCKET_NOERROR
;
995 wxSocketError
GAddress_INET6_SetHostName(GAddress
*address
, const char *hostname
)
997 CHECK_ADDRESS(address
, INET6
);
1000 memset( & hints
, 0, sizeof( hints
) );
1001 hints
.ai_family
= AF_INET6
;
1002 addrinfo
* info
= 0;
1003 if ( getaddrinfo( hostname
, "0", & hints
, & info
) || ! info
)
1005 address
->m_error
= wxSOCKET_NOHOST
;
1006 return wxSOCKET_NOHOST
;
1009 memcpy( address
->m_addr
, info
->ai_addr
, info
->ai_addrlen
);
1010 freeaddrinfo( info
);
1011 return wxSOCKET_NOERROR
;
1014 wxSocketError
GAddress_INET6_SetAnyAddress(GAddress
*address
)
1016 CHECK_ADDRESS(address
, INET6
);
1018 struct in6_addr addr
;
1019 memset( & addr
, 0, sizeof( addr
) );
1020 return GAddress_INET6_SetHostAddress(address
, addr
);
1022 wxSocketError
GAddress_INET6_SetHostAddress(GAddress
*address
,
1023 struct in6_addr hostaddr
)
1025 CHECK_ADDRESS(address
, INET6
);
1027 ((struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
= hostaddr
;
1029 return wxSOCKET_NOERROR
;
1032 wxSocketError
GAddress_INET6_SetPortName(GAddress
*address
, const char *port
,
1033 const char *protocol
)
1036 struct sockaddr_in6
*addr
;
1038 CHECK_ADDRESS(address
, INET6
);
1042 address
->m_error
= wxSOCKET_INVPORT
;
1043 return wxSOCKET_INVPORT
;
1046 se
= getservbyname(port
, protocol
);
1049 if (isdigit((unsigned char) port
[0]))
1053 port_int
= atoi(port
);
1054 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1055 addr
->sin6_port
= htons((u_short
) port_int
);
1056 return wxSOCKET_NOERROR
;
1059 address
->m_error
= wxSOCKET_INVPORT
;
1060 return wxSOCKET_INVPORT
;
1063 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1064 addr
->sin6_port
= se
->s_port
;
1066 return wxSOCKET_NOERROR
;
1069 wxSocketError
GAddress_INET6_SetPort(GAddress
*address
, unsigned short port
)
1071 struct sockaddr_in6
*addr
;
1073 CHECK_ADDRESS(address
, INET6
);
1075 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1076 addr
->sin6_port
= htons(port
);
1078 return wxSOCKET_NOERROR
;
1081 wxSocketError
GAddress_INET6_GetHostName(GAddress
*address
, char *hostname
, size_t sbuf
)
1085 struct sockaddr_in6
*addr
;
1087 CHECK_ADDRESS(address
, INET6
);
1089 addr
= (struct sockaddr_in6
*)address
->m_addr
;
1090 addr_buf
= (char *)&(addr
->sin6_addr
);
1092 he
= gethostbyaddr(addr_buf
, sizeof(addr
->sin6_addr
), AF_INET6
);
1095 address
->m_error
= wxSOCKET_NOHOST
;
1096 return wxSOCKET_NOHOST
;
1099 strncpy(hostname
, he
->h_name
, sbuf
);
1101 return wxSOCKET_NOERROR
;
1104 wxSocketError
GAddress_INET6_GetHostAddress(GAddress
*address
,struct in6_addr
*hostaddr
)
1106 CHECK_ADDRESS_RETVAL(address
, INET6
, wxSOCKET_INVADDR
);
1107 *hostaddr
= ( (struct sockaddr_in6
*)address
->m_addr
)->sin6_addr
;
1108 return wxSOCKET_NOERROR
;
1111 unsigned short GAddress_INET6_GetPort(GAddress
*address
)
1113 CHECK_ADDRESS_RETVAL(address
, INET6
, 0);
1115 return ntohs( ((struct sockaddr_in6
*)address
->m_addr
)->sin6_port
);
1118 #endif // wxUSE_IPV6
1121 * -------------------------------------------------------------------------
1122 * Unix address family
1123 * -------------------------------------------------------------------------
1126 wxSocketError
_GAddress_Init_UNIX(GAddress
*address
)
1128 address
->m_error
= wxSOCKET_INVADDR
;
1129 return wxSOCKET_INVADDR
;
1132 wxSocketError
GAddress_UNIX_SetPath(GAddress
*address
, const char *WXUNUSED(path
))
1134 address
->m_error
= wxSOCKET_INVADDR
;
1135 return wxSOCKET_INVADDR
;
1138 wxSocketError
GAddress_UNIX_GetPath(GAddress
*address
, char *WXUNUSED(path
), size_t WXUNUSED(sbuf
))
1140 address
->m_error
= wxSOCKET_INVADDR
;
1141 return wxSOCKET_INVADDR
;
1144 #endif // wxUSE_SOCKETS