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