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