]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
1. added wxGetNumberFromUser (to textdlgg.cpp and dialogs sample)
[wxWidgets.git] / src / common / socket.cpp
CommitLineData
f4ada568
GL
1////////////////////////////////////////////////////////////////////////////////
2// Name: socket.cpp
3// Purpose: Socket handler classes
a324a7bc 4// Authors: Guilhem Lavaux
f4ada568 5// Created: April 1997
a324a7bc
GL
6// Updated: July 1999
7// Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux
f4ada568
GL
8// RCS_ID: $Id$
9// License: see wxWindows license
10////////////////////////////////////////////////////////////////////////////////
384b4373 11#ifdef __GNUG__
f4ada568 12#pragma implementation "socket.h"
f4ada568
GL
13#endif
14
fcc6dddd
JS
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19#pragma hdrstop
20#endif
21
35a4dab7
GL
22#if wxUSE_SOCKETS
23
f4ada568
GL
24/////////////////////////////////////////////////////////////////////////////
25// wxWindows headers
26/////////////////////////////////////////////////////////////////////////////
27#include <wx/defs.h>
28#include <wx/object.h>
29#include <wx/string.h>
30#include <wx/timer.h>
31#include <wx/utils.h>
a324a7bc 32#include <wx/log.h>
7f555861 33
f4ada568
GL
34#include <stdlib.h>
35#include <string.h>
36#include <ctype.h>
37
f4ada568
GL
38/////////////////////////////////////////////////////////////////////////////
39// wxSocket headers
40/////////////////////////////////////////////////////////////////////////////
a737331d 41#include <wx/module.h>
a737331d
GL
42#include <wx/sckaddr.h>
43#include <wx/socket.h>
3b4183d8 44
f4ada568
GL
45// --------------------------------------------------------------
46// ClassInfos
47// --------------------------------------------------------------
48#if !USE_SHARED_LIBRARY
a737331d
GL
49IMPLEMENT_CLASS(wxSocketBase, wxObject)
50IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
51IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
a737331d 52IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
f4ada568
GL
53#endif
54
a324a7bc
GL
55class wxSocketState : public wxObject {
56public:
57 bool notify_state;
58 GSocketEventFlags evt_notify_state;
59 wxSocketBase::wxSockFlags socket_flags;
60 wxSocketBase::wxSockCbk c_callback;
61 char *c_callback_data;
62
63public:
64 wxSocketState() : wxObject() {}
65};
66
f4ada568
GL
67// --------------------------------------------------------------
68// --------- wxSocketBase CONSTRUCTOR ---------------------------
69// --------------------------------------------------------------
70wxSocketBase::wxSocketBase(wxSocketBase::wxSockFlags _flags,
17dff81c 71 wxSocketBase::wxSockType _type) :
f4ada568 72 wxEvtHandler(),
a324a7bc
GL
73 m_socket(NULL), m_flags(_flags), m_type(_type),
74 m_neededreq(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG),
75 m_lcount(0), m_timeout(3600),
76 m_unread(NULL), m_unrd_size(0), m_unrd_cur(0),
a737331d 77 m_cbk(NULL), m_cdata(NULL),
a324a7bc
GL
78 m_connected(FALSE), m_notify_state(FALSE), m_id(-1),
79 m_defering(NO_DEFER),
80 m_states()
f4ada568 81{
f4ada568
GL
82}
83
84wxSocketBase::wxSocketBase() :
85 wxEvtHandler(),
a324a7bc
GL
86 m_socket(NULL), m_flags((wxSockFlags)SPEED | WAITALL), m_type(SOCK_UNINIT),
87 m_neededreq(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG),
88 m_lcount(0), m_timeout(3600),
89 m_unread(NULL), m_unrd_size(0), m_unrd_cur(0),
a737331d 90 m_cbk(NULL), m_cdata(NULL),
a324a7bc
GL
91 m_connected(FALSE), m_notify_state(FALSE), m_id(-1),
92 m_defering(NO_DEFER),
93 m_states()
f4ada568 94{
f4ada568
GL
95}
96
97// --------------------------------------------------------------
a324a7bc 98// wxSocketBase destructor
f4ada568 99// --------------------------------------------------------------
8c14576d 100
f4ada568
GL
101wxSocketBase::~wxSocketBase()
102{
f4ada568
GL
103 if (m_unread)
104 free(m_unread);
a737331d 105
a324a7bc
GL
106 // At last, close the file descriptor.
107 Close();
f4ada568 108
a324a7bc
GL
109 if (m_socket)
110 GSocket_destroy(m_socket);
f4ada568
GL
111}
112
113bool wxSocketBase::Close()
114{
a324a7bc 115 if (m_socket)
8c14576d 116 {
2a4f27f2
GL
117 if (m_notify_state == TRUE)
118 Notify(FALSE);
f4ada568 119
a737331d 120 // Shutdown the connection.
a324a7bc 121 GSocket_Shutdown(m_socket);
f4ada568
GL
122 m_connected = FALSE;
123 }
124
125 return TRUE;
126}
127
128// --------------------------------------------------------------
8c14576d 129// wxSocketBase base IO function
f4ada568 130// --------------------------------------------------------------
8c14576d 131
a324a7bc
GL
132int wxSocketBase::DeferRead(char *buffer, size_t nbytes)
133{
134 GSocketEventFlags old_event_flags;
135 bool old_notify_state;
136
137 wxASSERT(m_defering == NO_DEFER);
138
139 m_defering = DEFER_READ;
140
141 old_event_flags = NeededReq();
142 old_notify_state = m_notify_state;
143
144 SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
145 Notify(TRUE);
146
147 m_defer_buffer = buffer;
148 m_defer_nbytes = nbytes;
149 while (m_defer_buffer != NULL)
150 wxYield();
151
152 Notify(old_notify_state);
153 SetNotify(old_event_flags);
154
155 m_defering = NO_DEFER;
156
157 return nbytes-m_defer_nbytes;
158}
159
f4ada568
GL
160wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes)
161{
a324a7bc
GL
162 int ret = 1;
163
a737331d
GL
164 m_lcount = GetPushback(buffer, nbytes, FALSE);
165 nbytes -= m_lcount;
166 buffer += m_lcount;
f4ada568 167
a324a7bc
GL
168 if (!m_connected)
169 return *this;
170
f4ada568
GL
171 // If we have got the whole needed buffer or if we don't want to
172 // wait then it returns immediately.
a737331d 173 if (!nbytes || (m_lcount && !(m_flags & WAITALL)) ) {
f4ada568 174 return *this;
375abe3d 175 }
f4ada568 176
a324a7bc
GL
177 if ((m_flags & SPEED) != 0) {
178
179 if ((m_flags & WAITALL) != 0) {
180 while (ret > 0 && nbytes > 0) {
181 ret = GSocket_Read(m_socket, buffer, nbytes);
182 m_lcount += ret;
183 buffer += ret;
184 nbytes -= ret;
185 }
186 // In case the last call was an error ...
187 if (ret < 0)
188 m_lcount ++;
189 } else {
190 ret = GSocket_Read(m_socket, buffer, nbytes);
191 if (ret > 0)
192 m_lcount += ret;
193 }
194
195 } else {
196 ret = DeferRead(buffer, nbytes);
197
198 if (ret > 0)
199 m_lcount += ret;
200 }
f4ada568
GL
201
202 return *this;
203}
204
062c4861
GL
205wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes)
206{
207 unsigned long len, len2, sig;
208 struct {
209 char sig[4];
210 char len[4];
211 } msg;
212
213 // sig should be an explicit 32-bit unsigned integer; I've seen
214 // compilers in which size_t was actually a 16-bit unsigned integer
215
216 Read((char *)&msg, sizeof(msg));
217 if (m_lcount != sizeof(msg))
218 return *this;
219
220 sig = msg.sig[0] & 0xff;
221 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
222 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
223 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
224
225 if (sig != 0xfeeddead)
226 return *this;
227 len = msg.len[0] & 0xff;
228 len |= (size_t)(msg.len[1] & 0xff) << 8;
229 len |= (size_t)(msg.len[2] & 0xff) << 16;
230 len |= (size_t)(msg.len[3] & 0xff) << 24;
231
232 // len2 is incorrectly computed in the original; this sequence is
233 // the fix
234 if (len > nbytes) {
235 len2 = len - nbytes;
236 len = nbytes;
237 }
238 else
239 len2 = 0;
240
241 // the "len &&" in the following statement is necessary so that
242 // we don't attempt to read (and possibly hang the system)
243 // if the message was zero bytes long
244 if (len && Read(buffer, len).LastCount() != len)
245 return *this;
246 if (len2 && (Read(NULL, len2).LastCount() != len2))
247 return *this;
248 if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg))
249 return *this;
250
251 sig = msg.sig[0] & 0xff;
252 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
253 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
254 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
a324a7bc 255
062c4861 256// ERROR
062c4861 257 if (sig != 0xdeadfeed)
a324a7bc 258 wxLogDebug(_T("Warning: invalid signature returned to ReadMsg\n"));
062c4861
GL
259
260 return *this;
261}
262
f4ada568
GL
263wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes)
264{
a324a7bc
GL
265 Read(buffer, nbytes);
266 CreatePushbackAfter(buffer, nbytes);
f4ada568
GL
267
268 return *this;
269}
270
a324a7bc
GL
271int wxSocketBase::DeferWrite(const char *buffer, size_t nbytes)
272{
273 GSocketEventFlags old_event_flags;
274 bool old_notify_state;
275
276 wxASSERT(m_defering == NO_DEFER);
277
278 m_defering = DEFER_WRITE;
279
280 old_event_flags = NeededReq();
281 old_notify_state = m_notify_state;
282
283 SetNotify(GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG);
284 Notify(TRUE);
285
286 m_defer_buffer = (char *)buffer;
287 m_defer_nbytes = nbytes;
288 while (m_defer_buffer != NULL)
289 wxYield();
290
291 Notify(old_notify_state);
292 SetNotify(old_event_flags);
293
294 m_defering = NO_DEFER;
295
296 return nbytes-m_defer_nbytes;
297}
298
f4ada568
GL
299wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes)
300{
a324a7bc
GL
301 int ret;
302
303 if ((m_flags & SPEED) != 0)
304 ret = GSocket_Write(m_socket, buffer, nbytes);
305 else
306 ret = DeferWrite(buffer, nbytes);
307
308 if (ret != -1)
309 m_lcount += ret;
310
f4ada568
GL
311 return *this;
312}
313
062c4861
GL
314wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes)
315{
316 struct {
317 char sig[4];
318 char len[4];
319 } msg;
320
321 // warning about 'cast truncates constant value'
322#ifdef __VISUALC__
323 #pragma warning(disable: 4310)
324#endif // __VISUALC__
325
326 msg.sig[0] = (char) 0xad;
327 msg.sig[1] = (char) 0xde;
328 msg.sig[2] = (char) 0xed;
329 msg.sig[3] = (char) 0xfe;
330
331 msg.len[0] = (char) nbytes & 0xff;
332 msg.len[1] = (char) (nbytes >> 8) & 0xff;
333 msg.len[2] = (char) (nbytes >> 16) & 0xff;
334 msg.len[3] = (char) (nbytes >> 24) & 0xff;
335
336 if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg))
337 return *this;
338 if (Write(buffer, nbytes).LastCount() < nbytes)
339 return *this;
340
341 msg.sig[0] = (char) 0xed;
342 msg.sig[1] = (char) 0xfe;
343 msg.sig[2] = (char) 0xad;
344 msg.sig[3] = (char) 0xde;
345 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
346 Write((char *)&msg, sizeof(msg));
347
348 return *this;
349
350#ifdef __VISUALC__
351 #pragma warning(default: 4310)
352#endif // __VISUALC__
353}
354
f4ada568
GL
355wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes)
356{
062c4861
GL
357 m_lcount = 0;
358 if (nbytes != 0) {
359 CreatePushbackAfter(buffer, nbytes);
360 m_lcount = nbytes;
361 }
f4ada568
GL
362 return *this;
363}
364
365bool wxSocketBase::IsData() const
366{
a324a7bc 367 if (!m_socket)
f4ada568 368 return FALSE;
f4ada568 369
a324a7bc
GL
370 return (GSocket_DataAvailable(m_socket));
371}
372
373void wxSocketBase::DoDefer(GSocketEvent req_evt)
374{
375 int ret;
a737331d 376
a324a7bc
GL
377 if (req_evt == GSOCK_LOST) {
378 Close();
379 m_defer_buffer = NULL;
380 return;
381 }
382 switch (m_defering) {
383 case DEFER_READ:
384 ret = GSocket_Read(m_socket, m_defer_buffer, m_defer_nbytes);
385 break;
386 case DEFER_WRITE:
387 ret = GSocket_Write(m_socket, m_defer_buffer, m_defer_nbytes);
388 break;
389 default:
390 ret = -1;
391 break;
392 }
a737331d 393
a324a7bc 394 m_defer_nbytes -= ret;
a737331d 395
a324a7bc
GL
396 if (ret < 0)
397 m_defer_nbytes++;
398
399 if ((m_flags & WAITALL) == 0 || m_defer_nbytes == 0 || ret < 0) {
400 m_defer_buffer = NULL;
401 Notify(FALSE);
402 } else
403 m_defer_buffer += ret;
f4ada568
GL
404}
405
406// ---------------------------------------------------------------------
407// --------- wxSocketBase Discard(): deletes all byte in the input queue
408// ---------------------------------------------------------------------
409void wxSocketBase::Discard()
410{
411#define MAX_BUFSIZE (10*1024)
412 char *my_data = new char[MAX_BUFSIZE];
413 size_t recv_size = MAX_BUFSIZE;
414
415 SaveState();
416 SetFlags((wxSockFlags)(NOWAIT | SPEED));
384b4373 417
8c14576d
RR
418 while (recv_size == MAX_BUFSIZE)
419 {
f4ada568
GL
420 recv_size = Read(my_data, MAX_BUFSIZE).LastCount();
421 }
422
423 RestoreState();
424 delete [] my_data;
425
426#undef MAX_BUFSIZE
427}
428
429// --------------------------------------------------------------
8c14576d 430// wxSocketBase socket info functions
f4ada568 431// --------------------------------------------------------------
8c14576d 432
f4ada568
GL
433bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
434{
a324a7bc 435 GAddress *peer;
f4ada568 436
a324a7bc 437 if (!m_socket)
f4ada568
GL
438 return FALSE;
439
a324a7bc
GL
440 peer = GSocket_GetPeer(m_socket);
441 addr_man.SetAddress(peer);
442 GAddress_destroy(peer);
a737331d 443
f4ada568
GL
444 return TRUE;
445}
446
447bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
448{
a324a7bc 449 GAddress *local;
f4ada568 450
a324a7bc 451 if (!m_socket)
f4ada568
GL
452 return FALSE;
453
a324a7bc
GL
454 local = GSocket_GetLocal(m_socket);
455 addr_man.SetAddress(local);
456 GAddress_destroy(local);
f4ada568 457
f4ada568
GL
458 return TRUE;
459}
460
461// --------------------------------------------------------------
8c14576d 462// wxSocketBase wait functions
f4ada568 463// --------------------------------------------------------------
db131261 464
f4ada568
GL
465void wxSocketBase::SaveState()
466{
a324a7bc
GL
467 wxSocketState *state;
468
469 state = new wxSocketState();
f4ada568 470
a737331d
GL
471 state->notify_state = m_notify_state;
472 state->evt_notify_state = m_neededreq;
473 state->socket_flags = m_flags;
474 state->c_callback = m_cbk;
475 state->c_callback_data = m_cdata;
f4ada568 476
a324a7bc 477 m_states.Append(state);
f4ada568
GL
478}
479
480void wxSocketBase::RestoreState()
481{
482 wxNode *node;
a324a7bc 483 wxSocketState *state;
f4ada568
GL
484
485 node = m_states.Last();
486 if (!node)
487 return;
488
a324a7bc 489 state = (wxSocketState *)node->Data();
384b4373 490
a737331d
GL
491 SetFlags(state->socket_flags);
492 m_neededreq = state->evt_notify_state;
493 m_cbk = state->c_callback;
494 m_cdata = state->c_callback_data;
495 Notify(state->notify_state);
f4ada568
GL
496
497 delete node;
498 delete state;
499}
500
501// --------------------------------------------------------------
a737331d 502// --------- wxSocketBase callback functions --------------------
f4ada568 503// --------------------------------------------------------------
db131261 504
a737331d 505wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
f4ada568 506{
a737331d 507 wxSockCbk old_cbk = cbk_;
f4ada568 508
a737331d
GL
509 m_cbk = cbk_;
510 return old_cbk;
f4ada568
GL
511}
512
a737331d 513char *wxSocketBase::CallbackData(char *data)
f4ada568 514{
a737331d 515 char *old_data = m_cdata;
f4ada568 516
a737331d
GL
517 m_cdata = data;
518 return old_data;
f4ada568
GL
519}
520
521// --------------------------------------------------------------
a737331d 522// --------- wxSocketBase wait functions ------------------------
f4ada568
GL
523// --------------------------------------------------------------
524
a324a7bc
GL
525class _wxSocketInternalTimer: public wxTimer {
526 public:
527 int *m_state;
528
529 void Notify()
530 {
531 *m_state = GSOCK_MAX_EVENT; // Just to say it's a timeout.
532 }
533};
534
535static void wx_socket_wait(GSocket *socket, GSocketEvent event, char *cdata)
536{
537 int *state = (int *)cdata;
538
539 *state = event;
540}
541
a737331d 542bool wxSocketBase::_Wait(long seconds, long milliseconds, int type)
375abe3d 543{
a324a7bc
GL
544 bool old_notify_state = m_notify_state;
545 int state = 0;
546 _wxSocketInternalTimer timer;
375abe3d 547
a324a7bc 548 if (!m_connected || !m_socket)
a737331d 549 return FALSE;
f4ada568 550
a324a7bc
GL
551 timer.m_state = &state;
552
553 Notify(FALSE);
554
555 timer.Start(seconds * 1000 + milliseconds, TRUE);
556 GSocket_SetFallback(m_socket, type, wx_socket_wait, (char *)&state);
f4ada568 557
a324a7bc
GL
558 while (state == 0)
559 wxYield();
f4ada568 560
a324a7bc
GL
561 GSocket_UnsetFallback(m_socket, type);
562 timer.Stop();
563
564 Notify(old_notify_state);
565
566 return (state != GSOCK_MAX_EVENT);
f4ada568 567}
f4ada568 568
a737331d 569bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 570{
a324a7bc
GL
571 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
572 GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG);
f4ada568 573}
f4ada568 574
a737331d 575bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 576{
a324a7bc 577 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
f4ada568
GL
578}
579
a737331d 580bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 581{
a324a7bc 582 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG);
a737331d 583}
f4ada568 584
a737331d
GL
585bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
586{
a324a7bc 587 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
f4ada568 588}
a737331d
GL
589
590// --------------------------------------------------------------
591// --------- wxSocketBase callback management -------------------
592// --------------------------------------------------------------
f4ada568 593
a324a7bc 594GSocketEventFlags wxSocketBase::EventToNotify(GSocketEvent evt)
f4ada568 595{
db131261
RR
596 switch (evt)
597 {
a324a7bc
GL
598 case GSOCK_INPUT:
599 return GSOCK_INPUT_FLAG;
600 case GSOCK_OUTPUT:
601 return GSOCK_OUTPUT_FLAG;
602 case GSOCK_CONNECTION:
603 return GSOCK_CONNECTION_FLAG;
604 case GSOCK_LOST_FLAG:
605 return GSOCK_LOST_FLAG;
606 default:
607 return 0;
f4ada568
GL
608 }
609 return 0;
610}
611
612void wxSocketBase::SetFlags(wxSockFlags _flags)
613{
614 m_flags = _flags;
f4ada568
GL
615}
616
a737331d 617wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const
f4ada568 618{
a737331d 619 return m_flags;
f4ada568
GL
620}
621
a324a7bc 622void wxSocketBase::SetNotify(GSocketEventFlags flags)
f4ada568 623{
a737331d
GL
624 /* Check if server */
625 if (m_type != SOCK_SERVER)
a324a7bc 626 flags &= ~GSOCK_CONNECTION_FLAG;
f4ada568 627
a737331d
GL
628 m_neededreq = flags;
629 if (m_neededreq == 0)
a324a7bc 630 Notify(FALSE);
8c14576d 631 else
a737331d 632 Notify(m_notify_state);
f4ada568
GL
633}
634
a324a7bc
GL
635// --------------------------------------------------------------
636// Automatic notifier
637// --------------------------------------------------------------
638
639static void wx_socket_fallback(GSocket *socket, GSocketEvent event, char *cdata)
640{
641 wxSocketBase *sckobj = (wxSocketBase *)cdata;
642
643 sckobj->OnRequest(event);
644}
645
f4ada568
GL
646void wxSocketBase::Notify(bool notify)
647{
aadbdf11 648 m_notify_state = notify;
a324a7bc 649 if (!m_socket)
aadbdf11
GL
650 return;
651
a324a7bc
GL
652 GSocket_UnsetFallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
653 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
654 if (!notify)
655 return;
656
657 GSocket_SetFallback(m_socket, m_neededreq, wx_socket_fallback, (char *)this);
f4ada568
GL
658}
659
a324a7bc 660void wxSocketBase::OnRequest(GSocketEvent req_evt)
f4ada568 661{
a737331d 662 wxSocketEvent event(m_id);
a324a7bc
GL
663 GSocketEventFlags notify = EventToNotify(req_evt);
664
665 if (m_defering != NO_DEFER) {
666 DoDefer(req_evt);
667 return;
668 }
f4ada568 669
a737331d
GL
670 if ((m_neededreq & notify) == notify) {
671 event.m_socket = this;
672 event.m_skevt = req_evt;
673 ProcessEvent(event);
a324a7bc 674 OldOnNotify(req_evt);
f4ada568 675 }
f4ada568 676
a324a7bc
GL
677 if (req_evt == GSOCK_LOST)
678 Close();
f4ada568
GL
679}
680
a324a7bc 681void wxSocketBase::OldOnNotify(GSocketEvent evt)
f4ada568 682{
f4ada568
GL
683}
684
a737331d
GL
685// --------------------------------------------------------------
686// --------- wxSocketBase functions [Callback, CallbackData] ----
687// --------------------------------------------------------------
f4ada568
GL
688
689void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
690{
691 SetNextHandler(&h_evt);
692 m_id = id;
693}
694
695// --------------------------------------------------------------
696// --------- wxSocketBase pushback library ----------------------
697// --------------------------------------------------------------
db131261 698
f4ada568
GL
699void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t size)
700{
701 char *curr_pos;
702
375abe3d
GL
703 if (m_unread != NULL)
704 m_unread = (char *) realloc(m_unread, m_unrd_size+size);
705 else
706 m_unread = (char *) malloc(size);
a324a7bc 707
f4ada568
GL
708 curr_pos = m_unread + m_unrd_size;
709
710 memcpy(curr_pos, buffer, size);
711 m_unrd_size += size;
712}
713
714void wxSocketBase::CreatePushbackBefore(const char *buffer, size_t size)
715{
a324a7bc
GL
716 if (m_unread == NULL)
717 m_unread = (char *)malloc(size);
718 else {
719 char *tmp;
f4ada568 720
a324a7bc
GL
721 tmp = (char *)malloc(m_unrd_size + size);
722 memcpy(tmp+size, m_unread, m_unrd_size);
41895a05 723 free(m_unread);
a324a7bc
GL
724
725 m_unread = tmp;
41895a05 726 }
a324a7bc 727
f4ada568 728 m_unrd_size += size;
a324a7bc
GL
729
730 memcpy(m_unread, buffer, size);
f4ada568
GL
731}
732
733size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek)
734{
735 if (!m_unrd_size)
736 return 0;
737
a324a7bc
GL
738 if (size > (m_unrd_size-m_unrd_cur))
739 size = m_unrd_size-m_unrd_cur;
740 memcpy(buffer, (m_unread+m_unrd_cur), size);
f4ada568
GL
741
742 if (!peek) {
a324a7bc
GL
743 m_unrd_cur += size;
744 if (m_unrd_size == m_unrd_cur) {
f4ada568
GL
745 free(m_unread);
746 m_unread = NULL;
a324a7bc
GL
747 m_unrd_size = 0;
748 m_unrd_cur = 0;
f4ada568
GL
749 }
750 }
751
752 return size;
753}
754
f4ada568 755// --------------------------------------------------------------
8c14576d 756// wxSocketServer
f4ada568
GL
757// --------------------------------------------------------------
758
f4ada568 759wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
17dff81c 760 wxSockFlags flags) :
f4ada568
GL
761 wxSocketBase(flags, SOCK_SERVER)
762{
a324a7bc 763 m_socket = GSocket_new();
f4ada568 764
a324a7bc 765 if (!m_socket)
f4ada568 766 return;
384b4373 767
a324a7bc
GL
768 GSocket_SetLocal(m_socket, addr_man.GetAddress());
769 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR) {
770 GSocket_destroy(m_socket);
771 m_socket = NULL;
f4ada568
GL
772 return;
773 }
a737331d 774
2a4f27f2 775 Notify(TRUE);
f4ada568
GL
776}
777
778// --------------------------------------------------------------
8c14576d 779// wxSocketServer Accept
f4ada568 780// --------------------------------------------------------------
8c14576d 781
f4ada568
GL
782bool wxSocketServer::AcceptWith(wxSocketBase& sock)
783{
a324a7bc 784 GSocket *child_socket;
f4ada568 785
a324a7bc 786 child_socket = GSocket_WaitConnection(m_socket);
384b4373 787
f4ada568 788 sock.m_type = SOCK_INTERNAL;
a324a7bc 789 sock.m_socket = child_socket;
f4ada568
GL
790 sock.m_connected = TRUE;
791
792 return TRUE;
793}
794
795wxSocketBase *wxSocketServer::Accept()
796{
797 wxSocketBase* sock = new wxSocketBase();
798
799 sock->SetFlags((wxSockFlags)m_flags);
800
801 if (!AcceptWith(*sock))
802 return NULL;
803
f4ada568
GL
804 return sock;
805}
806
f4ada568 807// --------------------------------------------------------------
8c14576d 808// wxSocketClient
f4ada568
GL
809// --------------------------------------------------------------
810
811// --------- wxSocketClient CONSTRUCTOR -------------------------
812// --------------------------------------------------------------
813wxSocketClient::wxSocketClient(wxSockFlags _flags) :
17dff81c 814 wxSocketBase(_flags, SOCK_CLIENT)
f4ada568
GL
815{
816}
817
818// --------------------------------------------------------------
819// --------- wxSocketClient DESTRUCTOR --------------------------
820// --------------------------------------------------------------
821wxSocketClient::~wxSocketClient()
822{
823}
824
825// --------------------------------------------------------------
826// --------- wxSocketClient Connect functions -------------------
827// --------------------------------------------------------------
e22036dc 828bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) )
f4ada568 829{
f4ada568
GL
830 if (IsConnected())
831 Close();
832
a324a7bc
GL
833 // This should never happen.
834 if (m_socket)
835 GSocket_destroy(m_socket);
836
a737331d
GL
837 // Initializes all socket stuff ...
838 // --------------------------------
a324a7bc 839 m_socket = GSocket_new();
384b4373 840
a324a7bc 841 if (!m_socket)
f4ada568 842 return FALSE;
384b4373 843
f4ada568
GL
844 m_connected = FALSE;
845
a324a7bc
GL
846 // Update the flags of m_socket.
847 SetFlags(m_flags);
848 GSocket_SetPeer(m_socket, addr_man.GetAddress());
849 if (GSocket_Connect(m_socket, GSOCK_STREAMED) != GSOCK_NOERROR) {
f4ada568 850 return FALSE;
a324a7bc 851 }
9111db68 852
a737331d
GL
853 // Enables bg events.
854 // ------------------
f4ada568
GL
855 Notify(TRUE);
856
857 m_connected = TRUE;
858 return TRUE;
859}
860
75ed1d15 861bool wxSocketClient::WaitOnConnect(long seconds, long microseconds)
f4ada568 862{
a324a7bc 863 int ret = _Wait(seconds, microseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG);
384b4373 864
f4ada568
GL
865 if (ret)
866 m_connected = TRUE;
384b4373
RD
867
868 return m_connected;
f4ada568
GL
869}
870
a324a7bc 871void wxSocketClient::OnRequest(GSocketEvent evt)
f4ada568 872{
a324a7bc 873 if (evt == GSOCK_CONNECTION)
8c14576d
RR
874 {
875 if (m_connected)
876 {
a324a7bc 877 m_neededreq &= ~GSOCK_CONNECTION_FLAG;
f4ada568
GL
878 return;
879 }
384b4373 880 m_connected = TRUE;
f4ada568
GL
881 return;
882 }
883 wxSocketBase::OnRequest(evt);
884}
885
f4ada568 886// --------------------------------------------------------------
a324a7bc 887// wxSocketEvent
f4ada568 888// --------------------------------------------------------------
f4ada568 889
a324a7bc
GL
890wxSocketEvent::wxSocketEvent(int id)
891 : wxEvent(id)
f4ada568 892{
a324a7bc 893 wxEventType type = (wxEventType)wxEVT_SOCKET;
f4ada568 894
a324a7bc 895 SetEventType(type);
f4ada568
GL
896}
897
a324a7bc 898void wxSocketEvent::CopyObject(wxObject& obj_d) const
f4ada568 899{
a324a7bc 900 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
f4ada568 901
a324a7bc 902 wxEvent::CopyObject(obj_d);
3b4183d8 903
a324a7bc
GL
904 event->m_skevt = m_skevt;
905 event->m_socket = m_socket;
3b4183d8
GL
906}
907
35a4dab7
GL
908#endif
909 // wxUSE_SOCKETS