move Read/Write() to common code, there was almost nothing platform-specific in it
[wxWidgets.git] / src / msw / sockmsw.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/sockmsw.cpp
3 // Purpose: MSW-specific socket code
4 // Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
5 // Created: April 1997
6 // Copyright: (C) 1999-1997, Guilhem Lavaux
7 // (C) 1999-2000, Guillermo Rodriguez Garcia
8 // (C) 2008 Vadim Zeitlin
9 // RCS_ID: $Id$
10 // License: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #if wxUSE_SOCKETS
22
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
26 */
27 #ifdef _MSC_VER
28 # pragma warning(disable:4115) /* named type definition in parentheses */
29 #endif
30
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"
36
37 #ifdef __WXWINCE__
38 /*
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
43 * message loop.
44 */
45 #include "wx/msw/wince/net.h"
46 #include "wx/hashmap.h"
47 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash,wxIntegerEqual,SocketHash);
48
49 #ifndef isdigit
50 #define isdigit(x) (x > 47 && x < 58)
51 #endif
52 #include "wx/msw/wince/net.h"
53
54 #endif // __WXWINCE__
55
56 #ifdef _MSC_VER
57 # pragma warning(default:4115) /* named type definition in parentheses */
58 #endif
59
60 #define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
61
62 /* implemented in utils.cpp */
63 extern "C" WXDLLIMPEXP_BASE HWND
64 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
65
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)
69 */
70 #define MAXSOCKETS 1024
71
72 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
73 #error "MAXSOCKETS is too big!"
74 #endif
75
76 #ifndef __WXWINCE__
77 typedef int (PASCAL *WSAAsyncSelect_t)(SOCKET,HWND,u_int,long);
78 #else
79 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
80 */
81 typedef struct _WSANETWORKEVENTS {
82 long lNetworkEvents;
83 int iErrorCode[10];
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);
89 #endif //__WXWINCE__
90
91 LRESULT CALLBACK wxSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM);
92
93 /* Global variables */
94
95 static HWND hWin;
96 wxCRIT_SECT_DECLARE_MEMBER(gs_critical);
97 static wxSocketImplMSW *socketList[MAXSOCKETS];
98 static int firstAvailable;
99
100 #ifndef __WXWINCE__
101 static WSAAsyncSelect_t gs_WSAAsyncSelect = NULL;
102 #else
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.
111 */
112 typedef struct thread_data{
113 HWND hEvtWin;
114 unsigned long msgnumber;
115 unsigned long fd;
116 unsigned long lEvent;
117 }thread_data;
118 #endif
119
120 #ifdef __WXWINCE__
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.
125 */
126 DWORD WINAPI SocketThread(LPVOID data)
127 {
128 WSANETWORKEVENTS NetworkEvents;
129 thread_data* d = (thread_data *)data;
130
131 HANDLE NetworkEvent = gs_WSACreateEvent();
132 gs_WSAEventSelect(d->fd, NetworkEvent, d->lEvent);
133
134 while(socketHash[d->fd] == true)
135 {
136 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent, FALSE,INFINITE, FALSE)) == WAIT_FAILED)
137 {
138 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
139 return 0;
140 }
141 if (gs_WSAEnumNetworkEvents(d->fd ,NetworkEvent, &NetworkEvents) == SOCKET_ERROR)
142 {
143 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
144 return 0;
145 }
146
147 long flags = NetworkEvents.lNetworkEvents;
148 if (flags & FD_READ)
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);
152 if (flags & FD_OOB)
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);
160
161 }
162 gs_WSAEventSelect(d->fd, NetworkEvent, 0);
163 ExitThread(0);
164 return 0;
165 }
166 #endif
167
168 // ----------------------------------------------------------------------------
169 // MSW implementation of wxSocketManager
170 // ----------------------------------------------------------------------------
171
172 class wxSocketMSWManager : public wxSocketManager
173 {
174 public:
175 virtual bool OnInit();
176 virtual void OnExit();
177
178 virtual wxSocketImpl *CreateSocket(wxSocketBase& wxsocket)
179 {
180 return new wxSocketImplMSW(wxsocket);
181 }
182 virtual void Install_Callback(wxSocketImpl *socket, wxSocketNotify event);
183 virtual void Uninstall_Callback(wxSocketImpl *socket, wxSocketNotify event);
184
185 private:
186 static wxDynamicLibrary gs_wsock32dll;
187 };
188
189 wxDynamicLibrary wxSocketMSWManager::gs_wsock32dll;
190
191 bool wxSocketMSWManager::OnInit()
192 {
193 static LPCTSTR pclassname = NULL;
194 int i;
195
196 /* Create internal window for event notifications */
197 hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, wxSocket_Internal_WinProc);
198 if (!hWin)
199 return false;
200
201 /* Initialize socket list */
202 for (i = 0; i < MAXSOCKETS; i++)
203 {
204 socketList[i] = NULL;
205 }
206 firstAvailable = 0;
207
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
210 // sockets
211 #ifdef __WXWINCE__
212 #define WINSOCK_DLL_NAME _T("ws2.dll")
213 #else
214 #define WINSOCK_DLL_NAME _T("wsock32.dll")
215 #endif
216
217 gs_wsock32dll.Load(WINSOCK_DLL_NAME, wxDL_VERBATIM | wxDL_QUIET);
218 if ( !gs_wsock32dll.IsLoaded() )
219 return false;
220
221 #ifndef __WXWINCE__
222 wxDL_INIT_FUNC(gs_, WSAAsyncSelect, gs_wsock32dll);
223 if ( !gs_WSAAsyncSelect )
224 return false;
225 #else
226 wxDL_INIT_FUNC(gs_, WSAEventSelect, gs_wsock32dll);
227 if ( !gs_WSAEventSelect )
228 return false;
229
230 wxDL_INIT_FUNC(gs_, WSACreateEvent, gs_wsock32dll);
231 if ( !gs_WSACreateEvent )
232 return false;
233
234 wxDL_INIT_FUNC(gs_, WSAWaitForMultipleEvents, gs_wsock32dll);
235 if ( !gs_WSAWaitForMultipleEvents )
236 return false;
237
238 wxDL_INIT_FUNC(gs_, WSAEnumNetworkEvents, gs_wsock32dll);
239 if ( !gs_WSAEnumNetworkEvents )
240 return false;
241
242 currSocket = 0;
243 #endif // !__WXWINCE__/__WXWINCE__
244
245 // finally initialize WinSock
246 WSADATA wsaData;
247 return WSAStartup((1 << 8) | 1, &wsaData) == 0;
248 }
249
250 void wxSocketMSWManager::OnExit()
251 {
252 #ifdef __WXWINCE__
253 /* Delete the threads here */
254 for(unsigned int i=0; i < currSocket; i++)
255 CloseHandle(hThread[i]);
256 #endif
257 /* Destroy internal window */
258 DestroyWindow(hWin);
259 UnregisterClass(CLASSNAME, wxGetInstance());
260
261 WSACleanup();
262
263 gs_wsock32dll.Unload();
264 }
265
266 /* Per-socket GUI initialization / cleanup */
267
268 wxSocketImplMSW::wxSocketImplMSW(wxSocketBase& wxsocket)
269 : wxSocketImpl(wxsocket)
270 {
271 /* Allocate a new message number for this socket */
272 wxCRIT_SECT_LOCKER(lock, gs_critical);
273
274 int i = firstAvailable;
275 while (socketList[i] != NULL)
276 {
277 i = (i + 1) % MAXSOCKETS;
278
279 if (i == firstAvailable) /* abort! */
280 {
281 m_msgnumber = 0; // invalid
282 return;
283 }
284 }
285 socketList[i] = this;
286 firstAvailable = (i + 1) % MAXSOCKETS;
287 m_msgnumber = (i + WM_USER);
288 }
289
290 wxSocketImplMSW::~wxSocketImplMSW()
291 {
292 /* Remove the socket from the list */
293 wxCRIT_SECT_LOCKER(lock, gs_critical);
294
295 if ( m_msgnumber )
296 {
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
300 MSG msg;
301 while ( ::PeekMessage(&msg, hWin, m_msgnumber, m_msgnumber, PM_REMOVE) )
302 ;
303
304 socketList[m_msgnumber - WM_USER] = NULL;
305 }
306 //else: the socket has never been created successfully
307 }
308
309 /* Windows proc for asynchronous event handling */
310
311 LRESULT CALLBACK wxSocket_Internal_WinProc(HWND hWnd,
312 UINT uMsg,
313 WPARAM wParam,
314 LPARAM lParam)
315 {
316 if ( uMsg < WM_USER || uMsg > (WM_USER + MAXSOCKETS - 1))
317 return DefWindowProc(hWnd, uMsg, wParam, lParam);
318
319 wxSocketImplMSW *socket;
320 wxSocketNotify event = (wxSocketNotify)-1;
321 {
322 wxCRIT_SECT_LOCKER(lock, gs_critical);
323
324 socket = socketList[(uMsg - WM_USER)];
325 if ( !socket )
326 return 0;
327
328 wxASSERT_MSG( socket->m_fd == (SOCKET)wParam,
329 "mismatch between message and socket?" );
330
331 switch WSAGETSELECTEVENT(lParam)
332 {
333 case FD_READ:
334 event = wxSOCKET_INPUT;
335 break;
336
337 case FD_WRITE:
338 event = wxSOCKET_OUTPUT;
339 break;
340
341 case FD_ACCEPT:
342 event = wxSOCKET_CONNECTION;
343 break;
344
345 case FD_CONNECT:
346 event = WSAGETSELECTERROR(lParam) ? wxSOCKET_LOST
347 : wxSOCKET_CONNECTION;
348 break;
349
350 case FD_CLOSE:
351 event = wxSOCKET_LOST;
352 break;
353
354 default:
355 wxFAIL_MSG( "unexpected socket notification" );
356 return 0;
357 }
358 } // unlock gs_critical
359
360 socket->NotifyOnStateChange(event);
361
362 return 0;
363 }
364
365 /*
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.
369 */
370 void wxSocketMSWManager::Install_Callback(wxSocketImpl *socket_,
371 wxSocketNotify WXUNUSED(event))
372 {
373 wxSocketImplMSW * const socket = static_cast<wxSocketImplMSW *>(socket_);
374
375 if (socket->m_fd != INVALID_SOCKET)
376 {
377 /* We could probably just subscribe to all events regardless
378 * of the socket type, but MS recommends to do it this way.
379 */
380 long lEvent = socket->m_server?
381 FD_ACCEPT : (FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
382 #ifndef __WXWINCE__
383 gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, lEvent);
384 #else
385 /*
386 * WinCE creates a thread for socket event handling.
387 * All needed parameters get passed through the thread_data structure.
388 */
389
390 thread_data* d = new thread_data;
391 d->lEvent = lEvent;
392 d->hEvtWin = hWin;
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);
397 #endif
398 }
399 }
400
401 /*
402 * Disable event notifications (used when shutting down the socket)
403 */
404 void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl *socket_,
405 wxSocketNotify WXUNUSED(event))
406 {
407 wxSocketImplMSW * const socket = static_cast<wxSocketImplMSW *>(socket_);
408
409 if (socket->m_fd != INVALID_SOCKET)
410 {
411 #ifndef __WXWINCE__
412 gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0);
413 #else
414 //Destroy the thread
415 socketHash[socket->m_fd] = false;
416 #endif
417 }
418 }
419
420 // set the wxBase variable to point to our wxSocketManager implementation
421 //
422 // see comments in wx/apptrait.h for the explanation of why do we do it
423 // like this
424 static struct ManagerSetter
425 {
426 ManagerSetter()
427 {
428 static wxSocketMSWManager s_manager;
429 wxAppTraits::SetDefaultSocketManager(&s_manager);
430 }
431 } gs_managerSetter;
432
433 // ============================================================================
434 // wxSocketImpl implementation
435 // ============================================================================
436
437 /* static */
438 wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
439 {
440 return new wxSocketImplMSW(wxsocket);
441 }
442
443 void wxSocketImplMSW::DoClose()
444 {
445 wxSocketManager::Get()->
446 Uninstall_Callback(this, wxSOCKET_MAX_EVENT /* unused anyhow */);
447
448 closesocket(m_fd);
449 }
450
451 wxSocketError wxSocketImplMSW::GetLastError() const
452 {
453 switch ( WSAGetLastError() )
454 {
455 case 0:
456 return wxSOCKET_NOERROR;
457
458 case WSAENOTSOCK:
459 return wxSOCKET_INVSOCK;
460
461 case WSAEWOULDBLOCK:
462 return wxSOCKET_WOULDBLOCK;
463
464 default:
465 return wxSOCKET_IOERR;
466 }
467 }
468
469 /*
470 * -------------------------------------------------------------------------
471 * GAddress
472 * -------------------------------------------------------------------------
473 */
474
475 /* CHECK_ADDRESS verifies that the current address family is either
476 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
477 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
478 * an appropiate error code.
479 *
480 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
481 */
482 #define CHECK_ADDRESS(address, family) \
483 { \
484 if (address->m_family == wxSOCKET_NOFAMILY) \
485 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
486 return address->m_error; \
487 if (address->m_family != wxSOCKET_##family) \
488 { \
489 address->m_error = wxSOCKET_INVADDR; \
490 return wxSOCKET_INVADDR; \
491 } \
492 }
493
494 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
495 { \
496 if (address->m_family == wxSOCKET_NOFAMILY) \
497 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
498 return retval; \
499 if (address->m_family != wxSOCKET_##family) \
500 { \
501 address->m_error = wxSOCKET_INVADDR; \
502 return retval; \
503 } \
504 }
505
506
507 GAddress *GAddress_new()
508 {
509 GAddress *address;
510
511 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
512 return NULL;
513
514 address->m_family = wxSOCKET_NOFAMILY;
515 address->m_addr = NULL;
516 address->m_len = 0;
517
518 return address;
519 }
520
521 GAddress *GAddress_copy(GAddress *address)
522 {
523 GAddress *addr2;
524
525 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
526 return NULL;
527
528 memcpy(addr2, address, sizeof(GAddress));
529
530 if (address->m_addr)
531 {
532 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
533 if (addr2->m_addr == NULL)
534 {
535 free(addr2);
536 return NULL;
537 }
538 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
539 }
540
541 return addr2;
542 }
543
544 void GAddress_destroy(GAddress *address)
545 {
546 if (address->m_addr)
547 free(address->m_addr);
548
549 free(address);
550 }
551
552 void GAddress_SetFamily(GAddress *address, GAddressType type)
553 {
554 address->m_family = type;
555 }
556
557 GAddressType GAddress_GetFamily(GAddress *address)
558 {
559 return address->m_family;
560 }
561
562 wxSocketError _GAddress_translate_from(GAddress *address,
563 struct sockaddr *addr, int len)
564 {
565 address->m_realfamily = addr->sa_family;
566 switch (addr->sa_family)
567 {
568 case AF_INET:
569 address->m_family = wxSOCKET_INET;
570 break;
571 case AF_UNIX:
572 address->m_family = wxSOCKET_UNIX;
573 break;
574 #if wxUSE_IPV6
575 case AF_INET6:
576 address->m_family = wxSOCKET_INET6;
577 break;
578 #endif
579 default:
580 {
581 address->m_error = wxSOCKET_INVOP;
582 return wxSOCKET_INVOP;
583 }
584 }
585
586 if (address->m_addr)
587 free(address->m_addr);
588
589 address->m_len = len;
590 address->m_addr = (struct sockaddr *) malloc(len);
591
592 if (address->m_addr == NULL)
593 {
594 address->m_error = wxSOCKET_MEMERR;
595 return wxSOCKET_MEMERR;
596 }
597 memcpy(address->m_addr, addr, len);
598
599 return wxSOCKET_NOERROR;
600 }
601
602 wxSocketError _GAddress_translate_to(GAddress *address,
603 struct sockaddr **addr, int *len)
604 {
605 if (!address->m_addr)
606 {
607 address->m_error = wxSOCKET_INVADDR;
608 return wxSOCKET_INVADDR;
609 }
610
611 *len = address->m_len;
612 *addr = (struct sockaddr *) malloc(address->m_len);
613 if (*addr == NULL)
614 {
615 address->m_error = wxSOCKET_MEMERR;
616 return wxSOCKET_MEMERR;
617 }
618
619 memcpy(*addr, address->m_addr, address->m_len);
620 return wxSOCKET_NOERROR;
621 }
622
623 /*
624 * -------------------------------------------------------------------------
625 * Internet address family
626 * -------------------------------------------------------------------------
627 */
628
629 wxSocketError _GAddress_Init_INET(GAddress *address)
630 {
631 address->m_len = sizeof(struct sockaddr_in);
632 address->m_addr = (struct sockaddr *) malloc(address->m_len);
633 if (address->m_addr == NULL)
634 {
635 address->m_error = wxSOCKET_MEMERR;
636 return wxSOCKET_MEMERR;
637 }
638
639 address->m_family = wxSOCKET_INET;
640 address->m_realfamily = AF_INET;
641 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
642 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
643
644 return wxSOCKET_NOERROR;
645 }
646
647 wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
648 {
649 struct hostent *he;
650 struct in_addr *addr;
651
652 CHECK_ADDRESS(address, INET);
653
654 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
655
656 addr->s_addr = inet_addr(hostname);
657
658 /* If it is a numeric host name, convert it now */
659 if (addr->s_addr == INADDR_NONE)
660 {
661 struct in_addr *array_addr;
662
663 /* It is a real name, we solve it */
664 if ((he = gethostbyname(hostname)) == NULL)
665 {
666 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
667 address->m_error = wxSOCKET_NOHOST;
668 return wxSOCKET_NOHOST;
669 }
670 array_addr = (struct in_addr *) *(he->h_addr_list);
671 addr->s_addr = array_addr[0].s_addr;
672 }
673 return wxSOCKET_NOERROR;
674 }
675
676 wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
677 {
678 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
679 }
680
681 wxSocketError GAddress_INET_SetAnyAddress(GAddress *address)
682 {
683 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
684 }
685
686 wxSocketError GAddress_INET_SetHostAddress(GAddress *address,
687 unsigned long hostaddr)
688 {
689 struct in_addr *addr;
690
691 CHECK_ADDRESS(address, INET);
692
693 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
694 addr->s_addr = htonl(hostaddr);
695
696 return wxSOCKET_NOERROR;
697 }
698
699 wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
700 const char *protocol)
701 {
702 struct servent *se;
703 struct sockaddr_in *addr;
704
705 CHECK_ADDRESS(address, INET);
706
707 if (!port)
708 {
709 address->m_error = wxSOCKET_INVPORT;
710 return wxSOCKET_INVPORT;
711 }
712
713 se = getservbyname(port, protocol);
714 if (!se)
715 {
716 if (isdigit(port[0]))
717 {
718 int port_int;
719
720 port_int = atoi(port);
721 addr = (struct sockaddr_in *)address->m_addr;
722 addr->sin_port = htons((u_short) port_int);
723 return wxSOCKET_NOERROR;
724 }
725
726 address->m_error = wxSOCKET_INVPORT;
727 return wxSOCKET_INVPORT;
728 }
729
730 addr = (struct sockaddr_in *)address->m_addr;
731 addr->sin_port = se->s_port;
732
733 return wxSOCKET_NOERROR;
734 }
735
736 wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
737 {
738 struct sockaddr_in *addr;
739
740 CHECK_ADDRESS(address, INET);
741
742 addr = (struct sockaddr_in *)address->m_addr;
743 addr->sin_port = htons(port);
744
745 return wxSOCKET_NOERROR;
746 }
747
748 wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
749 {
750 struct hostent *he;
751 char *addr_buf;
752 struct sockaddr_in *addr;
753
754 CHECK_ADDRESS(address, INET);
755
756 addr = (struct sockaddr_in *)address->m_addr;
757 addr_buf = (char *)&(addr->sin_addr);
758
759 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
760 if (he == NULL)
761 {
762 address->m_error = wxSOCKET_NOHOST;
763 return wxSOCKET_NOHOST;
764 }
765
766 strncpy(hostname, he->h_name, sbuf);
767
768 return wxSOCKET_NOERROR;
769 }
770
771 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
772 {
773 struct sockaddr_in *addr;
774
775 CHECK_ADDRESS_RETVAL(address, INET, 0);
776
777 addr = (struct sockaddr_in *)address->m_addr;
778
779 return ntohl(addr->sin_addr.s_addr);
780 }
781
782 unsigned short GAddress_INET_GetPort(GAddress *address)
783 {
784 struct sockaddr_in *addr;
785
786 CHECK_ADDRESS_RETVAL(address, INET, 0);
787
788 addr = (struct sockaddr_in *)address->m_addr;
789 return ntohs(addr->sin_port);
790 }
791
792
793 #if wxUSE_IPV6
794 /*
795 * -------------------------------------------------------------------------
796 * Internet IPv6 address family
797 * -------------------------------------------------------------------------
798 */
799 #include "ws2tcpip.h"
800
801 #ifdef __VISUALC__
802 #pragma comment(lib,"ws2_32")
803 #endif // __VISUALC__
804
805 wxSocketError _GAddress_Init_INET6(GAddress *address)
806 {
807 struct in6_addr any_address = IN6ADDR_ANY_INIT;
808 address->m_len = sizeof(struct sockaddr_in6);
809 address->m_addr = (struct sockaddr *) malloc(address->m_len);
810 if (address->m_addr == NULL)
811 {
812 address->m_error = wxSOCKET_MEMERR;
813 return wxSOCKET_MEMERR;
814 }
815 memset(address->m_addr,0,address->m_len);
816
817 address->m_family = wxSOCKET_INET6;
818 address->m_realfamily = AF_INET6;
819 ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6;
820 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address;
821
822 return wxSOCKET_NOERROR;
823 }
824
825 wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname)
826 {
827 CHECK_ADDRESS(address, INET6);
828
829 addrinfo hints;
830 memset( & hints, 0, sizeof( hints ) );
831 hints.ai_family = AF_INET6;
832 addrinfo * info = 0;
833 if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info )
834 {
835 address->m_error = wxSOCKET_NOHOST;
836 return wxSOCKET_NOHOST;
837 }
838
839 memcpy( address->m_addr, info->ai_addr, info->ai_addrlen );
840 freeaddrinfo( info );
841 return wxSOCKET_NOERROR;
842 }
843
844 wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address)
845 {
846 CHECK_ADDRESS(address, INET6);
847
848 struct in6_addr addr;
849 memset( & addr, 0, sizeof( addr ) );
850 return GAddress_INET6_SetHostAddress(address, addr);
851 }
852 wxSocketError GAddress_INET6_SetHostAddress(GAddress *address,
853 struct in6_addr hostaddr)
854 {
855 CHECK_ADDRESS(address, INET6);
856
857 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr;
858
859 return wxSOCKET_NOERROR;
860 }
861
862 wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port,
863 const char *protocol)
864 {
865 struct servent *se;
866 struct sockaddr_in6 *addr;
867
868 CHECK_ADDRESS(address, INET6);
869
870 if (!port)
871 {
872 address->m_error = wxSOCKET_INVPORT;
873 return wxSOCKET_INVPORT;
874 }
875
876 se = getservbyname(port, protocol);
877 if (!se)
878 {
879 if (isdigit((unsigned char) port[0]))
880 {
881 int port_int;
882
883 port_int = atoi(port);
884 addr = (struct sockaddr_in6 *)address->m_addr;
885 addr->sin6_port = htons((u_short) port_int);
886 return wxSOCKET_NOERROR;
887 }
888
889 address->m_error = wxSOCKET_INVPORT;
890 return wxSOCKET_INVPORT;
891 }
892
893 addr = (struct sockaddr_in6 *)address->m_addr;
894 addr->sin6_port = se->s_port;
895
896 return wxSOCKET_NOERROR;
897 }
898
899 wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port)
900 {
901 struct sockaddr_in6 *addr;
902
903 CHECK_ADDRESS(address, INET6);
904
905 addr = (struct sockaddr_in6 *)address->m_addr;
906 addr->sin6_port = htons(port);
907
908 return wxSOCKET_NOERROR;
909 }
910
911 wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf)
912 {
913 struct hostent *he;
914 char *addr_buf;
915 struct sockaddr_in6 *addr;
916
917 CHECK_ADDRESS(address, INET6);
918
919 addr = (struct sockaddr_in6 *)address->m_addr;
920 addr_buf = (char *)&(addr->sin6_addr);
921
922 he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6);
923 if (he == NULL)
924 {
925 address->m_error = wxSOCKET_NOHOST;
926 return wxSOCKET_NOHOST;
927 }
928
929 strncpy(hostname, he->h_name, sbuf);
930
931 return wxSOCKET_NOERROR;
932 }
933
934 wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr)
935 {
936 CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR);
937 *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr;
938 return wxSOCKET_NOERROR;
939 }
940
941 unsigned short GAddress_INET6_GetPort(GAddress *address)
942 {
943 CHECK_ADDRESS_RETVAL(address, INET6, 0);
944
945 return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port );
946 }
947
948 #endif // wxUSE_IPV6
949
950 /*
951 * -------------------------------------------------------------------------
952 * Unix address family
953 * -------------------------------------------------------------------------
954 */
955
956 wxSocketError _GAddress_Init_UNIX(GAddress *address)
957 {
958 address->m_error = wxSOCKET_INVADDR;
959 return wxSOCKET_INVADDR;
960 }
961
962 wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
963 {
964 address->m_error = wxSOCKET_INVADDR;
965 return wxSOCKET_INVADDR;
966 }
967
968 wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
969 {
970 address->m_error = wxSOCKET_INVADDR;
971 return wxSOCKET_INVADDR;
972 }
973
974 #endif // wxUSE_SOCKETS