]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
1. wxDialogs are now destroyed when they go out of scope
[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
a737331d
GL
7// Updated: April 1999
8// Copyright: (C) 1999 1998, 1997, Guilhem Lavaux
f4ada568
GL
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
55021f25
VZ
38// IRIX requires bstring.h be included to use select()
39#ifdef sgi
40 #include <bstring.h>
41#endif // IRIX
42
7f555861
JS
43// Not enough OS behaviour defined for wxStubs
44#ifndef __WXSTUBS__
45
f4ada568
GL
46#include <stdlib.h>
47#include <string.h>
48#include <ctype.h>
49
50/////////////////////////////////////////////////////////////////////////////
51// System specific headers
52/////////////////////////////////////////////////////////////////////////////
17dff81c
SC
53#ifdef __WXMAC__
54// in order to avoid problems with our c library and double definitions
55#define close closesocket
56#define ioctl ioctlsocket
57
58#include <wx/mac/macsock.h>
a737331d 59
17dff81c
SC
60#endif
61
f4ada568 62#if defined(__WINDOWS__)
a737331d 63#include <winsock.h>
f4ada568
GL
64#endif // __WINDOWS__
65
66#if defined(__UNIX__)
67
68#ifdef VMS
a737331d
GL
69#include <socket.h>
70#else
71#include <sys/socket.h>
72#endif
f4ada568
GL
73#include <sys/ioctl.h>
74
75#include <sys/time.h>
76#include <unistd.h>
77
384b4373 78#ifdef sun
a737331d 79#include <sys/filio.h>
384b4373
RD
80#endif
81
f4ada568
GL
82#endif // __UNIX__
83
84#include <signal.h>
85#include <errno.h>
86
3f4a0c5b 87#ifdef __VISUALC__
a737331d 88#include <io.h>
f4ada568
GL
89#endif
90
91/////////////////////////////////////////////////////////////////////////////
92// wxSocket headers
93/////////////////////////////////////////////////////////////////////////////
a737331d 94#include <wx/module.h>
f4ada568 95#define WXSOCK_INTERNAL
a737331d
GL
96#include <wx/sckaddr.h>
97#include <wx/socket.h>
98#include <wx/sckint.h>
57493f9f 99
a737331d
GL
100// ----------------------
101// Some patch ----- BEGIN
102// ----------------------
f4ada568
GL
103#ifdef __WINDOWS__
104#define close closesocket
105#define ioctl ioctlsocket
0c32066b
JS
106#ifdef errno
107#undef errno
108#endif
f4ada568
GL
109#define errno WSAGetLastError()
110#ifdef EWOULDBLOCK
111#undef EWOULDBLOCK
112#endif
113#define EWOULDBLOCK WSAEWOULDBLOCK
114#define ETIMEDOUT WSAETIMEDOUT
115#undef EINTR
116#define EINTR WSAEINTR
117#endif
118
119#ifndef __WINDOWS__
120#define INVALID_SOCKET -1
121#endif
122
f4ada568
GL
123#ifdef __WINDOWS__
124// This is an MS TCP/IP routine and is not needed here. Some WinSock
125// implementations (such as PC-NFS) will require you to include this
126// or a similar routine (see appendix in WinSock doc or help file).
127
3f4a0c5b 128#if defined( NEED_WSAFDIsSet ) || defined( __VISUALC__ )
f4ada568
GL
129int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set)
130{
17dff81c 131 int i = set->fd_count;
f4ada568 132
17dff81c
SC
133 while (i--)
134 {
135 if (set->fd_array[i] == fd)
136 return 1;
137 }
f4ada568 138
17dff81c 139 return 0;
f4ada568
GL
140}
141#endif
142#endif
143
a737331d
GL
144// -------------------
145// Some patch ---- END
146// -------------------
f4ada568 147
ce3ed50d
JS
148#ifdef GetClassInfo
149#undef GetClassInfo
150#endif
151
3b4183d8
GL
152// --------------------------------------------------------------
153// Module
154// --------------------------------------------------------------
db131261
RR
155class wxSocketModule: public wxModule
156{
3b4183d8
GL
157 DECLARE_DYNAMIC_CLASS(wxSocketModule)
158public:
159 wxSocketModule() {}
160 bool OnInit();
161 void OnExit();
162};
163
f4ada568
GL
164// --------------------------------------------------------------
165// ClassInfos
166// --------------------------------------------------------------
167#if !USE_SHARED_LIBRARY
a737331d
GL
168IMPLEMENT_CLASS(wxSocketBase, wxObject)
169IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
170IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
171IMPLEMENT_CLASS(wxSocketHandler, wxObject)
172IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
173IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
f4ada568
GL
174#endif
175
f4ada568
GL
176// --------------------------------------------------------------
177// --------- wxSocketBase CONSTRUCTOR ---------------------------
178// --------------------------------------------------------------
179wxSocketBase::wxSocketBase(wxSocketBase::wxSockFlags _flags,
17dff81c 180 wxSocketBase::wxSockType _type) :
f4ada568
GL
181 wxEvtHandler(),
182 m_flags(_flags), m_type(_type), m_connected(FALSE), m_connecting(FALSE),
a737331d 183 m_fd(INVALID_SOCKET), m_id(-1),
f4ada568
GL
184 m_handler(0),
185 m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)),
a737331d 186 m_timeout(3600),
f4ada568 187 m_unread(NULL), m_unrd_size(0),
a737331d
GL
188 m_cbk(NULL), m_cdata(NULL),
189 m_notify_state(FALSE)
f4ada568 190{
a737331d 191 m_internal = new wxSocketInternal(this);
f4ada568
GL
192}
193
194wxSocketBase::wxSocketBase() :
195 wxEvtHandler(),
196 m_flags(WAITALL), m_type(SOCK_UNINIT), m_connected(FALSE),
a737331d 197 m_connecting(FALSE), m_fd(INVALID_SOCKET),
f4ada568
GL
198 m_id(-1), m_handler(0),
199 m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)),
a737331d 200 m_timeout(3600),
f4ada568 201 m_unread(NULL), m_unrd_size(0),
a737331d
GL
202 m_cbk(NULL), m_cdata(NULL),
203 m_notify_state(FALSE)
f4ada568 204{
a737331d 205 m_internal = new wxSocketInternal(this);
f4ada568
GL
206}
207
208// --------------------------------------------------------------
8c14576d 209// wxSocketBase
f4ada568 210// --------------------------------------------------------------
8c14576d 211
f4ada568
GL
212wxSocketBase::~wxSocketBase()
213{
a737331d 214 // First, close the file descriptor.
f4ada568
GL
215 Close();
216
217 if (m_unread)
218 free(m_unread);
a737331d 219 // Unregister from the handler database.
8c14576d 220 if (m_handler)
f4ada568 221 m_handler->UnRegister(this);
a737331d
GL
222
223 // Destroy all saved states.
f4ada568
GL
224 m_states.DeleteContents(TRUE);
225
a737331d 226 // Destroy the socket manager.
f4ada568
GL
227 delete m_internal;
228}
229
230bool wxSocketBase::Close()
231{
8c14576d
RR
232 if (m_fd != INVALID_SOCKET)
233 {
2a4f27f2
GL
234 if (m_notify_state == TRUE)
235 Notify(FALSE);
f4ada568 236
a737331d 237 // Shutdown the connection.
f4ada568
GL
238 shutdown(m_fd, 2);
239 close(m_fd);
240 m_fd = INVALID_SOCKET;
241 m_connected = FALSE;
242 }
243
244 return TRUE;
245}
246
247// --------------------------------------------------------------
8c14576d 248// wxSocketBase base IO function
f4ada568 249// --------------------------------------------------------------
8c14576d 250
f4ada568
GL
251wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes)
252{
a737331d
GL
253 m_lcount = GetPushback(buffer, nbytes, FALSE);
254 nbytes -= m_lcount;
255 buffer += m_lcount;
f4ada568
GL
256
257 // If we have got the whole needed buffer or if we don't want to
258 // wait then it returns immediately.
a737331d 259 if (!nbytes || (m_lcount && !(m_flags & WAITALL)) ) {
f4ada568 260 return *this;
375abe3d 261 }
f4ada568
GL
262
263 WantBuffer(buffer, nbytes, EVT_READ);
264
265 return *this;
266}
267
062c4861
GL
268wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes)
269{
270 unsigned long len, len2, sig;
271 struct {
272 char sig[4];
273 char len[4];
274 } msg;
275
276 // sig should be an explicit 32-bit unsigned integer; I've seen
277 // compilers in which size_t was actually a 16-bit unsigned integer
278
279 Read((char *)&msg, sizeof(msg));
280 if (m_lcount != sizeof(msg))
281 return *this;
282
283 sig = msg.sig[0] & 0xff;
284 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
285 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
286 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
287
288 if (sig != 0xfeeddead)
289 return *this;
290 len = msg.len[0] & 0xff;
291 len |= (size_t)(msg.len[1] & 0xff) << 8;
292 len |= (size_t)(msg.len[2] & 0xff) << 16;
293 len |= (size_t)(msg.len[3] & 0xff) << 24;
294
295 // len2 is incorrectly computed in the original; this sequence is
296 // the fix
297 if (len > nbytes) {
298 len2 = len - nbytes;
299 len = nbytes;
300 }
301 else
302 len2 = 0;
303
304 // the "len &&" in the following statement is necessary so that
305 // we don't attempt to read (and possibly hang the system)
306 // if the message was zero bytes long
307 if (len && Read(buffer, len).LastCount() != len)
308 return *this;
309 if (len2 && (Read(NULL, len2).LastCount() != len2))
310 return *this;
311 if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg))
312 return *this;
313
314 sig = msg.sig[0] & 0xff;
315 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
316 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
317 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
318// ERROR
319// we return *this either way, so a smart optimizer will
320// optimize the following sequence out; I'm leaving it in anyway
321 if (sig != 0xdeadfeed)
322 return *this;
323
324 return *this;
325}
326
f4ada568
GL
327wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes)
328{
a737331d
GL
329 m_lcount = GetPushback(buffer, nbytes, TRUE);
330 if (nbytes-m_lcount == 0)
8c14576d 331 {
f4ada568
GL
332 return *this;
333 }
a737331d
GL
334 buffer += m_lcount;
335 nbytes -= m_lcount;
f4ada568
GL
336
337 WantBuffer(buffer, nbytes, EVT_PEEK);
338
339 return *this;
340}
341
342wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes)
343{
a737331d 344 m_lcount = 0;
f4ada568
GL
345 WantBuffer((char *)buffer, nbytes, EVT_WRITE);
346 return *this;
347}
348
062c4861
GL
349wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes)
350{
351 struct {
352 char sig[4];
353 char len[4];
354 } msg;
355
356 // warning about 'cast truncates constant value'
357#ifdef __VISUALC__
358 #pragma warning(disable: 4310)
359#endif // __VISUALC__
360
361 msg.sig[0] = (char) 0xad;
362 msg.sig[1] = (char) 0xde;
363 msg.sig[2] = (char) 0xed;
364 msg.sig[3] = (char) 0xfe;
365
366 msg.len[0] = (char) nbytes & 0xff;
367 msg.len[1] = (char) (nbytes >> 8) & 0xff;
368 msg.len[2] = (char) (nbytes >> 16) & 0xff;
369 msg.len[3] = (char) (nbytes >> 24) & 0xff;
370
371 if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg))
372 return *this;
373 if (Write(buffer, nbytes).LastCount() < nbytes)
374 return *this;
375
376 msg.sig[0] = (char) 0xed;
377 msg.sig[1] = (char) 0xfe;
378 msg.sig[2] = (char) 0xad;
379 msg.sig[3] = (char) 0xde;
380 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
381 Write((char *)&msg, sizeof(msg));
382
383 return *this;
384
385#ifdef __VISUALC__
386 #pragma warning(default: 4310)
387#endif // __VISUALC__
388}
389
f4ada568
GL
390wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes)
391{
062c4861
GL
392 m_lcount = 0;
393 if (nbytes != 0) {
394 CreatePushbackAfter(buffer, nbytes);
395 m_lcount = nbytes;
396 }
f4ada568
GL
397 return *this;
398}
399
400bool wxSocketBase::IsData() const
401{
402 struct timeval tv;
403 fd_set sock_set;
404
405 if (m_fd < 0)
406 return FALSE;
407 if (m_unrd_size > 0)
408 return TRUE;
409
a737331d
GL
410 m_internal->AcquireFD();
411
f4ada568
GL
412 tv.tv_sec = 0;
413 tv.tv_usec = 0;
414 FD_ZERO(&sock_set);
415 FD_SET(m_fd, &sock_set);
062c4861 416 select(m_fd+1, &sock_set, NULL, NULL, &tv);
a737331d
GL
417
418 m_internal->ReleaseFD();
419
0c32066b 420 return (FD_ISSET(m_fd, &sock_set) != 0);
f4ada568
GL
421}
422
423// ---------------------------------------------------------------------
424// --------- wxSocketBase Discard(): deletes all byte in the input queue
425// ---------------------------------------------------------------------
426void wxSocketBase::Discard()
427{
428#define MAX_BUFSIZE (10*1024)
429 char *my_data = new char[MAX_BUFSIZE];
430 size_t recv_size = MAX_BUFSIZE;
431
432 SaveState();
433 SetFlags((wxSockFlags)(NOWAIT | SPEED));
384b4373 434
8c14576d
RR
435 while (recv_size == MAX_BUFSIZE)
436 {
f4ada568
GL
437 recv_size = Read(my_data, MAX_BUFSIZE).LastCount();
438 }
439
440 RestoreState();
441 delete [] my_data;
442
443#undef MAX_BUFSIZE
444}
445
a737331d
GL
446// If what? Who seems to need unsigned int?
447// BTW uint isn't even defined on wxMSW for VC++ for some reason. Even if it
448// were, getpeername/getsockname don't take unsigned int*, they take int*.
449//
450// Under glibc 2.0.7, socketbits.h declares socklen_t to be unsigned int
451// and it uses *socklen_t as the 3rd parameter. Robert.
452
453// JACS - How can we detect this?
454// Meanwhile, if your compiler complains about socklen_t,
455// switch lines below.
456
457#if wxHAVE_GLIBC2
458# define wxSOCKET_INT socklen_t
459#else
460# define wxSOCKET_INT int
461#endif
15ed4533 462
f4ada568 463// --------------------------------------------------------------
8c14576d 464// wxSocketBase socket info functions
f4ada568 465// --------------------------------------------------------------
8c14576d 466
f4ada568
GL
467bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
468{
469 struct sockaddr my_addr;
a737331d 470 wxSOCKET_INT len_addr = sizeof(my_addr);
f4ada568
GL
471
472 if (m_fd < 0)
473 return FALSE;
474
a737331d
GL
475 m_internal->AcquireFD();
476
477 if (getpeername(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) {
478 m_internal->ReleaseFD();
384b4373 479 return FALSE;
a737331d 480 }
f4ada568 481
a737331d 482 m_internal->ReleaseFD();
f4ada568
GL
483 addr_man.Disassemble(&my_addr, len_addr);
484 return TRUE;
485}
486
487bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
488{
489 struct sockaddr my_addr;
a737331d 490 wxSOCKET_INT len_addr = sizeof(my_addr);
f4ada568
GL
491
492 if (m_fd < 0)
493 return FALSE;
494
a737331d
GL
495 m_internal->AcquireFD();
496
497 if (getsockname(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) {
498 m_internal->ReleaseFD();
f4ada568 499 return FALSE;
a737331d
GL
500 }
501 m_internal->ReleaseFD();
f4ada568
GL
502
503 addr_man.Disassemble(&my_addr, len_addr);
504 return TRUE;
505}
506
507// --------------------------------------------------------------
8c14576d 508// wxSocketBase wait functions
f4ada568 509// --------------------------------------------------------------
db131261 510
f4ada568
GL
511void wxSocketBase::SaveState()
512{
a737331d 513 SocketState *state = new SocketState;
f4ada568 514
a737331d
GL
515 state->notify_state = m_notify_state;
516 state->evt_notify_state = m_neededreq;
517 state->socket_flags = m_flags;
518 state->c_callback = m_cbk;
519 state->c_callback_data = m_cdata;
f4ada568 520
a737331d 521 m_states.Append((wxObject *)state);
f4ada568
GL
522}
523
524void wxSocketBase::RestoreState()
525{
526 wxNode *node;
a737331d 527 SocketState *state;
f4ada568
GL
528
529 node = m_states.Last();
530 if (!node)
531 return;
532
a737331d 533 state = (SocketState *)node->Data();
384b4373 534
a737331d 535 SetFlags(state->socket_flags);
062c4861 536 m_internal->AcquireData();
a737331d 537 m_neededreq = state->evt_notify_state;
062c4861 538 m_internal->ReleaseData();
a737331d
GL
539 m_cbk = state->c_callback;
540 m_cdata = state->c_callback_data;
541 Notify(state->notify_state);
f4ada568
GL
542
543 delete node;
544 delete state;
545}
546
547// --------------------------------------------------------------
a737331d 548// --------- wxSocketBase callback functions --------------------
f4ada568 549// --------------------------------------------------------------
db131261 550
a737331d 551wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
f4ada568 552{
a737331d 553 wxSockCbk old_cbk = cbk_;
f4ada568 554
a737331d
GL
555 m_cbk = cbk_;
556 return old_cbk;
f4ada568
GL
557}
558
a737331d 559char *wxSocketBase::CallbackData(char *data)
f4ada568 560{
a737331d 561 char *old_data = m_cdata;
f4ada568 562
a737331d
GL
563 m_cdata = data;
564 return old_data;
f4ada568
GL
565}
566
567// --------------------------------------------------------------
a737331d 568// --------- wxSocketBase wait functions ------------------------
f4ada568
GL
569// --------------------------------------------------------------
570
a737331d 571bool wxSocketBase::_Wait(long seconds, long milliseconds, int type)
375abe3d 572{
a737331d 573 SockRequest *req;
375abe3d 574
a737331d
GL
575 if ((!m_connected && !m_connecting) || m_fd < 0)
576 return FALSE;
f4ada568 577
a737331d 578 req = new SockRequest;
f4ada568 579
a737331d
GL
580 req->type = REQ_WAIT | type;
581 req->timeout = seconds * 1000 + milliseconds;
582 req->done = FALSE;
583 req->buffer = NULL;
584 req->size = 0;
585 req->error = 0;
586 req->wait = TRUE;
587 m_internal->QueueRequest(req, TRUE);
f4ada568 588
a737331d 589 return (req->io_nbytes != 0);
f4ada568 590}
f4ada568 591
a737331d 592bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 593{
a737331d
GL
594 return _Wait(seconds, milliseconds, REQ_ACCEPT | REQ_CONNECT |
595 REQ_READ | REQ_WRITE | REQ_LOST);
f4ada568 596}
f4ada568 597
a737331d 598bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 599{
a737331d 600 return _Wait(seconds, milliseconds, REQ_READ | REQ_LOST);
f4ada568
GL
601}
602
a737331d 603bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 604{
a737331d
GL
605 return _Wait(seconds, milliseconds, REQ_WRITE);
606}
f4ada568 607
a737331d
GL
608bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
609{
610 return _Wait(seconds, milliseconds, REQ_LOST);
f4ada568 611}
a737331d
GL
612
613// --------------------------------------------------------------
614// --------- wxSocketBase callback management -------------------
615// --------------------------------------------------------------
f4ada568
GL
616
617wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt)
618{
db131261
RR
619 switch (evt)
620 {
f4ada568
GL
621 case EVT_READ:
622 return REQ_READ;
623 case EVT_PEEK:
624 return REQ_PEEK;
625 case EVT_WRITE:
626 return REQ_WRITE;
627 case EVT_LOST:
628 return REQ_LOST;
629 case EVT_ACCEPT:
630 return REQ_ACCEPT;
631 case EVT_CONNECT:
632 return REQ_CONNECT;
633 }
634 return 0;
635}
636
637void wxSocketBase::SetFlags(wxSockFlags _flags)
638{
639 m_flags = _flags;
a737331d 640 if (_flags & SPEED) {
f4ada568
GL
641 // SPEED and WAITALL are antagonists.
642 m_flags = (wxSockFlags)(m_flags & ~WAITALL);
f4ada568
GL
643 }
644}
645
a737331d 646wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const
f4ada568 647{
a737331d 648 return m_flags;
f4ada568
GL
649}
650
a737331d 651void wxSocketBase::SetNotify(wxRequestNotify flags)
f4ada568 652{
a737331d
GL
653 /* Check if server */
654 if (m_type != SOCK_SERVER)
655 flags &= ~REQ_ACCEPT;
f4ada568 656
48da7d0b 657 m_internal->AcquireData();
a737331d 658 m_neededreq = flags;
48da7d0b 659 m_internal->ReleaseData();
a737331d 660 if (m_neededreq == 0)
2a4f27f2 661 m_internal->StopWaiter();
8c14576d 662 else
a737331d 663 Notify(m_notify_state);
f4ada568
GL
664}
665
666void wxSocketBase::Notify(bool notify)
667{
aadbdf11
GL
668 m_notify_state = notify;
669 if (m_fd == INVALID_SOCKET)
670 return;
671
f4ada568 672 if (notify)
2a4f27f2 673 m_internal->ResumeWaiter();
f4ada568 674 else
2a4f27f2 675 m_internal->StopWaiter();
f4ada568
GL
676}
677
678void wxSocketBase::OnRequest(wxRequestEvent req_evt)
679{
a737331d
GL
680 wxSocketEvent event(m_id);
681 wxRequestNotify notify = EventToNotify(req_evt);
f4ada568 682
a737331d
GL
683 if ((m_neededreq & notify) == notify) {
684 event.m_socket = this;
685 event.m_skevt = req_evt;
686 ProcessEvent(event);
687 // TODOTODO
688 // OldOnNotify(req_evt);
f4ada568 689
a737331d 690 // We disable the event reporting.
2a4f27f2 691 m_neededreq &= ~notify;
f4ada568 692 }
f4ada568
GL
693}
694
695wxSocketEvent::wxSocketEvent(int id)
696 : wxEvent(id)
697{
698 wxEventType type = (wxEventType)wxEVT_SOCKET;
699
700 SetEventType(type);
701}
702
aadbdf11 703void wxSocketEvent::CopyObject(wxObject& obj_d) const
f4ada568 704{
aadbdf11
GL
705 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
706
707 wxEvent::CopyObject(obj_d);
f4ada568 708
a737331d
GL
709 event->m_skevt = m_skevt;
710 event->m_socket = m_socket;
f4ada568
GL
711}
712
a737331d 713void wxSocketBase::OldOnNotify(wxRequestEvent evt)
f4ada568 714{
f4ada568
GL
715}
716
a737331d
GL
717// --------------------------------------------------------------
718// --------- wxSocketBase functions [Callback, CallbackData] ----
719// --------------------------------------------------------------
f4ada568
GL
720
721void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
722{
723 SetNextHandler(&h_evt);
724 m_id = id;
725}
726
727// --------------------------------------------------------------
728// --------- wxSocketBase pushback library ----------------------
729// --------------------------------------------------------------
db131261 730
f4ada568
GL
731void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t size)
732{
733 char *curr_pos;
734
375abe3d
GL
735 if (m_unread != NULL)
736 m_unread = (char *) realloc(m_unread, m_unrd_size+size);
737 else
738 m_unread = (char *) malloc(size);
f4ada568
GL
739 curr_pos = m_unread + m_unrd_size;
740
741 memcpy(curr_pos, buffer, size);
742 m_unrd_size += size;
743}
744
745void wxSocketBase::CreatePushbackBefore(const char *buffer, size_t size)
746{
747 char *curr_pos, *new_buf;
748
749 new_buf = (char *) malloc(m_unrd_size+size);
750 curr_pos = new_buf + size;
751
752 memcpy(new_buf, buffer, size);
41895a05
GL
753 if (m_unrd_size != 0) {
754 memcpy(curr_pos, m_unread, m_unrd_size);
755 free(m_unread);
756 }
f4ada568
GL
757 m_unread = new_buf;
758 m_unrd_size += size;
759}
760
761size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek)
762{
763 if (!m_unrd_size)
764 return 0;
765
766 if (size > m_unrd_size)
767 size = m_unrd_size;
768 memcpy(buffer, m_unread, size);
769
770 if (!peek) {
771 m_unrd_size -= size;
41895a05 772 if (m_unrd_size == 0) {
f4ada568
GL
773 free(m_unread);
774 m_unread = NULL;
775 }
776 }
777
778 return size;
779}
780
781// --------------------------------------------------------------
a737331d 782// --------- wxSocketBase buffer core requester -----------------
f4ada568
GL
783// --------------------------------------------------------------
784
f4ada568 785void wxSocketBase::WantBuffer(char *buffer, size_t nbytes,
17dff81c 786 wxRequestEvent evt)
f4ada568
GL
787{
788 bool buf_timed_out;
789
790 if (m_fd == INVALID_SOCKET || !m_handler || !m_connected)
791 return;
792
f4ada568 793 SockRequest *buf = new SockRequest;
f4ada568
GL
794
795 SaveState();
f4ada568
GL
796 buf->buffer = buffer;
797 buf->size = nbytes;
798 buf->done = FALSE;
a737331d
GL
799 buf->type = EventToNotify(evt);
800 buf->io_nbytes = 0;
f4ada568 801 buf->error = 0;
a737331d
GL
802 buf->wait = TRUE;
803 buf->timeout = 1000;
f4ada568
GL
804 buf_timed_out = FALSE;
805
48da7d0b 806 if ((m_flags & SPEED) != 0)
a737331d
GL
807 m_internal->QueueRequest(buf, FALSE);
808 else
48da7d0b 809 if ((m_flags & NOWAIT) != 0)
a737331d
GL
810 m_internal->QueueRequest(buf, TRUE);
811 else
812 m_internal->QueueRequest(buf, TRUE);
813 m_lcount += buf->io_nbytes;
f4ada568
GL
814 if (buf_timed_out)
815 m_error = ETIMEDOUT;
816 else
817 m_error = buf->error;
818
819 delete buf;
820 RestoreState();
821}
822
823// --------------------------------------------------------------
8c14576d 824// wxSocketServer
f4ada568
GL
825// --------------------------------------------------------------
826
f4ada568 827wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
17dff81c 828 wxSockFlags flags) :
f4ada568
GL
829 wxSocketBase(flags, SOCK_SERVER)
830{
831 m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0);
832
833 if (m_fd == INVALID_SOCKET)
834 return;
384b4373 835
f4ada568
GL
836 int flag = 1;
837 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, sizeof(int));
384b4373 838
f4ada568
GL
839 struct sockaddr *myaddr;
840 size_t len;
384b4373 841
f4ada568
GL
842 addr_man.Build(myaddr, len);
843 if (bind(m_fd, myaddr, addr_man.SockAddrLen()) < 0)
844 return;
384b4373 845
f4ada568
GL
846 if (listen(m_fd, 5) < 0) {
847 m_fd = INVALID_SOCKET;
848 return;
849 }
a737331d 850
9111db68
GL
851 m_internal->SetFD(m_fd);
852
2a4f27f2 853 Notify(TRUE);
f4ada568
GL
854}
855
856// --------------------------------------------------------------
8c14576d 857// wxSocketServer Accept
f4ada568 858// --------------------------------------------------------------
8c14576d 859
f4ada568
GL
860bool wxSocketServer::AcceptWith(wxSocketBase& sock)
861{
862 int fd2;
384b4373 863
aadbdf11
GL
864 m_internal->AcquireFD();
865 if ((fd2 = accept(m_fd, 0, 0)) < 0) {
866 m_internal->ReleaseFD();
f4ada568 867 return FALSE;
aadbdf11
GL
868 }
869 m_internal->ReleaseFD();
f4ada568
GL
870
871 struct linger linger;
872 linger.l_onoff = 0;
873 linger.l_linger = 1;
384b4373 874
f4ada568 875 setsockopt(fd2, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
384b4373 876
f4ada568
GL
877 int flag = 0;
878 setsockopt(fd2, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int));
384b4373 879
f4ada568
GL
880 sock.m_type = SOCK_INTERNAL;
881 sock.m_fd = fd2;
882 sock.m_connected = TRUE;
883
9111db68
GL
884 sock.m_internal->SetFD(fd2);
885
2a4f27f2 886 sock.m_internal->ResumeWaiter();
a737331d 887
f4ada568
GL
888 return TRUE;
889}
890
891wxSocketBase *wxSocketServer::Accept()
892{
893 wxSocketBase* sock = new wxSocketBase();
894
895 sock->SetFlags((wxSockFlags)m_flags);
896
897 if (!AcceptWith(*sock))
898 return NULL;
899
900 if (m_handler)
901 m_handler->Register(sock);
902
903 return sock;
904}
905
f4ada568 906// --------------------------------------------------------------
8c14576d 907// wxSocketClient
f4ada568
GL
908// --------------------------------------------------------------
909
910// --------- wxSocketClient CONSTRUCTOR -------------------------
911// --------------------------------------------------------------
912wxSocketClient::wxSocketClient(wxSockFlags _flags) :
17dff81c 913 wxSocketBase(_flags, SOCK_CLIENT)
f4ada568
GL
914{
915}
916
917// --------------------------------------------------------------
918// --------- wxSocketClient DESTRUCTOR --------------------------
919// --------------------------------------------------------------
920wxSocketClient::~wxSocketClient()
921{
922}
923
924// --------------------------------------------------------------
925// --------- wxSocketClient Connect functions -------------------
926// --------------------------------------------------------------
e22036dc 927bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) )
f4ada568
GL
928{
929 struct linger linger;
930
931 if (IsConnected())
932 Close();
933
a737331d
GL
934 // Initializes all socket stuff ...
935 // --------------------------------
f4ada568 936 m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0);
384b4373 937
f4ada568
GL
938 if (m_fd < 0)
939 return FALSE;
384b4373 940
f4ada568
GL
941 m_connected = FALSE;
942
943 linger.l_onoff = 1;
384b4373 944 linger.l_linger = 5;
f4ada568 945 setsockopt(m_fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
384b4373 946
f4ada568 947 // Stay in touch with the state of things...
384b4373 948
f4ada568
GL
949 unsigned long flag = 1;
950 setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int));
384b4373 951
f4ada568
GL
952 // Disable the nagle algorithm, which delays sends till the
953 // buffer is full (or a certain time period has passed?)...
954
955#if defined(__WINDOWS__) || (defined(IPPROTO_TCP) && defined(TCP_NODELAY))
956 flag = 1;
957 setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
958#endif
384b4373 959
f4ada568
GL
960 struct sockaddr *remote;
961 size_t len;
962
963 addr_man.Build(remote, len);
964
965 if (connect(m_fd, remote, len) != 0)
966 return FALSE;
967
9111db68
GL
968 m_internal->SetFD(m_fd);
969
a737331d
GL
970 // Enables bg events.
971 // ------------------
f4ada568
GL
972 Notify(TRUE);
973
974 m_connected = TRUE;
975 return TRUE;
976}
977
75ed1d15 978bool wxSocketClient::WaitOnConnect(long seconds, long microseconds)
f4ada568 979{
75ed1d15 980 int ret = _Wait(seconds, microseconds, REQ_CONNECT | REQ_LOST);
384b4373 981
f4ada568
GL
982 if (ret)
983 m_connected = TRUE;
384b4373
RD
984
985 return m_connected;
f4ada568
GL
986}
987
988void wxSocketClient::OnRequest(wxRequestEvent evt)
989{
8c14576d
RR
990 if (evt == EVT_CONNECT)
991 {
992 if (m_connected)
993 {
2a4f27f2 994 m_neededreq &= ~REQ_CONNECT;
f4ada568
GL
995 return;
996 }
384b4373 997 m_connected = TRUE;
f4ada568
GL
998 return;
999 }
1000 wxSocketBase::OnRequest(evt);
1001}
1002
1003/////////////////////////////////////////////////////////////////
1004// wxSocketHandler ///////////////////////////////////////////////
1005/////////////////////////////////////////////////////////////////
1006
1007wxSocketHandler *wxSocketHandler::master = NULL;
1008#if defined(__WINDOWS__)
1009static int win_initialized = 0;
1010#endif
1011
1012// --------------------------------------------------------------
1013// --------- wxSocketHandler CONSTRUCTOR ------------------------
1014// --------------------------------------------------------------
f4ada568
GL
1015wxSocketHandler::wxSocketHandler()
1016{
1017#if defined(__WINDOWS__)
8c14576d
RR
1018 if (!win_initialized)
1019 {
f4ada568
GL
1020 WSADATA wsaData;
1021
1022 WSAStartup((1 << 8) | 1, &wsaData);
1023 win_initialized = 1;
1024 }
f4ada568
GL
1025#endif
1026
1027 socks = new wxList;
1028
1029#ifndef __WINDOWS__
1030 signal(SIGPIPE, SIG_IGN);
1031#endif
1032}
1033
1034// --------------------------------------------------------------
1035// --------- wxSocketHandler DESTRUCTOR -------------------------
1036// --------------------------------------------------------------
1037wxSocketHandler::~wxSocketHandler()
1038{
1039 wxNode *next_node, *node = socks->First();
1040
8c14576d
RR
1041 while (node)
1042 {
f4ada568
GL
1043 wxSocketBase* sock = (wxSocketBase*)node->Data();
1044
1045 delete sock;
1046 next_node = node->Next();
1047 delete node;
1048 node = next_node;
1049 }
1050
1051 delete socks;
1052
1053#ifdef __WINDOWS__
f4ada568
GL
1054 WSACleanup();
1055 win_initialized = 0;
f4ada568
GL
1056#endif
1057}
1058
1059// --------------------------------------------------------------
1060// --------- wxSocketHandler registering functions --------------
1061// --------------------------------------------------------------
8c14576d 1062
f4ada568
GL
1063void wxSocketHandler::Register(wxSocketBase* sock)
1064{
1065 wxNode *node;
1066
8c14576d
RR
1067 for (node = socks->First(); node != NULL; node = node->Next())
1068 {
f4ada568
GL
1069 wxSocketBase* s = (wxSocketBase*)node->Data();
1070
1071 if (s == sock)
1072 return;
1073 }
1074
8c14576d
RR
1075 if (sock)
1076 {
f4ada568
GL
1077 socks->Append(sock);
1078 sock->SetHandler(this);
f4ada568
GL
1079 }
1080}
1081
1082void wxSocketHandler::UnRegister(wxSocketBase* sock)
1083{
1084 wxNode *node;
1085
8c14576d
RR
1086 for (node = socks->First(); node; node = node->Next())
1087 {
f4ada568 1088 wxSocketBase* s = (wxSocketBase*)node->Data();
384b4373 1089
8c14576d
RR
1090 if (s == sock)
1091 {
f4ada568 1092 delete node;
f4ada568
GL
1093 sock->SetHandler(NULL);
1094 return;
1095 }
1096 }
1097}
1098
1099unsigned long wxSocketHandler::Count() const
1100{
1101 return socks->Number();
1102}
1103
1104// --------------------------------------------------------------
1105// --------- wxSocketHandler "big" wait functions ---------------
1106// --------------------------------------------------------------
f4ada568
GL
1107
1108int wxSocketHandler::Wait(long seconds, long microseconds)
1109{
a737331d
GL
1110 // TODO Needs the completely asynchronous notifier.
1111
1112 /*
f4ada568
GL
1113 int i;
1114 int on_wait;
f4ada568 1115 wxNode *node;
8c14576d
RR
1116 for (node = socks->First(), i=0; node; node = node->Next(), i++)
1117 {
f4ada568
GL
1118 wxSocketBase *sock = (wxSocketBase *)node->Data();
1119
1120 sock->SaveState();
1121
1122 sock->SetupCallbacks();
1123
1124 sock->Callback(handler_cbk);
1125 sock->CallbackData((char *)&on_wait);
1126 }
1127 on_wait = 0;
1128 if (seconds != -1)
1129 s_wake.Start((seconds*1000) + (microseconds/1000), TRUE);
1130
1131 while (!on_wait)
1132 PROCESS_EVENTS();
1133
8c14576d
RR
1134 for (node = socks->First(), i=0; node; node = node->Next(), i++)
1135 {
f4ada568
GL
1136 wxSocketBase *sock = (wxSocketBase *)node->Data();
1137
1138 sock->RestoreState();
1139 }
1140
1141 if (on_wait == -2)
1142 return 0;
1143
1144 return on_wait;
a737331d
GL
1145 */
1146 return 0;
f4ada568
GL
1147}
1148
1149void wxSocketHandler::YieldSock()
1150{
1151 wxNode *node;
1152
a737331d
GL
1153 // Nothing to do anymore here except waiting for the queue emptying.
1154 for (node = socks->First(); node; node=node->Next()) {
f4ada568
GL
1155 wxSocketBase *sock = (wxSocketBase *)node->Data();
1156
a737331d 1157 sock->m_internal->WaitForEnd(NULL);
f4ada568
GL
1158 }
1159}
1160
1161// --------------------------------------------------------------
1162// --------- wxSocketHandler: create and register the socket ----
1163// --------------------------------------------------------------
1164wxSocketServer *wxSocketHandler::CreateServer(wxSockAddress& addr,
17dff81c 1165 wxSocketBase::wxSockFlags flags)
f4ada568
GL
1166{
1167 wxSocketServer *serv = new wxSocketServer(addr, flags);
1168
1169 Register(serv);
1170 return serv;
1171}
1172
1173wxSocketClient *wxSocketHandler::CreateClient(wxSocketBase::wxSockFlags flags)
1174{
1175 wxSocketClient *client = new wxSocketClient(flags);
1176
1177 Register(client);
1178 return client;
1179}
1180
8c14576d
RR
1181bool wxSocketModule::OnInit()
1182{
3b4183d8
GL
1183 wxSocketHandler::master = new wxSocketHandler();
1184 return TRUE;
1185}
1186
8c14576d
RR
1187void wxSocketModule::OnExit()
1188{
3b4183d8
GL
1189 delete wxSocketHandler::master;
1190 wxSocketHandler::master = NULL;
1191}
1192
7f555861
JS
1193#endif
1194 // __WXSTUBS__
35a4dab7
GL
1195
1196#endif
1197 // wxUSE_SOCKETS