more wxSocket code wx-ification: use wxDynamicLibrary instead of raw Win32 calls
[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/apptrait.h"
33 #include "wx/thread.h"
34 #include "wx/dynlib.h"
35
36 extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance();
37 #define INSTANCE wxGetInstance()
38
39 #ifdef __WXWINCE__
40 /*
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
45 * message loop.
46 */
47 #include "wx/msw/wince/net.h"
48 #include "wx/hashmap.h"
49 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash,wxIntegerEqual,SocketHash);
50
51 #ifndef isdigit
52 #define isdigit(x) (x > 47 && x < 58)
53 #endif
54 #include "wx/msw/wince/net.h"
55
56 #endif // __WXWINCE__
57
58 #ifdef _MSC_VER
59 # pragma warning(default:4115) /* named type definition in parentheses */
60 #endif
61
62 #define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
63
64 /* implemented in utils.cpp */
65 extern "C" WXDLLIMPEXP_BASE HWND
66 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
67
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)
71 */
72 #define MAXSOCKETS 1024
73
74 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
75 #error "MAXSOCKETS is too big!"
76 #endif
77
78 #ifndef __WXWINCE__
79 typedef int (PASCAL *WSAAsyncSelect_t)(SOCKET,HWND,u_int,long);
80 #else
81 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
82 */
83 typedef struct _WSANETWORKEVENTS {
84 long lNetworkEvents;
85 int iErrorCode[10];
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);
91 #endif //__WXWINCE__
92
93 LRESULT CALLBACK wxSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM);
94
95 /* Global variables */
96
97 static HWND hWin;
98 wxCRIT_SECT_DECLARE_MEMBER(gs_critical);
99 static wxSocketImplMSW *socketList[MAXSOCKETS];
100 static int firstAvailable;
101
102 #ifndef __WXWINCE__
103 static WSAAsyncSelect_t gs_WSAAsyncSelect = NULL;
104 #else
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.
113 */
114 typedef struct thread_data{
115 HWND hEvtWin;
116 unsigned long msgnumber;
117 unsigned long fd;
118 unsigned long lEvent;
119 }thread_data;
120 #endif
121
122 #ifdef __WXWINCE__
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.
127 */
128 DWORD WINAPI SocketThread(LPVOID data)
129 {
130 WSANETWORKEVENTS NetworkEvents;
131 thread_data* d = (thread_data *)data;
132
133 HANDLE NetworkEvent = gs_WSACreateEvent();
134 gs_WSAEventSelect(d->fd, NetworkEvent, d->lEvent);
135
136 while(socketHash[d->fd] == true)
137 {
138 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent, FALSE,INFINITE, FALSE)) == WAIT_FAILED)
139 {
140 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
141 return 0;
142 }
143 if (gs_WSAEnumNetworkEvents(d->fd ,NetworkEvent, &NetworkEvents) == SOCKET_ERROR)
144 {
145 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
146 return 0;
147 }
148
149 long flags = NetworkEvents.lNetworkEvents;
150 if (flags & FD_READ)
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);
154 if (flags & FD_OOB)
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);
162
163 }
164 gs_WSAEventSelect(d->fd, NetworkEvent, 0);
165 ExitThread(0);
166 return 0;
167 }
168 #endif
169
170 // ----------------------------------------------------------------------------
171 // MSW implementation of wxSocketManager
172 // ----------------------------------------------------------------------------
173
174 class wxSocketMSWManager : public wxSocketManager
175 {
176 public:
177 virtual bool OnInit();
178 virtual void OnExit();
179
180 virtual wxSocketImpl *CreateSocket(wxSocketBase& wxsocket)
181 {
182 return new wxSocketImplMSW(wxsocket);
183 }
184 virtual void Install_Callback(wxSocketImpl *socket, wxSocketNotify event);
185 virtual void Uninstall_Callback(wxSocketImpl *socket, wxSocketNotify event);
186
187 private:
188 static wxDynamicLibrary gs_wsock32dll;
189 };
190
191 wxDynamicLibrary wxSocketMSWManager::gs_wsock32dll;
192
193 bool wxSocketMSWManager::OnInit()
194 {
195 static LPCTSTR pclassname = NULL;
196 int i;
197
198 /* Create internal window for event notifications */
199 hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, wxSocket_Internal_WinProc);
200 if (!hWin)
201 return false;
202
203 /* Initialize socket list */
204 for (i = 0; i < MAXSOCKETS; i++)
205 {
206 socketList[i] = NULL;
207 }
208 firstAvailable = 0;
209
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
212 // sockets
213 #ifdef __WXWINCE__
214 #define WINSOCK_DLL_NAME _T("ws2.dll")
215 #else
216 #define WINSOCK_DLL_NAME _T("wsock32.dll")
217 #endif
218
219 gs_wsock32dll.Load(WINSOCK_DLL_NAME, wxDL_VERBATIM | wxDL_QUIET);
220 if ( !gs_wsock32dll.IsLoaded() )
221 return false;
222
223 #ifndef __WXWINCE__
224 wxDL_INIT_FUNC(gs_, WSAAsyncSelect, gs_wsock32dll);
225 if ( !gs_WSAAsyncSelect )
226 return false;
227 #else
228 wxDL_INIT_FUNC(gs_, WSAEventSelect, gs_wsock32dll);
229 if ( !gs_WSAEventSelect )
230 return false;
231
232 wxDL_INIT_FUNC(gs_, WSACreateEvent, gs_wsock32dll);
233 if ( !gs_WSACreateEvent )
234 return false;
235
236 wxDL_INIT_FUNC(gs_, WSAWaitForMultipleEvents, gs_wsock32dll);
237 if ( !gs_WSAWaitForMultipleEvents )
238 return false;
239
240 wxDL_INIT_FUNC(gs_, WSAEnumNetworkEvents, gs_wsock32dll);
241 if ( !gs_WSAEnumNetworkEvents )
242 return false;
243
244 currSocket = 0;
245 #endif // !__WXWINCE__/__WXWINCE__
246
247 // finally initialize WinSock
248 WSADATA wsaData;
249 return WSAStartup((1 << 8) | 1, &wsaData) == 0;
250 }
251
252 void wxSocketMSWManager::OnExit()
253 {
254 #ifdef __WXWINCE__
255 /* Delete the threads here */
256 for(unsigned int i=0; i < currSocket; i++)
257 CloseHandle(hThread[i]);
258 #endif
259 /* Destroy internal window */
260 DestroyWindow(hWin);
261 UnregisterClass(CLASSNAME, INSTANCE);
262
263 WSACleanup();
264
265 gs_wsock32dll.Unload();
266 }
267
268 /* Per-socket GUI initialization / cleanup */
269
270 wxSocketImplMSW::wxSocketImplMSW(wxSocketBase& wxsocket)
271 : wxSocketImpl(wxsocket)
272 {
273 /* Allocate a new message number for this socket */
274 wxCRIT_SECT_LOCKER(lock, gs_critical);
275
276 int i = firstAvailable;
277 while (socketList[i] != NULL)
278 {
279 i = (i + 1) % MAXSOCKETS;
280
281 if (i == firstAvailable) /* abort! */
282 {
283 m_msgnumber = 0; // invalid
284 return;
285 }
286 }
287 socketList[i] = this;
288 firstAvailable = (i + 1) % MAXSOCKETS;
289 m_msgnumber = (i + WM_USER);
290 }
291
292 wxSocketImplMSW::~wxSocketImplMSW()
293 {
294 /* Remove the socket from the list */
295 wxCRIT_SECT_LOCKER(lock, gs_critical);
296
297 if ( m_msgnumber )
298 {
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
302 MSG msg;
303 while ( ::PeekMessage(&msg, hWin, m_msgnumber, m_msgnumber, PM_REMOVE) )
304 ;
305
306 socketList[m_msgnumber - WM_USER] = NULL;
307 }
308 //else: the socket has never been created successfully
309 }
310
311 /* Windows proc for asynchronous event handling */
312
313 LRESULT CALLBACK wxSocket_Internal_WinProc(HWND hWnd,
314 UINT uMsg,
315 WPARAM wParam,
316 LPARAM lParam)
317 {
318 if ( uMsg < WM_USER || uMsg > (WM_USER + MAXSOCKETS - 1))
319 return DefWindowProc(hWnd, uMsg, wParam, lParam);
320
321 wxSocketImplMSW *socket;
322 wxSocketNotify event;
323 {
324 wxCRIT_SECT_LOCKER(lock, gs_critical);
325
326 socket = socketList[(uMsg - WM_USER)];
327 event = (wxSocketNotify) -1;
328
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.
332 */
333 if ((socket != NULL) && ((WPARAM)socket->m_fd == wParam))
334 {
335 switch WSAGETSELECTEVENT(lParam)
336 {
337 case FD_READ: event = wxSOCKET_INPUT; break;
338 case FD_WRITE: event = wxSOCKET_OUTPUT; break;
339 case FD_ACCEPT: event = wxSOCKET_CONNECTION; break;
340 case FD_CONNECT:
341 {
342 if (WSAGETSELECTERROR(lParam) != 0)
343 event = wxSOCKET_LOST;
344 else
345 event = wxSOCKET_CONNECTION;
346 break;
347 }
348 case FD_CLOSE: event = wxSOCKET_LOST; break;
349 }
350
351 if (event != -1)
352 {
353 if (event == wxSOCKET_LOST)
354 socket->m_detected = wxSOCKET_LOST_FLAG;
355 else
356 socket->m_detected |= (1 << event);
357 }
358 }
359 } // unlock gs_critical
360
361 if ( socket )
362 socket->NotifyOnStateChange(event);
363
364 return (LRESULT) 0;
365 }
366
367 /*
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.
371 */
372 void wxSocketMSWManager::Install_Callback(wxSocketImpl *socket_,
373 wxSocketNotify WXUNUSED(event))
374 {
375 wxSocketImplMSW * const socket = static_cast<wxSocketImplMSW *>(socket_);
376
377 if (socket->m_fd != INVALID_SOCKET)
378 {
379 /* We could probably just subscribe to all events regardless
380 * of the socket type, but MS recommends to do it this way.
381 */
382 long lEvent = socket->m_server?
383 FD_ACCEPT : (FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
384 #ifndef __WXWINCE__
385 gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, lEvent);
386 #else
387 /*
388 * WinCE creates a thread for socket event handling.
389 * All needed parameters get passed through the thread_data structure.
390 */
391
392 thread_data* d = new thread_data;
393 d->lEvent = lEvent;
394 d->hEvtWin = hWin;
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);
399 #endif
400 }
401 }
402
403 /*
404 * Disable event notifications (used when shutting down the socket)
405 */
406 void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl *socket_,
407 wxSocketNotify WXUNUSED(event))
408 {
409 wxSocketImplMSW * const socket = static_cast<wxSocketImplMSW *>(socket_);
410
411 if (socket->m_fd != INVALID_SOCKET)
412 {
413 #ifndef __WXWINCE__
414 gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0);
415 #else
416 //Destroy the thread
417 socketHash[socket->m_fd] = false;
418 #endif
419 }
420 }
421
422 // set the wxBase variable to point to our wxSocketManager implementation
423 //
424 // see comments in wx/apptrait.h for the explanation of why do we do it
425 // like this
426 static struct ManagerSetter
427 {
428 ManagerSetter()
429 {
430 static wxSocketMSWManager s_manager;
431 wxAppTraits::SetDefaultSocketManager(&s_manager);
432 }
433 } gs_managerSetter;
434
435 // ============================================================================
436 // wxSocketImpl implementation
437 // ============================================================================
438
439 /* static */
440 wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
441 {
442 return new wxSocketImplMSW(wxsocket);
443 }
444
445 void wxSocketImplMSW::DoClose()
446 {
447 wxSocketManager::Get()->
448 Uninstall_Callback(this, wxSOCKET_MAX_EVENT /* unused anyhow */);
449
450 closesocket(m_fd);
451 }
452
453 /*
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.
457 *
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.
464 */
465 wxSocketImpl *wxSocketImplMSW::WaitConnection(wxSocketBase& wxsocket)
466 {
467 wxSocketImpl *connection;
468 wxSockAddr from;
469 WX_SOCKLEN_T fromlen = sizeof(from);
470 wxSocketError err;
471 u_long arg = 1;
472
473 /* Reenable CONNECTION events */
474 m_detected &= ~wxSOCKET_CONNECTION_FLAG;
475
476 /* If the socket has already been created, we exit immediately */
477 if (m_fd == INVALID_SOCKET || !m_server)
478 {
479 m_error = wxSOCKET_INVSOCK;
480 return NULL;
481 }
482
483 /* Create a wxSocketImpl object for the new connection */
484 connection = wxSocketImplMSW::Create(wxsocket);
485
486 if (!connection)
487 {
488 m_error = wxSOCKET_MEMERR;
489 return NULL;
490 }
491
492 /* Wait for a connection (with timeout) */
493 if (Input_Timeout() == wxSOCKET_TIMEDOUT)
494 {
495 delete connection;
496 /* m_error set by Input_Timeout */
497 return NULL;
498 }
499
500 connection->m_fd = accept(m_fd, (sockaddr*)&from, &fromlen);
501
502 if (connection->m_fd == INVALID_SOCKET)
503 {
504 if (WSAGetLastError() == WSAEWOULDBLOCK)
505 m_error = wxSOCKET_WOULDBLOCK;
506 else
507 m_error = wxSOCKET_IOERR;
508
509 delete connection;
510 return NULL;
511 }
512
513 /* Initialize all fields */
514 connection->m_server = false;
515 connection->m_stream = true;
516
517 /* Setup the peer address field */
518 connection->m_peer = GAddress_new();
519 if (!connection->m_peer)
520 {
521 delete connection;
522 m_error = wxSOCKET_MEMERR;
523 return NULL;
524 }
525 err = _GAddress_translate_from(connection->m_peer, (sockaddr*)&from, fromlen);
526 if (err != wxSOCKET_NOERROR)
527 {
528 GAddress_destroy(connection->m_peer);
529 delete connection;
530 m_error = err;
531 return NULL;
532 }
533
534 ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
535 wxSocketManager::Get()->Install_Callback(connection);
536
537 return connection;
538 }
539
540 wxSocketError wxSocketImplMSW::DoHandleConnect(int ret)
541 {
542 // TODO: review this
543 if (ret == SOCKET_ERROR)
544 {
545 int err = WSAGetLastError();
546
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
550 * completes.
551 */
552 if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
553 {
554 err = Connect_Timeout();
555
556 if (err != wxSOCKET_NOERROR)
557 {
558 Close();
559 /* m_error is set in Connect_Timeout */
560 }
561
562 return (wxSocketError) err;
563 }
564
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.
570 */
571 if ((err == WSAEWOULDBLOCK) && (m_non_blocking))
572 {
573 m_establishing = true;
574 m_error = wxSOCKET_WOULDBLOCK;
575 return wxSOCKET_WOULDBLOCK;
576 }
577
578 /* If connect failed with an error other than EWOULDBLOCK,
579 * then the call to Connect() has failed.
580 */
581 Close();
582 m_error = wxSOCKET_IOERR;
583 return wxSOCKET_IOERR;
584 }
585
586 return wxSOCKET_NOERROR;
587 }
588
589 /* Generic IO */
590
591 /* Like recv(), send(), ... */
592 int wxSocketImplMSW::Read(void *buffer, int size)
593 {
594 int ret;
595
596 /* Reenable INPUT events */
597 m_detected &= ~wxSOCKET_INPUT_FLAG;
598
599 if (m_fd == INVALID_SOCKET || m_server)
600 {
601 m_error = wxSOCKET_INVSOCK;
602 return -1;
603 }
604
605 /* If the socket is blocking, wait for data (with a timeout) */
606 if (Input_Timeout() == wxSOCKET_TIMEDOUT)
607 {
608 m_error = wxSOCKET_TIMEDOUT;
609 return -1;
610 }
611
612 /* Read the data */
613 if (m_stream)
614 ret = Recv_Stream(buffer, size);
615 else
616 ret = Recv_Dgram(buffer, size);
617
618 if (ret == SOCKET_ERROR)
619 {
620 if (WSAGetLastError() != WSAEWOULDBLOCK)
621 m_error = wxSOCKET_IOERR;
622 else
623 m_error = wxSOCKET_WOULDBLOCK;
624 return -1;
625 }
626
627 return ret;
628 }
629
630 int wxSocketImplMSW::Write(const void *buffer, int size)
631 {
632 int ret;
633
634 if (m_fd == INVALID_SOCKET || m_server)
635 {
636 m_error = wxSOCKET_INVSOCK;
637 return -1;
638 }
639
640 /* If the socket is blocking, wait for writability (with a timeout) */
641 if (Output_Timeout() == wxSOCKET_TIMEDOUT)
642 return -1;
643
644 /* Write the data */
645 if (m_stream)
646 ret = Send_Stream(buffer, size);
647 else
648 ret = Send_Dgram(buffer, size);
649
650 if (ret == SOCKET_ERROR)
651 {
652 if (WSAGetLastError() != WSAEWOULDBLOCK)
653 m_error = wxSOCKET_IOERR;
654 else
655 m_error = wxSOCKET_WOULDBLOCK;
656
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.
661 */
662 m_detected &= ~wxSOCKET_OUTPUT_FLAG;
663 return -1;
664 }
665
666 return ret;
667 }
668
669 /* Internals (IO) */
670
671 /*
672 * For blocking sockets, wait until data is available or
673 * until timeout ellapses.
674 */
675 wxSocketError wxSocketImplMSW::Input_Timeout()
676 {
677 fd_set readfds;
678
679 if (!m_non_blocking)
680 {
681 FD_ZERO(&readfds);
682 FD_SET(m_fd, &readfds);
683 if (select(0, &readfds, NULL, NULL, &m_timeout) == 0)
684 {
685 m_error = wxSOCKET_TIMEDOUT;
686 return wxSOCKET_TIMEDOUT;
687 }
688 }
689 return wxSOCKET_NOERROR;
690 }
691
692 /*
693 * For blocking sockets, wait until data can be sent without
694 * blocking or until timeout ellapses.
695 */
696 wxSocketError wxSocketImplMSW::Output_Timeout()
697 {
698 fd_set writefds;
699
700 if (!m_non_blocking)
701 {
702 FD_ZERO(&writefds);
703 FD_SET(m_fd, &writefds);
704 if (select(0, NULL, &writefds, NULL, &m_timeout) == 0)
705 {
706 m_error = wxSOCKET_TIMEDOUT;
707 return wxSOCKET_TIMEDOUT;
708 }
709 }
710 return wxSOCKET_NOERROR;
711 }
712
713 /*
714 * For blocking sockets, wait until the connection is
715 * established or fails, or until timeout ellapses.
716 */
717 wxSocketError wxSocketImplMSW::Connect_Timeout()
718 {
719 fd_set writefds;
720 fd_set exceptfds;
721
722 FD_ZERO(&writefds);
723 FD_ZERO(&exceptfds);
724 FD_SET(m_fd, &writefds);
725 FD_SET(m_fd, &exceptfds);
726 if (select(0, NULL, &writefds, &exceptfds, &m_timeout) == 0)
727 {
728 m_error = wxSOCKET_TIMEDOUT;
729 return wxSOCKET_TIMEDOUT;
730 }
731 if (!FD_ISSET(m_fd, &writefds))
732 {
733 m_error = wxSOCKET_IOERR;
734 return wxSOCKET_IOERR;
735 }
736
737 return wxSOCKET_NOERROR;
738 }
739
740 int wxSocketImplMSW::Recv_Stream(void *buffer, int size)
741 {
742 return recv(m_fd, static_cast<char *>(buffer), size, 0);
743 }
744
745 int wxSocketImplMSW::Recv_Dgram(void *buffer, int size)
746 {
747 wxSockAddr from;
748 WX_SOCKLEN_T fromlen = sizeof(from);
749 int ret;
750 wxSocketError err;
751
752 ret = recvfrom(m_fd, static_cast<char *>(buffer),
753 size, 0, &from, &fromlen);
754
755 if (ret == SOCKET_ERROR)
756 return SOCKET_ERROR;
757
758 /* Translate a system address into a wxSocketImpl address */
759 if (!m_peer)
760 {
761 m_peer = GAddress_new();
762 if (!m_peer)
763 {
764 m_error = wxSOCKET_MEMERR;
765 return -1;
766 }
767 }
768 err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
769 if (err != wxSOCKET_NOERROR)
770 {
771 GAddress_destroy(m_peer);
772 m_peer = NULL;
773 m_error = err;
774 return -1;
775 }
776
777 return ret;
778 }
779
780 int wxSocketImplMSW::Send_Stream(const void *buffer, int size)
781 {
782 return send(m_fd, static_cast<const char *>(buffer), size, 0);
783 }
784
785 int wxSocketImplMSW::Send_Dgram(const void *buffer, int size)
786 {
787 struct sockaddr *addr;
788 int len, ret;
789 wxSocketError err;
790
791 if (!m_peer)
792 {
793 m_error = wxSOCKET_INVADDR;
794 return -1;
795 }
796
797 err = _GAddress_translate_to(m_peer, &addr, &len);
798 if (err != wxSOCKET_NOERROR)
799 {
800 m_error = err;
801 return -1;
802 }
803
804 ret = sendto(m_fd, static_cast<const char *>(buffer), size, 0, addr, len);
805
806 /* Frees memory allocated by _GAddress_translate_to */
807 free(addr);
808
809 return ret;
810 }
811
812 /*
813 * -------------------------------------------------------------------------
814 * GAddress
815 * -------------------------------------------------------------------------
816 */
817
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.
822 *
823 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
824 */
825 #define CHECK_ADDRESS(address, family) \
826 { \
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) \
831 { \
832 address->m_error = wxSOCKET_INVADDR; \
833 return wxSOCKET_INVADDR; \
834 } \
835 }
836
837 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
838 { \
839 if (address->m_family == wxSOCKET_NOFAMILY) \
840 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
841 return retval; \
842 if (address->m_family != wxSOCKET_##family) \
843 { \
844 address->m_error = wxSOCKET_INVADDR; \
845 return retval; \
846 } \
847 }
848
849
850 GAddress *GAddress_new()
851 {
852 GAddress *address;
853
854 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
855 return NULL;
856
857 address->m_family = wxSOCKET_NOFAMILY;
858 address->m_addr = NULL;
859 address->m_len = 0;
860
861 return address;
862 }
863
864 GAddress *GAddress_copy(GAddress *address)
865 {
866 GAddress *addr2;
867
868 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
869 return NULL;
870
871 memcpy(addr2, address, sizeof(GAddress));
872
873 if (address->m_addr)
874 {
875 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
876 if (addr2->m_addr == NULL)
877 {
878 free(addr2);
879 return NULL;
880 }
881 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
882 }
883
884 return addr2;
885 }
886
887 void GAddress_destroy(GAddress *address)
888 {
889 if (address->m_addr)
890 free(address->m_addr);
891
892 free(address);
893 }
894
895 void GAddress_SetFamily(GAddress *address, GAddressType type)
896 {
897 address->m_family = type;
898 }
899
900 GAddressType GAddress_GetFamily(GAddress *address)
901 {
902 return address->m_family;
903 }
904
905 wxSocketError _GAddress_translate_from(GAddress *address,
906 struct sockaddr *addr, int len)
907 {
908 address->m_realfamily = addr->sa_family;
909 switch (addr->sa_family)
910 {
911 case AF_INET:
912 address->m_family = wxSOCKET_INET;
913 break;
914 case AF_UNIX:
915 address->m_family = wxSOCKET_UNIX;
916 break;
917 #if wxUSE_IPV6
918 case AF_INET6:
919 address->m_family = wxSOCKET_INET6;
920 break;
921 #endif
922 default:
923 {
924 address->m_error = wxSOCKET_INVOP;
925 return wxSOCKET_INVOP;
926 }
927 }
928
929 if (address->m_addr)
930 free(address->m_addr);
931
932 address->m_len = len;
933 address->m_addr = (struct sockaddr *) malloc(len);
934
935 if (address->m_addr == NULL)
936 {
937 address->m_error = wxSOCKET_MEMERR;
938 return wxSOCKET_MEMERR;
939 }
940 memcpy(address->m_addr, addr, len);
941
942 return wxSOCKET_NOERROR;
943 }
944
945 wxSocketError _GAddress_translate_to(GAddress *address,
946 struct sockaddr **addr, int *len)
947 {
948 if (!address->m_addr)
949 {
950 address->m_error = wxSOCKET_INVADDR;
951 return wxSOCKET_INVADDR;
952 }
953
954 *len = address->m_len;
955 *addr = (struct sockaddr *) malloc(address->m_len);
956 if (*addr == NULL)
957 {
958 address->m_error = wxSOCKET_MEMERR;
959 return wxSOCKET_MEMERR;
960 }
961
962 memcpy(*addr, address->m_addr, address->m_len);
963 return wxSOCKET_NOERROR;
964 }
965
966 /*
967 * -------------------------------------------------------------------------
968 * Internet address family
969 * -------------------------------------------------------------------------
970 */
971
972 wxSocketError _GAddress_Init_INET(GAddress *address)
973 {
974 address->m_len = sizeof(struct sockaddr_in);
975 address->m_addr = (struct sockaddr *) malloc(address->m_len);
976 if (address->m_addr == NULL)
977 {
978 address->m_error = wxSOCKET_MEMERR;
979 return wxSOCKET_MEMERR;
980 }
981
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;
986
987 return wxSOCKET_NOERROR;
988 }
989
990 wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
991 {
992 struct hostent *he;
993 struct in_addr *addr;
994
995 CHECK_ADDRESS(address, INET);
996
997 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
998
999 addr->s_addr = inet_addr(hostname);
1000
1001 /* If it is a numeric host name, convert it now */
1002 if (addr->s_addr == INADDR_NONE)
1003 {
1004 struct in_addr *array_addr;
1005
1006 /* It is a real name, we solve it */
1007 if ((he = gethostbyname(hostname)) == NULL)
1008 {
1009 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
1010 address->m_error = wxSOCKET_NOHOST;
1011 return wxSOCKET_NOHOST;
1012 }
1013 array_addr = (struct in_addr *) *(he->h_addr_list);
1014 addr->s_addr = array_addr[0].s_addr;
1015 }
1016 return wxSOCKET_NOERROR;
1017 }
1018
1019 wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
1020 {
1021 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
1022 }
1023
1024 wxSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1025 {
1026 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1027 }
1028
1029 wxSocketError GAddress_INET_SetHostAddress(GAddress *address,
1030 unsigned long hostaddr)
1031 {
1032 struct in_addr *addr;
1033
1034 CHECK_ADDRESS(address, INET);
1035
1036 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1037 addr->s_addr = htonl(hostaddr);
1038
1039 return wxSOCKET_NOERROR;
1040 }
1041
1042 wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1043 const char *protocol)
1044 {
1045 struct servent *se;
1046 struct sockaddr_in *addr;
1047
1048 CHECK_ADDRESS(address, INET);
1049
1050 if (!port)
1051 {
1052 address->m_error = wxSOCKET_INVPORT;
1053 return wxSOCKET_INVPORT;
1054 }
1055
1056 se = getservbyname(port, protocol);
1057 if (!se)
1058 {
1059 if (isdigit(port[0]))
1060 {
1061 int port_int;
1062
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;
1067 }
1068
1069 address->m_error = wxSOCKET_INVPORT;
1070 return wxSOCKET_INVPORT;
1071 }
1072
1073 addr = (struct sockaddr_in *)address->m_addr;
1074 addr->sin_port = se->s_port;
1075
1076 return wxSOCKET_NOERROR;
1077 }
1078
1079 wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1080 {
1081 struct sockaddr_in *addr;
1082
1083 CHECK_ADDRESS(address, INET);
1084
1085 addr = (struct sockaddr_in *)address->m_addr;
1086 addr->sin_port = htons(port);
1087
1088 return wxSOCKET_NOERROR;
1089 }
1090
1091 wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1092 {
1093 struct hostent *he;
1094 char *addr_buf;
1095 struct sockaddr_in *addr;
1096
1097 CHECK_ADDRESS(address, INET);
1098
1099 addr = (struct sockaddr_in *)address->m_addr;
1100 addr_buf = (char *)&(addr->sin_addr);
1101
1102 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1103 if (he == NULL)
1104 {
1105 address->m_error = wxSOCKET_NOHOST;
1106 return wxSOCKET_NOHOST;
1107 }
1108
1109 strncpy(hostname, he->h_name, sbuf);
1110
1111 return wxSOCKET_NOERROR;
1112 }
1113
1114 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1115 {
1116 struct sockaddr_in *addr;
1117
1118 CHECK_ADDRESS_RETVAL(address, INET, 0);
1119
1120 addr = (struct sockaddr_in *)address->m_addr;
1121
1122 return ntohl(addr->sin_addr.s_addr);
1123 }
1124
1125 unsigned short GAddress_INET_GetPort(GAddress *address)
1126 {
1127 struct sockaddr_in *addr;
1128
1129 CHECK_ADDRESS_RETVAL(address, INET, 0);
1130
1131 addr = (struct sockaddr_in *)address->m_addr;
1132 return ntohs(addr->sin_port);
1133 }
1134
1135
1136 #if wxUSE_IPV6
1137 /*
1138 * -------------------------------------------------------------------------
1139 * Internet IPv6 address family
1140 * -------------------------------------------------------------------------
1141 */
1142 #include "ws2tcpip.h"
1143
1144 #ifdef __VISUALC__
1145 #pragma comment(lib,"ws2_32")
1146 #endif // __VISUALC__
1147
1148 wxSocketError _GAddress_Init_INET6(GAddress *address)
1149 {
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)
1154 {
1155 address->m_error = wxSOCKET_MEMERR;
1156 return wxSOCKET_MEMERR;
1157 }
1158 memset(address->m_addr,0,address->m_len);
1159
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;
1164
1165 return wxSOCKET_NOERROR;
1166 }
1167
1168 wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname)
1169 {
1170 CHECK_ADDRESS(address, INET6);
1171
1172 addrinfo hints;
1173 memset( & hints, 0, sizeof( hints ) );
1174 hints.ai_family = AF_INET6;
1175 addrinfo * info = 0;
1176 if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info )
1177 {
1178 address->m_error = wxSOCKET_NOHOST;
1179 return wxSOCKET_NOHOST;
1180 }
1181
1182 memcpy( address->m_addr, info->ai_addr, info->ai_addrlen );
1183 freeaddrinfo( info );
1184 return wxSOCKET_NOERROR;
1185 }
1186
1187 wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address)
1188 {
1189 CHECK_ADDRESS(address, INET6);
1190
1191 struct in6_addr addr;
1192 memset( & addr, 0, sizeof( addr ) );
1193 return GAddress_INET6_SetHostAddress(address, addr);
1194 }
1195 wxSocketError GAddress_INET6_SetHostAddress(GAddress *address,
1196 struct in6_addr hostaddr)
1197 {
1198 CHECK_ADDRESS(address, INET6);
1199
1200 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr;
1201
1202 return wxSOCKET_NOERROR;
1203 }
1204
1205 wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port,
1206 const char *protocol)
1207 {
1208 struct servent *se;
1209 struct sockaddr_in6 *addr;
1210
1211 CHECK_ADDRESS(address, INET6);
1212
1213 if (!port)
1214 {
1215 address->m_error = wxSOCKET_INVPORT;
1216 return wxSOCKET_INVPORT;
1217 }
1218
1219 se = getservbyname(port, protocol);
1220 if (!se)
1221 {
1222 if (isdigit((unsigned char) port[0]))
1223 {
1224 int port_int;
1225
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;
1230 }
1231
1232 address->m_error = wxSOCKET_INVPORT;
1233 return wxSOCKET_INVPORT;
1234 }
1235
1236 addr = (struct sockaddr_in6 *)address->m_addr;
1237 addr->sin6_port = se->s_port;
1238
1239 return wxSOCKET_NOERROR;
1240 }
1241
1242 wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port)
1243 {
1244 struct sockaddr_in6 *addr;
1245
1246 CHECK_ADDRESS(address, INET6);
1247
1248 addr = (struct sockaddr_in6 *)address->m_addr;
1249 addr->sin6_port = htons(port);
1250
1251 return wxSOCKET_NOERROR;
1252 }
1253
1254 wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1255 {
1256 struct hostent *he;
1257 char *addr_buf;
1258 struct sockaddr_in6 *addr;
1259
1260 CHECK_ADDRESS(address, INET6);
1261
1262 addr = (struct sockaddr_in6 *)address->m_addr;
1263 addr_buf = (char *)&(addr->sin6_addr);
1264
1265 he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6);
1266 if (he == NULL)
1267 {
1268 address->m_error = wxSOCKET_NOHOST;
1269 return wxSOCKET_NOHOST;
1270 }
1271
1272 strncpy(hostname, he->h_name, sbuf);
1273
1274 return wxSOCKET_NOERROR;
1275 }
1276
1277 wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr)
1278 {
1279 CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR);
1280 *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr;
1281 return wxSOCKET_NOERROR;
1282 }
1283
1284 unsigned short GAddress_INET6_GetPort(GAddress *address)
1285 {
1286 CHECK_ADDRESS_RETVAL(address, INET6, 0);
1287
1288 return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port );
1289 }
1290
1291 #endif // wxUSE_IPV6
1292
1293 /*
1294 * -------------------------------------------------------------------------
1295 * Unix address family
1296 * -------------------------------------------------------------------------
1297 */
1298
1299 wxSocketError _GAddress_Init_UNIX(GAddress *address)
1300 {
1301 address->m_error = wxSOCKET_INVADDR;
1302 return wxSOCKET_INVADDR;
1303 }
1304
1305 wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
1306 {
1307 address->m_error = wxSOCKET_INVADDR;
1308 return wxSOCKET_INVADDR;
1309 }
1310
1311 wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
1312 {
1313 address->m_error = wxSOCKET_INVADDR;
1314 return wxSOCKET_INVADDR;
1315 }
1316
1317 #endif // wxUSE_SOCKETS