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