]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
CW Win32 support
[wxWidgets.git] / src / common / socket.cpp
CommitLineData
f4ada568
GL
1////////////////////////////////////////////////////////////////////////////////
2// Name: socket.cpp
3// Purpose: Socket handler classes
4// Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew
5// Davidson(1995) in wxWeb)
6// Created: April 1997
7// Updated: March 1998
8// Copyright: (C) 1998, 1997, Guilhem Lavaux
9// RCS_ID: $Id$
10// License: see wxWindows license
11////////////////////////////////////////////////////////////////////////////////
384b4373 12#ifdef __GNUG__
f4ada568 13#pragma implementation "socket.h"
0c32066b
JS
14// #pragma interface
15// #pragma implementation "socket.cpp"
f4ada568
GL
16#endif
17
fcc6dddd
JS
18// For compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22#pragma hdrstop
23#endif
24
f4ada568
GL
25/////////////////////////////////////////////////////////////////////////////
26// wxWindows headers
27/////////////////////////////////////////////////////////////////////////////
28#include <wx/defs.h>
29#include <wx/object.h>
30#include <wx/string.h>
31#include <wx/timer.h>
32#include <wx/utils.h>
33
7f555861
JS
34// Not enough OS behaviour defined for wxStubs
35#ifndef __WXSTUBS__
36
f4ada568
GL
37#include <stdlib.h>
38#include <string.h>
39#include <ctype.h>
40
41/////////////////////////////////////////////////////////////////////////////
42// System specific headers
43/////////////////////////////////////////////////////////////////////////////
44#if defined(__WINDOWS__)
45#include <winsock.h>
46#endif // __WINDOWS__
47
48#if defined(__UNIX__)
49
50#ifdef VMS
51#include <socket.h>
52#else
53#include <sys/socket.h>
54#endif
55#include <sys/ioctl.h>
56
57#include <sys/time.h>
58#include <unistd.h>
59
384b4373
RD
60#ifdef sun
61#include <sys/filio.h>
62#endif
63
f4ada568
GL
64#endif // __UNIX__
65
66#include <signal.h>
67#include <errno.h>
68
fcc6dddd
JS
69#ifdef _MSC_VER
70#include <io.h>
71#endif
72
f4ada568
GL
73#if defined(__WXMOTIF__) || defined(__WXXT__)
74#include <X11/Intrinsic.h>
75
76/////////////////////////////
77// Needs internal variables
78/////////////////////////////
79#ifdef __WXXT__
80#define Uses_XtIntrinsic
81#endif
82
83#endif
84
85#if defined(__WXGTK__)
86#include <gtk/gtk.h>
87#endif
88
89/////////////////////////////////////////////////////////////////////////////
90// wxSocket headers
91/////////////////////////////////////////////////////////////////////////////
3b4183d8 92#include "wx/module.h"
f4ada568
GL
93#define WXSOCK_INTERNAL
94#include "wx/sckaddr.h"
95#include "wx/socket.h"
96
f4ada568
GL
97/////////////////////////////////////////////////////////////////////////////
98// Some patch ///// BEGIN
99/////////////////////////////////////////////////////////////////////////////
100#ifdef __WINDOWS__
101#define close closesocket
102#define ioctl ioctlsocket
0c32066b
JS
103#ifdef errno
104#undef errno
105#endif
f4ada568
GL
106#define errno WSAGetLastError()
107#ifdef EWOULDBLOCK
108#undef EWOULDBLOCK
109#endif
110#define EWOULDBLOCK WSAEWOULDBLOCK
111#define ETIMEDOUT WSAETIMEDOUT
112#undef EINTR
113#define EINTR WSAEINTR
114#endif
115
116#ifndef __WINDOWS__
117#define INVALID_SOCKET -1
118#endif
119
120#ifdef __WXMOTIF__
46ccb510 121#define wxAPP_CONTEXT ((XtAppContext)wxTheApp->GetAppContext())
f4ada568
GL
122#endif
123
124#ifdef __WINDOWS__
125// This is an MS TCP/IP routine and is not needed here. Some WinSock
126// implementations (such as PC-NFS) will require you to include this
127// or a similar routine (see appendix in WinSock doc or help file).
128
129#if defined( NEED_WSAFDIsSet ) || defined( _MSC_VER )
130int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set)
131{
132 int i = set->fd_count;
133
134 while (i--)
135 {
136 if (set->fd_array[i] == fd)
137 return 1;
138 }
139
140 return 0;
141}
142#endif
143#endif
144
145#if defined(__WINDOWS__)
146#define PROCESS_EVENTS() wxYield()
147#elif defined(__WXXT__) || defined(__WXMOTIF__)
148#define PROCESS_EVENTS() XtAppProcessEvent(wxAPP_CONTEXT, XtIMAll)
149#elif defined(__WXGTK__)
150#define PROCESS_EVENTS() gtk_main_iteration()
151#endif
152
153/////////////////////////////////////////////////////////////////////////////
154// Some patch ///// END
155/////////////////////////////////////////////////////////////////////////////
156
3b4183d8
GL
157// --------------------------------------------------------------
158// Module
159// --------------------------------------------------------------
160class wxSocketModule: public wxModule {
161 DECLARE_DYNAMIC_CLASS(wxSocketModule)
162public:
163 wxSocketModule() {}
164 bool OnInit();
165 void OnExit();
166};
167
f4ada568
GL
168// --------------------------------------------------------------
169// ClassInfos
170// --------------------------------------------------------------
171#if !USE_SHARED_LIBRARY
172IMPLEMENT_CLASS(wxSocketBase, wxObject)
173IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
174IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
175IMPLEMENT_CLASS(wxSocketHandler, wxObject)
176IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
3b4183d8 177IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
f4ada568
GL
178#endif
179
180class wxSockWakeUp : public wxTimer {
181public:
182 int *my_id;
183 int n_val;
184 wxSocketBase *sock;
185
186 wxSockWakeUp(wxSocketBase *_sock, int *id, int new_val) {
187 my_id = id; n_val = new_val;
188 sock = _sock;
189 }
190 virtual void Notify() {
191 *my_id = n_val;
192 if (sock) sock->Notify(FALSE);
193 }
194};
195
196/// Socket request
197class SockRequest : public wxObject {
198public:
199 char *buffer;
200 size_t size, nbytes;
201 bool done;
202 int error;
203 wxSockWakeUp *auto_wakeup;
204 wxSocketBase::wxRequestNotify type;
205};
384b4373 206
f4ada568
GL
207
208/////////////////////////////////////////////////////////////////////////////
209// Some internal define
210/////////////////////////////////////////////////////////////////////////////
211
212// --------------------------------------------------------------
213// --------- wxSocketBase CONSTRUCTOR ---------------------------
214// --------------------------------------------------------------
215wxSocketBase::wxSocketBase(wxSocketBase::wxSockFlags _flags,
216 wxSocketBase::wxSockType _type) :
217 wxEvtHandler(),
218 m_flags(_flags), m_type(_type), m_connected(FALSE), m_connecting(FALSE),
219 m_fd(INVALID_SOCKET), m_waitflags(0), m_cbk(0), m_cdata(0), m_id(-1),
220 m_handler(0),
221 m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)),
222 m_cbkon(FALSE),
223 m_unread(NULL), m_unrd_size(0),
224 m_processing(FALSE),
225 m_timeout(3600), m_wantbuf(0)
226{
227 m_internal = new wxSockInternal;
228#if defined(__WXXT__) || defined(__WXMOTIF__) || defined(__WXGTK__)
229 m_internal->sock_inputid = 0;
230 m_internal->sock_outputid = 0;
231 m_internal->sock_exceptid = 0;
232#endif
233#ifdef __WINDOWS__
234 m_internal->my_msg = 0;
235#endif
236}
237
238wxSocketBase::wxSocketBase() :
239 wxEvtHandler(),
240 m_flags(WAITALL), m_type(SOCK_UNINIT), m_connected(FALSE),
241 m_connecting(FALSE), m_fd(INVALID_SOCKET), m_waitflags(0),
242 m_cbk(0), m_cdata(0),
243 m_id(-1), m_handler(0),
244 m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)),
245 m_cbkon(FALSE),
246 m_unread(NULL), m_unrd_size(0),
247 m_processing(FALSE),
248 m_timeout(3600), m_wantbuf(0)
249{
250 m_internal = new wxSockInternal;
251#if defined(__WXXT__) || defined(__WXMOTIF__) || defined(__WXGTK__)
252 m_internal->sock_inputid = 0;
253 m_internal->sock_outputid = 0;
254 m_internal->sock_exceptid = 0;
255#endif
256#ifdef __WINDOWS__
257 m_internal->my_msg = 0;
258#endif
259}
260
261// --------------------------------------------------------------
262// --------- wxSocketBase CONSTRUCTOR ---------------------------
263// --------------------------------------------------------------
264wxSocketBase::~wxSocketBase()
265{
266 DestroyCallbacks();
267 Close();
268
269 if (m_unread)
270 free(m_unread);
271 if (m_handler) {
272#ifdef __WINDOWS__
273 if (m_internal->my_msg)
274 m_handler->DestroyMessage(m_internal->my_msg);
275#endif
276 m_handler->UnRegister(this);
277 }
278 m_states.DeleteContents(TRUE);
279
280 delete m_internal;
281}
282
283bool wxSocketBase::Close()
284{
285 if (m_fd != INVALID_SOCKET) {
286 for (int i=0;i<3;i++) {
287 wxNode *n, *node = req_list[i].First();
288
289 while (node) {
290 SockRequest *req = (SockRequest *)node->Data();
291 req->done = TRUE;
384b4373 292
f4ada568
GL
293 n = node->Next();
294 delete node;
295 node = n;
296 }
297 }
298
299 DestroyCallbacks();
300 shutdown(m_fd, 2);
301 close(m_fd);
302 m_fd = INVALID_SOCKET;
303 m_connected = FALSE;
304 }
305
306 return TRUE;
307}
308
309// --------------------------------------------------------------
310// --------- wxSocketBase base IO functions ---------------------
311// --------------------------------------------------------------
312wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes)
313{
314 m_lcount = GetPushback(buffer, nbytes, FALSE);
315
316 // If we have got the whole needed buffer or if we don't want to
317 // wait then it returns immediately.
318 if (!nbytes || (m_lcount && !(m_flags & WAITALL)) )
319 return *this;
320
321 WantBuffer(buffer, nbytes, EVT_READ);
322
323 return *this;
324}
325
326wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes)
327{
328 size_t nbytes_old = nbytes;
329
330 nbytes -= GetPushback(buffer, nbytes, TRUE);
331 if (!nbytes) {
332 m_lcount = nbytes_old;
333 return *this;
334 }
335
336 WantBuffer(buffer, nbytes, EVT_PEEK);
337
338 return *this;
339}
340
341wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes)
342{
343 WantBuffer((char *)buffer, nbytes, EVT_WRITE);
344 return *this;
345}
346
347wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes)
348{
349 SockMsg msg;
350 size_t len, len2, sig;
384b4373 351
f4ada568
GL
352 Read((char *)&msg, sizeof(msg));
353 if (m_lcount != sizeof(msg))
354 return *this;
355
356 sig = msg.sig[0] & 0xff;
357 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
358 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
359 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
360
361 if (sig != 0xfeeddead)
362 return *this;
363 len = msg.len[0] & 0xff;
364 len |= (size_t)(msg.len[1] & 0xff) << 8;
365 len |= (size_t)(msg.len[2] & 0xff) << 16;
366 len |= (size_t)(msg.len[3] & 0xff) << 24;
367 len2 = len;
368 if (len > nbytes)
369 len = nbytes;
370 else
371 len2 = 0;
372
373 if (Read(buffer, len).LastCount() != len)
374 return *this;
375 if (len2 && (Read(NULL, len2).LastCount() != len2))
376 return *this;
377 if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg))
378 return *this;
379
380 sig = msg.sig[0] & 0xff;
381 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
382 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
383 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
384// ERROR
385 if (sig != 0xdeadfeed)
386 return *this;
387
388 return *this;
389}
390
391wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes)
392{
393 SockMsg msg;
384b4373 394
0c32066b
JS
395 msg.sig[0] = (char) 0xad;
396 msg.sig[1] = (char) 0xde;
397 msg.sig[2] = (char) 0xed;
398 msg.sig[3] = (char) 0xfe;
f4ada568 399
0c32066b
JS
400 msg.len[0] = (char) nbytes & 0xff;
401 msg.len[1] = (char) (nbytes >> 8) & 0xff;
402 msg.len[2] = (char) (nbytes >> 16) & 0xff;
403 msg.len[3] = (char) (nbytes >> 24) & 0xff;
f4ada568
GL
404
405 if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg))
406 return *this;
407 if (Write(buffer, nbytes).LastCount() < nbytes)
384b4373 408 return *this;
f4ada568 409
0c32066b
JS
410 msg.sig[0] = (char) 0xed;
411 msg.sig[1] = (char) 0xfe;
412 msg.sig[2] = (char) 0xad;
413 msg.sig[3] = (char) 0xde;
414 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
f4ada568
GL
415 Write((char *)&msg, sizeof(msg));
416
417 return *this;
418}
419
420wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes)
421{
422 CreatePushbackAfter(buffer, nbytes);
423 return *this;
424}
425
426bool wxSocketBase::IsData() const
427{
428 struct timeval tv;
429 fd_set sock_set;
430
431 if (m_fd < 0)
432 return FALSE;
433 if (m_unrd_size > 0)
434 return TRUE;
435
436 tv.tv_sec = 0;
437 tv.tv_usec = 0;
438 FD_ZERO(&sock_set);
439 FD_SET(m_fd, &sock_set);
440 select(FD_SETSIZE, &sock_set, NULL, NULL, &tv);
0c32066b 441 return (FD_ISSET(m_fd, &sock_set) != 0);
f4ada568
GL
442}
443
444// ---------------------------------------------------------------------
445// --------- wxSocketBase Discard(): deletes all byte in the input queue
446// ---------------------------------------------------------------------
447void wxSocketBase::Discard()
448{
449#define MAX_BUFSIZE (10*1024)
450 char *my_data = new char[MAX_BUFSIZE];
451 size_t recv_size = MAX_BUFSIZE;
452
453 SaveState();
454 SetFlags((wxSockFlags)(NOWAIT | SPEED));
384b4373 455
f4ada568
GL
456 while (recv_size == MAX_BUFSIZE) {
457 recv_size = Read(my_data, MAX_BUFSIZE).LastCount();
458 }
459
460 RestoreState();
461 delete [] my_data;
462
463#undef MAX_BUFSIZE
464}
465
466// --------------------------------------------------------------
467// --------- wxSocketBase socket info functions -----------------
468// --------------------------------------------------------------
469bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
470{
471 struct sockaddr my_addr;
472 size_t len_addr = sizeof(my_addr);
473
474 if (m_fd < 0)
475 return FALSE;
476
f4ada568 477 if (getpeername(m_fd, (struct sockaddr *)&my_addr, (int *)&len_addr) < 0)
384b4373 478 return FALSE;
f4ada568
GL
479
480 addr_man.Disassemble(&my_addr, len_addr);
481 return TRUE;
482}
483
484bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
485{
486 struct sockaddr my_addr;
487 size_t len_addr = sizeof(my_addr);
488
489 if (m_fd < 0)
490 return FALSE;
491
f4ada568 492 if (getsockname(m_fd, (struct sockaddr *)&my_addr, (int *)&len_addr) < 0)
f4ada568
GL
493 return FALSE;
494
495 addr_man.Disassemble(&my_addr, len_addr);
496 return TRUE;
497}
498
499// --------------------------------------------------------------
500// --------- wxSocketBase wait functions ------------------------
501// --------------------------------------------------------------
502void wxSocketBase::SaveState()
503{
504 wxSockState *state = new wxSockState;
505
506 state->cbk_on = m_cbkon;
507 state->cbk_set= m_neededreq;
508 state->cbk = m_cbk;
509 state->cdata = m_cdata;
510 state->flags = m_flags;
511 state->notif = m_notifyme;
512
513 m_states.Append(state);
514}
515
516void wxSocketBase::RestoreState()
517{
518 wxNode *node;
519
520 node = m_states.Last();
521 if (!node)
522 return;
523
524 wxSockState *state = (wxSockState *)node->Data();
384b4373 525
f4ada568
GL
526 SetFlags(state->flags);
527 m_neededreq = state->cbk_set;
528 m_cbk = state->cbk;
529 m_cdata = state->cdata;
530 m_notifyme = state->notif;
531 if (state->cbk_on)
532 SetupCallbacks();
533 else
534 DestroyCallbacks();
535
536 delete node;
537 delete state;
538}
539
540// --------------------------------------------------------------
541// --------- wxSocketBase wait functions ------------------------
542// --------------------------------------------------------------
543//
544bool wxSocketBase::_Wait(long seconds, long microseconds, int type)
545{
546 if ((!m_connected && !m_connecting) || m_fd < 0)
547 return FALSE;
548
549 wxSockWakeUp wakeup(this, &m_waitflags, 0);
550
551 SaveState();
552 SetNotify((wxRequestNotify)type);
553 SetupCallbacks();
554
555 if (seconds != -1)
556 wakeup.Start((int)(seconds*1000 + (microseconds / 1000)), TRUE);
384b4373 557
f4ada568
GL
558 m_waitflags = 0x80 | type;
559 while (m_waitflags & 0x80)
560 PROCESS_EVENTS();
561
562 RestoreState();
563
564 if (m_waitflags & 0x40) {
565 m_waitflags = 0;
566 return TRUE;
567 }
568 m_waitflags = 0;
569
570 return FALSE;
571}
572
573bool wxSocketBase::Wait(long seconds, long microseconds)
574{
575 return _Wait(seconds, microseconds, REQ_ACCEPT | REQ_CONNECT |
576 REQ_READ | REQ_WRITE | REQ_LOST);
577}
578
579bool wxSocketBase::WaitForRead(long seconds, long microseconds)
580{
581 return _Wait(seconds, microseconds, REQ_READ | REQ_LOST);
582}
583
584bool wxSocketBase::WaitForWrite(long seconds, long microseconds)
585{
586 return _Wait(seconds, microseconds, REQ_WRITE);
587}
588
589bool wxSocketBase::WaitForLost(long seconds, long microseconds)
590{
591 return _Wait(seconds, microseconds, REQ_LOST);
592}
593
594// --------------------------------------------------------------
595// --------- wxSocketBase callback management -------------------
596// --------------------------------------------------------------
597
598#if defined(__WXMOTIF__) || defined(__WXXT__) || defined(__WXGTK__)
599#if defined(__WXMOTIF__) || defined(__WXXT__)
600static void wx_socket_read(XtPointer client, int *fid,
601 XtInputId *WXUNUSED(id))
602#define fd *fid
603#else
604static void wx_socket_read(gpointer client, gint fd,
605 GdkInputCondition WXUNUSED(cond))
606#define fd fd
607#endif
608{
609 wxSocketBase *sock = (wxSocketBase *)client;
610 char c;
611 int i;
612
613 i = recv(fd, &c, 1, MSG_PEEK);
614
615 if (i == -1 && (sock->NeededReq() & wxSocketBase::REQ_ACCEPT)) {
616 sock->OnRequest(wxSocketBase::EVT_ACCEPT);
617 return;
618 }
619
620 if (i != 0) {
621 if (!(sock->NeededReq() & wxSocketBase::REQ_READ))
622 return;
623
624 sock->OnRequest(wxSocketBase::EVT_READ);
625 } else {
626 if (!(sock->NeededReq() & wxSocketBase::REQ_LOST)) {
627 sock->Close();
628 return;
629 }
630
631 sock->OnRequest(wxSocketBase::EVT_LOST);
632 }
633}
634#undef fd
635
636#if defined(__WXMOTIF__) || defined(__WXXT__)
637static void wx_socket_write(XtPointer client, int *WXUNUSED(fid),
638 XtInputId *WXUNUSED(id))
639#else
640static void wx_socket_write(gpointer client, gint WXUNUSED(fd),
641 GdkInputCondition WXUNUSED(cond))
642#endif
643{
644 wxSocketBase *sock = (wxSocketBase *)client;
645
646 if (!sock->IsConnected())
647 sock->OnRequest(wxSocketBase::EVT_CONNECT);
648 else
649 sock->OnRequest(wxSocketBase::EVT_WRITE);
650}
651#endif
652
653#ifdef wx_xview
654Notify_value wx_sock_read_xview (Notify_client client, int fd)
655{
656 wxSocketBase *sock = (wxSocketBase *)client;
657 char c;
658 int i;
659
660 i = recv(fd, &c, 1, MSG_PEEK);
661
662 if (i == -1 && (sock->NeededReq() & wxSocketBase::REQ_ACCEPT)) {
663 sock->OnRequest(wxSocketBase::EVT_ACCEPT);
664 return;
665 }
666
667 /* Bytes arrived */
668 if (i != 0) {
669 if (!(sock->NeededReq() & wxSocketBase::REQ_READ))
670 return (Notify_value) FALSE;
671
672 sock->OnRequest(wxSocketBase::EVT_READ);
673 } else {
674 if (!(sock->NeededReq() & wxSocketBase::REQ_LOST))
675 return;
676
677 sock->OnRequest(wxSocketBase::EVT_LOST);
678 }
679
680 return (Notify_value) FALSE;
681}
682
683Notify_value wx_sock_write_xview (Notify_client client, int fd)
684{
685 wxSocketBase *sock = (wxSocketBase *)client;
686
687 if (!sock->IsConnected())
688 sock->OnRequest(wxSocketBase::EVT_CONNECT);
689 else
690 sock->OnRequest(wxSocketBase::EVT_WRITE);
691
692 return (Notify_value) TRUE;
693}
694#endif
695
696wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt)
697{
698 switch (evt) {
699 case EVT_READ:
700 return REQ_READ;
701 case EVT_PEEK:
702 return REQ_PEEK;
703 case EVT_WRITE:
704 return REQ_WRITE;
705 case EVT_LOST:
706 return REQ_LOST;
707 case EVT_ACCEPT:
708 return REQ_ACCEPT;
709 case EVT_CONNECT:
710 return REQ_CONNECT;
711 }
712 return 0;
713}
714
715void wxSocketBase::SetFlags(wxSockFlags _flags)
716{
717 m_flags = _flags;
718 if (_flags & SPEED) {
719 unsigned long flag = 0;
720 ioctl(m_fd, FIONBIO, &flag);
721
722 // SPEED and WAITALL are antagonists.
723 m_flags = (wxSockFlags)(m_flags & ~WAITALL);
724
725 Notify(FALSE);
726 } else {
727 unsigned long flag = 1;
728 ioctl(m_fd, FIONBIO, &flag);
729 }
730}
731
732void wxSocketBase::SetNotify(wxRequestNotify flags)
733{
734 wxRequestNotify old_needed_req = m_neededreq;
735 if (flags & REQ_ACCEPT) {
736 /* Check if server */
737 if (!(GetClassInfo()->IsKindOf(CLASSINFO(wxSocketServer))))
738 flags &= ~REQ_ACCEPT;
739 }
740 m_neededreq = flags;
741 if (m_cbkon && old_needed_req != flags)
742 SetupCallbacks();
743}
744
745void wxSocketBase::SetupCallbacks()
746{
747 if (m_fd == INVALID_SOCKET || !m_handler || (m_flags & SPEED))
748 return;
749
750#if defined(__WXMOTIF__) || defined(__WXXT__) || defined(__WXGTK__)
751 if (m_cbkon)
752 DestroyCallbacks();
753 if (m_neededreq & (REQ_ACCEPT | REQ_READ | REQ_LOST)) {
754#ifdef __WXGTK__
755 m_internal->sock_inputid = gdk_input_add(m_fd, GDK_INPUT_READ,
756 wx_socket_read, (gpointer)this);
757#else
758 m_internal->sock_inputid = XtAppAddInput (wxAPP_CONTEXT, m_fd,
759 (XtPointer *) XtInputReadMask,
760 (XtInputCallbackProc) wx_socket_read,
761 (XtPointer) this);
762#endif
763 }
764 if (m_neededreq & (REQ_CONNECT | REQ_WRITE)) {
765#ifdef __WXGTK__
766 m_internal->sock_inputid = gdk_input_add(m_fd, GDK_INPUT_WRITE,
767 wx_socket_write, (gpointer)this);
768#else
769 m_internal->sock_outputid = XtAppAddInput (wxAPP_CONTEXT, m_fd,
770 (XtPointer *) XtInputWriteMask,
771 (XtInputCallbackProc) wx_socket_write,
772 (XtPointer) this);
773#endif
774 }
775#endif
776#ifdef __WINDOWS__
777 WORD mask = 0;
778
779 if (m_neededreq & REQ_READ)
780 mask |= FD_READ;
781 if (m_neededreq & REQ_WRITE)
782 mask |= FD_WRITE;
783 if (m_neededreq & REQ_LOST)
784 mask |= FD_CLOSE;
785 if (m_neededreq & REQ_ACCEPT)
786 mask |= FD_ACCEPT;
787 if (m_neededreq & REQ_CONNECT)
788 mask |= FD_CONNECT;
789
790 if (!m_internal->my_msg)
791 m_internal->my_msg = m_handler->NewMessage(this);
792 WSAAsyncSelect(m_fd, m_handler->GetHWND(), m_internal->my_msg, mask);
793#endif
794 m_cbkon = TRUE;
795 m_processing = FALSE;
796}
797
798void wxSocketBase::DestroyCallbacks()
799{
800 if (!m_cbkon || !m_handler)
801 return;
802 m_cbkon = FALSE;
803 m_processing = FALSE;
804#if defined(__WXMOTIF__) || defined(__WXXT__)
805 if (m_internal->sock_inputid > 0)
806 XtRemoveInput(m_internal->sock_inputid);
807 m_internal->sock_inputid = 0;
808 if (m_internal->sock_outputid > 0)
809 XtRemoveInput(m_internal->sock_outputid);
810 m_internal->sock_outputid = 0;
811#endif
812#ifdef __WXGTK__
813 if (m_internal->sock_inputid > 0)
814 gdk_input_remove(m_internal->sock_inputid);
815 m_internal->sock_inputid = 0;
816 if (m_internal->sock_outputid > 0)
817 gdk_input_remove(m_internal->sock_outputid);
818 m_internal->sock_outputid = 0;
819#endif
820#ifdef __WINDOWS__
821 WSAAsyncSelect(m_fd, m_handler->GetHWND(), 0, 0);
822#endif
823}
824
825void wxSocketBase::Notify(bool notify)
826{
827 if (m_notifyme == notify)
828 return;
829 if (notify)
830 SetupCallbacks();
831 else
832 DestroyCallbacks();
833 m_notifyme = notify;
834}
835
836void wxSocketBase::OnRequest(wxRequestEvent req_evt)
837{
838 wxRequestNotify req_notif = EventToNotify(req_evt);
839
840 // Mask the current event
841 SetNotify(m_neededreq & ~req_notif);
842
843 if (req_evt <= EVT_WRITE && DoRequests(req_evt))
844 return;
845
846 if (m_waitflags & 0xF0) {
847 // Wake up
848 if ((m_waitflags & 0x0F) == req_evt) {
849 m_waitflags = 0x80;
850#ifndef __WXGTK__
851 DestroyCallbacks(); // I disable it to prevent infinite loop on X11.
852#endif
853 }
854 return;
855 }
856
857 if (req_evt == EVT_LOST) {
858 m_connected = FALSE;
859 Close();
860 }
861 if (m_notifyme)
862 OldOnNotify(req_evt);
863
864 // Unmask
865 SetNotify(m_neededreq | req_notif);
866}
867
868wxSocketEvent::wxSocketEvent(int id)
869 : wxEvent(id)
870{
871 wxEventType type = (wxEventType)wxEVT_SOCKET;
872
873 SetEventType(type);
874}
875
876void wxSocketBase::OldOnNotify(wxRequestEvent evt)
877{
878 wxSocketEvent event(m_id);
879
880 event.SetEventObject(this);
881 event.m_skevt = evt;
882 ProcessEvent(event);
883
884 if (m_cbk)
885 m_cbk(*this, evt, m_cdata);
886}
887
888// --------------------------------------------------------------
889// --------- wxSocketBase functions [Callback, CallbackData] ----
890// --------------------------------------------------------------
891wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSocketBase::wxSockCbk _cbk)
892{
893 wxSockCbk old_cbk = m_cbk;
894
895 m_cbk = _cbk;
896 return old_cbk;
897}
898
899char *wxSocketBase::CallbackData(char *cdata_)
900{
901 char *old_cdata = m_cdata;
902
903 m_cdata = cdata_;
904 return old_cdata;
905}
906
907void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
908{
909 SetNextHandler(&h_evt);
910 m_id = id;
911}
912
913// --------------------------------------------------------------
914// --------- wxSocketBase pushback library ----------------------
915// --------------------------------------------------------------
916void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t size)
917{
918 char *curr_pos;
919
920 m_unread = (char *) realloc(m_unread, m_unrd_size+size);
921 curr_pos = m_unread + m_unrd_size;
922
923 memcpy(curr_pos, buffer, size);
924 m_unrd_size += size;
925}
926
927void wxSocketBase::CreatePushbackBefore(const char *buffer, size_t size)
928{
929 char *curr_pos, *new_buf;
930
931 new_buf = (char *) malloc(m_unrd_size+size);
932 curr_pos = new_buf + size;
933
934 memcpy(new_buf, buffer, size);
935 memcpy(curr_pos, m_unread, m_unrd_size);
936
937 free(m_unread);
938 m_unread = new_buf;
939 m_unrd_size += size;
940}
941
942size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek)
943{
944 if (!m_unrd_size)
945 return 0;
946
947 if (size > m_unrd_size)
948 size = m_unrd_size;
949 memcpy(buffer, m_unread, size);
950
951 if (!peek) {
952 m_unrd_size -= size;
953 if (!m_unrd_size) {
954 free(m_unread);
955 m_unread = NULL;
956 }
957 }
958
959 return size;
960}
961
962// --------------------------------------------------------------
963// --------- wxSocketBase "multi-thread" core -------------------
964// --------------------------------------------------------------
965
966bool wxSocketBase::DoRequests(wxRequestEvent req_flag)
967{
968 wxNode *node = req_list[req_flag].First();
969 size_t len;
970 int ret;
971
972 if (!node)
973 return FALSE;
974
975 SockRequest *req = (SockRequest *)node->Data();
976
977 delete node;
978
979 switch (req->type) {
980 case EVT_READ:
981 case EVT_PEEK:
982 ret = recv(m_fd, req->buffer, req->size,
983 (req->type == EVT_PEEK) ? MSG_PEEK : 0);
984 if (ret < 0) {
985 req->error = errno;
986 req->done = TRUE;
987 break;
988 }
989 len = ret;
990 if ((len < req->size) && (m_flags & WAITALL)) {
991 req->size -= len;
992 req->nbytes += len;
993 req->buffer += len;
994 req->auto_wakeup->Start(m_timeout*1000, TRUE);
995 req_list[req_flag].Insert(req);
996 break;
997 }
998 req->done = TRUE;
999 req->nbytes += len;
1000#ifndef __WXGTK__
1001 DestroyCallbacks();
1002#endif
1003 break;
1004 case EVT_WRITE:
1005 ret = send(m_fd, req->buffer, req->size, 0);
1006 if (ret < 0) {
1007 req->error = errno;
1008 req->done = TRUE;
1009 break;
1010 }
1011 len = ret;
1012 if ((len < req->size) && (m_flags & WAITALL)) {
1013 req->size -= len;
1014 req->nbytes += len;
1015 req->buffer += len;
1016 req->auto_wakeup->Start(m_timeout*1000, TRUE);
1017 req_list[req_flag].Insert(req);
1018 break;
1019 }
1020 req->done = TRUE;
1021 req->nbytes += len;
1022#ifndef __WXGTK__
1023 DestroyCallbacks();
1024#endif
1025 break;
1026 default:
1027 return FALSE;
1028 }
1029 return TRUE;
1030}
1031
1032void wxSocketBase::WantSpeedBuffer(char *buffer, size_t nbytes,
1033 wxRequestEvent evt)
1034{
e22036dc 1035 int ret = 0;
f4ada568
GL
1036
1037 switch (evt) {
1038 case EVT_PEEK:
1039 case EVT_READ:
c740f496
GL
1040 ret = recv(m_fd, buffer, nbytes,
1041 (evt == EVT_PEEK) ? MSG_PEEK : 0);
f4ada568
GL
1042 break;
1043 case EVT_WRITE:
c740f496 1044 ret = send(m_fd, buffer, nbytes, 0);
f4ada568
GL
1045 break;
1046 }
1047 if (ret < 0) {
1048 m_lcount = 0;
1049 m_error = errno;
8ef6a930 1050 } else {
f4ada568 1051 m_lcount = ret;
8ef6a930
GL
1052 m_error = 0;
1053 }
f4ada568
GL
1054}
1055
1056void wxSocketBase::WantBuffer(char *buffer, size_t nbytes,
1057 wxRequestEvent evt)
1058{
1059 bool buf_timed_out;
1060
1061 if (m_fd == INVALID_SOCKET || !m_handler || !m_connected)
1062 return;
1063
1064 if (m_flags & SPEED) {
1065 WantSpeedBuffer(buffer, nbytes, evt);
1066 return;
1067 }
1068
1069 SockRequest *buf = new SockRequest;
1070 wxSockWakeUp s_wake(NULL, (int *)&buf_timed_out, (int)TRUE);
384b4373 1071
f4ada568
GL
1072 m_wantbuf++;
1073 req_list[evt].Append(buf);
1074
1075 SaveState();
1076 SetNotify(REQ_LOST | EventToNotify(evt));
1077 SetupCallbacks();
1078 buf->buffer = buffer;
1079 buf->size = nbytes;
1080 buf->done = FALSE;
1081 buf->type = evt;
1082 buf->nbytes = 0;
1083 buf->auto_wakeup = &s_wake;
1084 buf->error = 0;
1085 buf_timed_out = FALSE;
1086
1087 s_wake.Start(m_timeout*1000, TRUE);
1088 if (m_flags & NOWAIT) {
1089 DoRequests(evt);
1090 } else {
1091 while (!buf->done && !buf_timed_out)
1092 PROCESS_EVENTS();
1093 }
1094 m_wantbuf--;
1095 m_lcount = buf->nbytes;
1096 if (buf_timed_out)
1097 m_error = ETIMEDOUT;
1098 else
1099 m_error = buf->error;
1100
1101 delete buf;
1102 RestoreState();
1103}
1104
1105// --------------------------------------------------------------
1106// wxSocketServer ///////////////////////////////////////////////
1107// --------------------------------------------------------------
1108
1109// --------------------------------------------------------------
1110// --------- wxSocketServer CONSTRUCTOR -------------------------
1111// --------------------------------------------------------------
1112wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
1113 wxSockFlags flags) :
1114 wxSocketBase(flags, SOCK_SERVER)
1115{
1116 m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0);
1117
1118 if (m_fd == INVALID_SOCKET)
1119 return;
384b4373 1120
f4ada568
GL
1121 int flag = 1;
1122 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(int));
384b4373 1123
f4ada568
GL
1124 struct sockaddr *myaddr;
1125 size_t len;
384b4373 1126
f4ada568
GL
1127 addr_man.Build(myaddr, len);
1128 if (bind(m_fd, myaddr, addr_man.SockAddrLen()) < 0)
1129 return;
384b4373 1130
f4ada568
GL
1131 if (listen(m_fd, 5) < 0) {
1132 m_fd = INVALID_SOCKET;
1133 return;
1134 }
1135}
1136
1137// --------------------------------------------------------------
1138// --------- wxSocketServer Accept ------------------------------
1139// --------------------------------------------------------------
1140bool wxSocketServer::AcceptWith(wxSocketBase& sock)
1141{
1142 int fd2;
384b4373 1143
f4ada568
GL
1144 if ((fd2 = accept(m_fd, 0, 0)) < 0)
1145 return FALSE;
1146
1147 struct linger linger;
1148 linger.l_onoff = 0;
1149 linger.l_linger = 1;
384b4373 1150
f4ada568 1151 setsockopt(fd2, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
384b4373 1152
f4ada568
GL
1153 int flag = 0;
1154 setsockopt(fd2, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int));
384b4373 1155
f4ada568
GL
1156 if (!(sock.m_flags & SPEED)) {
1157 unsigned long flag2 = 1;
1158 ioctl(fd2, FIONBIO, &flag2);
1159 }
384b4373 1160
f4ada568
GL
1161 sock.m_type = SOCK_INTERNAL;
1162 sock.m_fd = fd2;
1163 sock.m_connected = TRUE;
1164
1165 return TRUE;
1166}
1167
1168wxSocketBase *wxSocketServer::Accept()
1169{
1170 wxSocketBase* sock = new wxSocketBase();
1171
1172 sock->SetFlags((wxSockFlags)m_flags);
1173
1174 if (!AcceptWith(*sock))
1175 return NULL;
1176
1177 if (m_handler)
1178 m_handler->Register(sock);
1179
1180 return sock;
1181}
1182
1183// --------------------------------------------------------------
1184// --------- wxSocketServer callbacks ---------------------------
1185// --------------------------------------------------------------
1186void wxSocketServer::OnRequest(wxRequestEvent evt)
1187{
1188 if (evt == EVT_ACCEPT) {
1189 OldOnNotify(EVT_ACCEPT);
1190 }
1191}
1192
1193// --------------------------------------------------------------
1194// wxSocketClient ///////////////////////////////////////////////
1195// --------------------------------------------------------------
1196
1197// --------- wxSocketClient CONSTRUCTOR -------------------------
1198// --------------------------------------------------------------
1199wxSocketClient::wxSocketClient(wxSockFlags _flags) :
1200 wxSocketBase(_flags, SOCK_CLIENT)
1201{
1202}
1203
1204// --------------------------------------------------------------
1205// --------- wxSocketClient DESTRUCTOR --------------------------
1206// --------------------------------------------------------------
1207wxSocketClient::~wxSocketClient()
1208{
1209}
1210
1211// --------------------------------------------------------------
1212// --------- wxSocketClient Connect functions -------------------
1213// --------------------------------------------------------------
e22036dc 1214bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) )
f4ada568
GL
1215{
1216 struct linger linger;
1217
1218 if (IsConnected())
1219 Close();
1220
1221 m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0);
384b4373 1222
f4ada568
GL
1223 if (m_fd < 0)
1224 return FALSE;
384b4373 1225
f4ada568
GL
1226 m_connected = FALSE;
1227
1228 linger.l_onoff = 1;
384b4373 1229 linger.l_linger = 5;
f4ada568 1230 setsockopt(m_fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
384b4373 1231
f4ada568 1232 // Stay in touch with the state of things...
384b4373 1233
f4ada568
GL
1234 unsigned long flag = 1;
1235 setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int));
384b4373 1236
f4ada568
GL
1237 // Disable the nagle algorithm, which delays sends till the
1238 // buffer is full (or a certain time period has passed?)...
1239
1240#if defined(__WINDOWS__) || (defined(IPPROTO_TCP) && defined(TCP_NODELAY))
1241 flag = 1;
1242 setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
1243#endif
384b4373 1244
f4ada568
GL
1245 struct sockaddr *remote;
1246 size_t len;
1247
1248 addr_man.Build(remote, len);
1249
1250 if (connect(m_fd, remote, len) != 0)
1251 return FALSE;
1252
1253 if (!(m_flags & SPEED)) {
1254 flag = 1;
1255 ioctl(m_fd, FIONBIO, &flag);
1256 }
384b4373 1257
f4ada568
GL
1258 Notify(TRUE);
1259
1260 m_connected = TRUE;
1261 return TRUE;
1262}
1263
75ed1d15 1264bool wxSocketClient::WaitOnConnect(long seconds, long microseconds)
f4ada568 1265{
75ed1d15 1266 int ret = _Wait(seconds, microseconds, REQ_CONNECT | REQ_LOST);
384b4373 1267
f4ada568
GL
1268 if (ret)
1269 m_connected = TRUE;
384b4373
RD
1270
1271 return m_connected;
f4ada568
GL
1272}
1273
1274void wxSocketClient::OnRequest(wxRequestEvent evt)
1275{
1276 if (evt == EVT_CONNECT) {
1277 if (m_connected) {
1278 SetNotify(m_neededreq & ~REQ_CONNECT);
1279 return;
1280 }
1281 m_waitflags = 0x40;
384b4373 1282 m_connected = TRUE;
f4ada568
GL
1283 OldOnNotify(EVT_CONNECT);
1284 DestroyCallbacks();
1285 return;
1286 }
1287 wxSocketBase::OnRequest(evt);
1288}
1289
1290/////////////////////////////////////////////////////////////////
1291// wxSocketHandler ///////////////////////////////////////////////
1292/////////////////////////////////////////////////////////////////
1293
1294wxSocketHandler *wxSocketHandler::master = NULL;
1295#if defined(__WINDOWS__)
1296static int win_initialized = 0;
1297#endif
1298
1299// --------------------------------------------------------------
1300// --------- wxSocketHandler CONSTRUCTOR ------------------------
1301// --------------------------------------------------------------
1302#ifdef __WINDOWS__
1303
1304extern char wxPanelClassName[];
1305
1306LRESULT APIENTRY _EXPORT wxSocketHandlerWndProc(HWND hWnd, UINT message,
1307 WPARAM wParam, LPARAM lParam)
1308{
1cff61de
UU
1309 if(message==WM_DESTROY)
1310 {
1311 ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG) DefWindowProc);
1312 return DefWindowProc(hWnd, message, wParam, lParam);
1313 }
f4ada568
GL
1314 wxSocketHandler *h_sock = (wxSocketHandler *)GetWindowLong(hWnd, GWL_USERDATA);
1315 wxNode *node = h_sock->smsg_list->Find(message);
1316 wxSocketBase *sock;
1317 wxSocketBase::wxRequestEvent sk_req;
1318 UINT event = WSAGETSELECTEVENT(lParam);
1319
1320 if (!node)
1321 return DefWindowProc(hWnd, message, wParam, lParam);
1322
1323 sock = (wxSocketBase *)node->Data();
1324
1325 switch (event) {
1326 case FD_READ:
1327 sk_req = wxSocketBase::EVT_READ;
1328 break;
1329 case FD_WRITE:
1330 sk_req = wxSocketBase::EVT_WRITE;
1331 break;
1332 case FD_CLOSE:
1333 sk_req = wxSocketBase::EVT_LOST;
1334 break;
1335 case FD_ACCEPT:
1336 sk_req = wxSocketBase::EVT_ACCEPT;
1337 break;
1338 case FD_CONNECT:
1339 sk_req = wxSocketBase::EVT_CONNECT;
1340 break;
1341 }
1342 sock->OnRequest(sk_req);
1343
1344 return (LRESULT)0;
1345}
1346
1347FARPROC wxSocketSubClassProc = NULL;
1348
1349#endif
1350
1351wxSocketHandler::wxSocketHandler()
1352{
1353#if defined(__WINDOWS__)
1354 if (!win_initialized) {
1355 WSADATA wsaData;
1356
1357 WSAStartup((1 << 8) | 1, &wsaData);
1358 win_initialized = 1;
1359 }
1360 internal = new wxSockHandlerInternal;
1361 internal->sockWin = ::CreateWindow(wxPanelClassName, NULL, 0,
1362 0, 0, 0, 0, NULL, (HMENU) NULL,
1363 wxhInstance, 0);
1364
1365 // Subclass the window
1366 if (!wxSocketSubClassProc)
1367 wxSocketSubClassProc = MakeProcInstance((FARPROC) wxSocketHandlerWndProc, wxhInstance);
1368 ::SetWindowLong(internal->sockWin, GWL_WNDPROC, (LONG) wxSocketSubClassProc);
1369 ::SetWindowLong(internal->sockWin, GWL_USERDATA, (LONG) this);
1370
1371 internal->firstAvailableMsg = 5000;
1372 smsg_list = new wxList(wxKEY_INTEGER);
1373#endif
1374
1375 socks = new wxList;
1376
1377#ifndef __WINDOWS__
1378 signal(SIGPIPE, SIG_IGN);
1379#endif
1380}
1381
1382// --------------------------------------------------------------
1383// --------- wxSocketHandler DESTRUCTOR -------------------------
1384// --------------------------------------------------------------
1385wxSocketHandler::~wxSocketHandler()
1386{
1387 wxNode *next_node, *node = socks->First();
1388
1389 while (node) {
1390 wxSocketBase* sock = (wxSocketBase*)node->Data();
1391
1392 delete sock;
1393 next_node = node->Next();
1394 delete node;
1395 node = next_node;
1396 }
1397
1398 delete socks;
1399
1400#ifdef __WINDOWS__
1401 delete smsg_list;
1402
1403 ::DestroyWindow(internal->sockWin);
1404 WSACleanup();
1405 win_initialized = 0;
1406
1407 delete internal;
1408#endif
1409}
1410
1411// --------------------------------------------------------------
1412// --------- wxSocketHandler registering functions --------------
1413// --------------------------------------------------------------
1414void wxSocketHandler::Register(wxSocketBase* sock)
1415{
1416 wxNode *node;
1417
1418 for (node = socks->First(); node != NULL; node = node->Next()) {
1419 wxSocketBase* s = (wxSocketBase*)node->Data();
1420
1421 if (s == sock)
1422 return;
1423 }
1424
1425 if (sock) {
1426 socks->Append(sock);
1427 sock->SetHandler(this);
1428 sock->SetupCallbacks();
1429 }
1430}
1431
1432void wxSocketHandler::UnRegister(wxSocketBase* sock)
1433{
1434 wxNode *node;
1435
1436 for (node = socks->First(); node; node = node->Next()) {
1437 wxSocketBase* s = (wxSocketBase*)node->Data();
384b4373 1438
f4ada568
GL
1439 if (s == sock) {
1440 delete node;
1441 sock->DestroyCallbacks();
1442 sock->SetHandler(NULL);
1443 return;
1444 }
1445 }
1446}
1447
1448unsigned long wxSocketHandler::Count() const
1449{
1450 return socks->Number();
1451}
1452
1453// --------------------------------------------------------------
1454// --------- wxSocketHandler "big" wait functions ---------------
1455// --------------------------------------------------------------
1456void handler_cbk(wxSocketBase& sock,
1457 wxSocketBase::wxRequestEvent WXUNUSED(flags),
1458 char *cdata)
1459{
1460 int *a_wait = (int *)cdata;
1461
1462 (*a_wait)++;
1463 sock.Notify(FALSE);
1464}
1465
1466int wxSocketHandler::Wait(long seconds, long microseconds)
1467{
1468 int i;
1469 int on_wait;
1470 wxSockWakeUp s_wake(NULL, &on_wait, -2);
1471 wxNode *node;
1472
1473 for (node = socks->First(), i=0; node; node = node->Next(), i++) {
1474 wxSocketBase *sock = (wxSocketBase *)node->Data();
1475
1476 sock->SaveState();
1477
1478 sock->SetupCallbacks();
1479
1480 sock->Callback(handler_cbk);
1481 sock->CallbackData((char *)&on_wait);
1482 }
1483 on_wait = 0;
1484 if (seconds != -1)
1485 s_wake.Start((seconds*1000) + (microseconds/1000), TRUE);
1486
1487 while (!on_wait)
1488 PROCESS_EVENTS();
1489
1490 for (node = socks->First(), i=0; node; node = node->Next(), i++) {
1491 wxSocketBase *sock = (wxSocketBase *)node->Data();
1492
1493 sock->RestoreState();
1494 }
1495
1496 if (on_wait == -2)
1497 return 0;
1498
1499 return on_wait;
1500}
1501
1502void wxSocketHandler::YieldSock()
1503{
1504 wxNode *node;
1505
1506 for (node = socks->First(); node; node = node->Next() ) {
1507 wxSocketBase *sock = (wxSocketBase *)node->Data();
1508
1509 sock->SaveState();
1510
1511 sock->SetFlags(wxSocketBase::SPEED);
1512 if (sock->IsData())
1513 sock->DoRequests(wxSocketBase::EVT_READ);
1514 sock->DoRequests(wxSocketBase::EVT_WRITE);
1515
1516 sock->RestoreState();
1517 }
1518}
1519
1520// --------------------------------------------------------------
1521// --------- wxSocketHandler: create and register the socket ----
1522// --------------------------------------------------------------
1523wxSocketServer *wxSocketHandler::CreateServer(wxSockAddress& addr,
1524 wxSocketBase::wxSockFlags flags)
1525{
1526 wxSocketServer *serv = new wxSocketServer(addr, flags);
1527
1528 Register(serv);
1529 return serv;
1530}
1531
1532wxSocketClient *wxSocketHandler::CreateClient(wxSocketBase::wxSockFlags flags)
1533{
1534 wxSocketClient *client = new wxSocketClient(flags);
1535
1536 Register(client);
1537 return client;
1538}
1539
1540#ifdef __WINDOWS__
1541// --------------------------------------------------------------
1542// --------- wxSocketHandler: Windows specific methods ----------
1543// --------------------------------------------------------------
1544UINT wxSocketHandler::NewMessage(wxSocketBase *sock)
1545{
1546 internal->firstAvailableMsg++;
1547 smsg_list->Append(internal->firstAvailableMsg, sock);
1548 return internal->firstAvailableMsg;
1549}
1550
1551void wxSocketHandler::DestroyMessage(UINT msg)
1552{
1553 wxNode *node = smsg_list->Find(msg);
1554 delete node;
1555}
1556
1557HWND wxSocketHandler::GetHWND() const
1558{
1559 return internal->sockWin;
1560}
1561
1562#endif
7f555861 1563
3b4183d8
GL
1564bool wxSocketModule::OnInit() {
1565 wxSocketHandler::master = new wxSocketHandler();
1566 return TRUE;
1567}
1568
1569void wxSocketModule::OnExit() {
1570 delete wxSocketHandler::master;
1571 wxSocketHandler::master = NULL;
1572}
1573
7f555861
JS
1574#endif
1575 // __WXSTUBS__