]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
Whole lot of stuff for new wxFileDialog
[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:
31528cd3 57 bool notify_state;
a324a7bc
GL
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),
7e1e0960 75 m_lcount(0), m_timeout(600),
a324a7bc 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(),
dbd300df 86 m_socket(NULL), m_flags(SPEED | WAITALL), m_type(SOCK_UNINIT),
a324a7bc 87 m_neededreq(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG),
7e1e0960 88 m_lcount(0), m_timeout(600),
a324a7bc 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{
31528cd3 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// --------------------------------------------------------------
39b91eca
GL
131class _wxSocketInternalTimer: public wxTimer {
132 public:
133 int *m_state;
e00f35bb 134 unsigned long m_new_val;
39b91eca
GL
135
136 void Notify()
137 {
138 *m_state = m_new_val; // Change the value
139 }
140};
8c14576d 141
a324a7bc
GL
142int wxSocketBase::DeferRead(char *buffer, size_t nbytes)
143{
144 GSocketEventFlags old_event_flags;
145 bool old_notify_state;
39b91eca
GL
146 // Timer for timeout
147 _wxSocketInternalTimer timer;
a324a7bc
GL
148
149 wxASSERT(m_defering == NO_DEFER);
150
39b91eca 151 // Set the defering mode to READ.
a324a7bc
GL
152 m_defering = DEFER_READ;
153
39b91eca 154 // Save the old state.
a324a7bc
GL
155 old_event_flags = NeededReq();
156 old_notify_state = m_notify_state;
31528cd3 157
39b91eca 158 // Set the new async flag.
a324a7bc
GL
159 SetNotify(GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
160 Notify(TRUE);
161
39b91eca 162 // Set the current buffer.
a324a7bc
GL
163 m_defer_buffer = buffer;
164 m_defer_nbytes = nbytes;
39b91eca
GL
165 m_defer_timer = &timer;
166
167 timer.m_state = (int *)&m_defer_buffer;
e00f35bb 168 timer.m_new_val = 0;
39b91eca
GL
169
170 timer.Start(m_timeout * 1000, FALSE);
171
172 // Wait for buffer completion.
a324a7bc
GL
173 while (m_defer_buffer != NULL)
174 wxYield();
175
39b91eca
GL
176 timer.Stop();
177
178 // Restore the old state.
a324a7bc
GL
179 Notify(old_notify_state);
180 SetNotify(old_event_flags);
181
39b91eca 182 // Disable defering mode.
a324a7bc 183 m_defering = NO_DEFER;
39b91eca 184 m_defer_timer = NULL;
a324a7bc 185
39b91eca 186 // Return the number of bytes read from the socket.
a324a7bc
GL
187 return nbytes-m_defer_nbytes;
188}
189
f4ada568
GL
190wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes)
191{
a324a7bc
GL
192 int ret = 1;
193
a737331d
GL
194 m_lcount = GetPushback(buffer, nbytes, FALSE);
195 nbytes -= m_lcount;
196 buffer += m_lcount;
f4ada568 197
a324a7bc
GL
198 if (!m_connected)
199 return *this;
200
f4ada568
GL
201 // If we have got the whole needed buffer or if we don't want to
202 // wait then it returns immediately.
a737331d 203 if (!nbytes || (m_lcount && !(m_flags & WAITALL)) ) {
f4ada568 204 return *this;
375abe3d 205 }
f4ada568 206
a324a7bc
GL
207 if ((m_flags & SPEED) != 0) {
208
209 if ((m_flags & WAITALL) != 0) {
210 while (ret > 0 && nbytes > 0) {
211 ret = GSocket_Read(m_socket, buffer, nbytes);
212 m_lcount += ret;
213 buffer += ret;
214 nbytes -= ret;
215 }
216 // In case the last call was an error ...
217 if (ret < 0)
218 m_lcount ++;
219 } else {
220 ret = GSocket_Read(m_socket, buffer, nbytes);
221 if (ret > 0)
222 m_lcount += ret;
223 }
224
225 } else {
226 ret = DeferRead(buffer, nbytes);
227
228 if (ret > 0)
229 m_lcount += ret;
230 }
f4ada568
GL
231
232 return *this;
233}
234
062c4861
GL
235wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes)
236{
237 unsigned long len, len2, sig;
238 struct {
239 char sig[4];
240 char len[4];
241 } msg;
242
243 // sig should be an explicit 32-bit unsigned integer; I've seen
244 // compilers in which size_t was actually a 16-bit unsigned integer
245
246 Read((char *)&msg, sizeof(msg));
247 if (m_lcount != sizeof(msg))
248 return *this;
249
250 sig = msg.sig[0] & 0xff;
251 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
252 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
253 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
254
255 if (sig != 0xfeeddead)
256 return *this;
257 len = msg.len[0] & 0xff;
258 len |= (size_t)(msg.len[1] & 0xff) << 8;
259 len |= (size_t)(msg.len[2] & 0xff) << 16;
260 len |= (size_t)(msg.len[3] & 0xff) << 24;
261
262 // len2 is incorrectly computed in the original; this sequence is
263 // the fix
264 if (len > nbytes) {
265 len2 = len - nbytes;
266 len = nbytes;
267 }
268 else
269 len2 = 0;
270
271 // the "len &&" in the following statement is necessary so that
272 // we don't attempt to read (and possibly hang the system)
273 // if the message was zero bytes long
274 if (len && Read(buffer, len).LastCount() != len)
275 return *this;
276 if (len2 && (Read(NULL, len2).LastCount() != len2))
277 return *this;
278 if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg))
279 return *this;
280
281 sig = msg.sig[0] & 0xff;
282 sig |= (size_t)(msg.sig[1] & 0xff) << 8;
283 sig |= (size_t)(msg.sig[2] & 0xff) << 16;
284 sig |= (size_t)(msg.sig[3] & 0xff) << 24;
a324a7bc 285
062c4861 286// ERROR
062c4861 287 if (sig != 0xdeadfeed)
a324a7bc 288 wxLogDebug(_T("Warning: invalid signature returned to ReadMsg\n"));
062c4861
GL
289
290 return *this;
291}
292
f4ada568
GL
293wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes)
294{
a324a7bc
GL
295 Read(buffer, nbytes);
296 CreatePushbackAfter(buffer, nbytes);
f4ada568
GL
297
298 return *this;
299}
300
a324a7bc
GL
301int wxSocketBase::DeferWrite(const char *buffer, size_t nbytes)
302{
303 GSocketEventFlags old_event_flags;
304 bool old_notify_state;
39b91eca
GL
305 // Timer for timeout
306 _wxSocketInternalTimer timer;
a324a7bc
GL
307
308 wxASSERT(m_defering == NO_DEFER);
309
310 m_defering = DEFER_WRITE;
311
39b91eca 312 // Save the old state
a324a7bc
GL
313 old_event_flags = NeededReq();
314 old_notify_state = m_notify_state;
315
316 SetNotify(GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG);
317 Notify(TRUE);
318
39b91eca 319 // Set the current buffer
a324a7bc
GL
320 m_defer_buffer = (char *)buffer;
321 m_defer_nbytes = nbytes;
39b91eca
GL
322
323 // Start timer
324 timer.m_state = (int *)&m_defer_buffer;
e00f35bb 325 timer.m_new_val = 0;
39b91eca
GL
326
327 m_defer_timer = &timer;
328 timer.Start(m_timeout * 1000, FALSE);
329
a324a7bc
GL
330 while (m_defer_buffer != NULL)
331 wxYield();
332
39b91eca
GL
333 // Stop timer
334 m_defer_timer = NULL;
335 timer.Stop();
336
337 // Restore the old state
a324a7bc
GL
338 Notify(old_notify_state);
339 SetNotify(old_event_flags);
340
341 m_defering = NO_DEFER;
342
343 return nbytes-m_defer_nbytes;
344}
345
f4ada568
GL
346wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes)
347{
a324a7bc
GL
348 int ret;
349
350 if ((m_flags & SPEED) != 0)
351 ret = GSocket_Write(m_socket, buffer, nbytes);
352 else
353 ret = DeferWrite(buffer, nbytes);
354
355 if (ret != -1)
356 m_lcount += ret;
357
f4ada568
GL
358 return *this;
359}
360
062c4861
GL
361wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes)
362{
363 struct {
364 char sig[4];
365 char len[4];
366 } msg;
367
368 // warning about 'cast truncates constant value'
369#ifdef __VISUALC__
370 #pragma warning(disable: 4310)
371#endif // __VISUALC__
372
373 msg.sig[0] = (char) 0xad;
374 msg.sig[1] = (char) 0xde;
375 msg.sig[2] = (char) 0xed;
376 msg.sig[3] = (char) 0xfe;
377
378 msg.len[0] = (char) nbytes & 0xff;
379 msg.len[1] = (char) (nbytes >> 8) & 0xff;
380 msg.len[2] = (char) (nbytes >> 16) & 0xff;
381 msg.len[3] = (char) (nbytes >> 24) & 0xff;
382
383 if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg))
384 return *this;
385 if (Write(buffer, nbytes).LastCount() < nbytes)
386 return *this;
387
388 msg.sig[0] = (char) 0xed;
389 msg.sig[1] = (char) 0xfe;
390 msg.sig[2] = (char) 0xad;
391 msg.sig[3] = (char) 0xde;
392 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
393 Write((char *)&msg, sizeof(msg));
394
395 return *this;
396
397#ifdef __VISUALC__
398 #pragma warning(default: 4310)
399#endif // __VISUALC__
400}
401
f4ada568
GL
402wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes)
403{
062c4861
GL
404 m_lcount = 0;
405 if (nbytes != 0) {
406 CreatePushbackAfter(buffer, nbytes);
407 m_lcount = nbytes;
408 }
f4ada568
GL
409 return *this;
410}
411
412bool wxSocketBase::IsData() const
413{
a324a7bc 414 if (!m_socket)
f4ada568 415 return FALSE;
f4ada568 416
a324a7bc
GL
417 return (GSocket_DataAvailable(m_socket));
418}
419
420void wxSocketBase::DoDefer(GSocketEvent req_evt)
421{
422 int ret;
a737331d 423
a324a7bc
GL
424 if (req_evt == GSOCK_LOST) {
425 Close();
426 m_defer_buffer = NULL;
427 return;
428 }
429 switch (m_defering) {
430 case DEFER_READ:
431 ret = GSocket_Read(m_socket, m_defer_buffer, m_defer_nbytes);
432 break;
433 case DEFER_WRITE:
434 ret = GSocket_Write(m_socket, m_defer_buffer, m_defer_nbytes);
435 break;
436 default:
437 ret = -1;
438 break;
439 }
a737331d 440
a324a7bc 441 m_defer_nbytes -= ret;
a737331d 442
a324a7bc
GL
443 if (ret < 0)
444 m_defer_nbytes++;
445
39b91eca
GL
446 // If we are waiting for all bytes to be acquired, keep the defering modei
447 // enabled.
a324a7bc
GL
448 if ((m_flags & WAITALL) == 0 || m_defer_nbytes == 0 || ret < 0) {
449 m_defer_buffer = NULL;
450 Notify(FALSE);
39b91eca 451 } else {
a324a7bc 452 m_defer_buffer += ret;
39b91eca
GL
453 m_defer_timer->Start(m_timeout * 1000, FALSE);
454 }
f4ada568
GL
455}
456
457// ---------------------------------------------------------------------
458// --------- wxSocketBase Discard(): deletes all byte in the input queue
459// ---------------------------------------------------------------------
460void wxSocketBase::Discard()
461{
462#define MAX_BUFSIZE (10*1024)
463 char *my_data = new char[MAX_BUFSIZE];
464 size_t recv_size = MAX_BUFSIZE;
465
466 SaveState();
dbd300df 467 SetFlags(NOWAIT | SPEED);
384b4373 468
31528cd3 469 while (recv_size == MAX_BUFSIZE)
8c14576d 470 {
f4ada568
GL
471 recv_size = Read(my_data, MAX_BUFSIZE).LastCount();
472 }
473
474 RestoreState();
475 delete [] my_data;
476
477#undef MAX_BUFSIZE
478}
479
480// --------------------------------------------------------------
8c14576d 481// wxSocketBase socket info functions
f4ada568 482// --------------------------------------------------------------
8c14576d 483
f4ada568
GL
484bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
485{
a324a7bc 486 GAddress *peer;
f4ada568 487
a324a7bc 488 if (!m_socket)
f4ada568
GL
489 return FALSE;
490
a324a7bc
GL
491 peer = GSocket_GetPeer(m_socket);
492 addr_man.SetAddress(peer);
493 GAddress_destroy(peer);
a737331d 494
f4ada568
GL
495 return TRUE;
496}
497
498bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
499{
a324a7bc 500 GAddress *local;
f4ada568 501
a324a7bc 502 if (!m_socket)
f4ada568
GL
503 return FALSE;
504
a324a7bc
GL
505 local = GSocket_GetLocal(m_socket);
506 addr_man.SetAddress(local);
507 GAddress_destroy(local);
f4ada568 508
f4ada568
GL
509 return TRUE;
510}
511
512// --------------------------------------------------------------
8c14576d 513// wxSocketBase wait functions
f4ada568 514// --------------------------------------------------------------
db131261 515
f4ada568
GL
516void wxSocketBase::SaveState()
517{
a324a7bc
GL
518 wxSocketState *state;
519
520 state = new wxSocketState();
f4ada568 521
a737331d
GL
522 state->notify_state = m_notify_state;
523 state->evt_notify_state = m_neededreq;
524 state->socket_flags = m_flags;
525 state->c_callback = m_cbk;
526 state->c_callback_data = m_cdata;
f4ada568 527
a324a7bc 528 m_states.Append(state);
f4ada568
GL
529}
530
531void wxSocketBase::RestoreState()
532{
533 wxNode *node;
a324a7bc 534 wxSocketState *state;
f4ada568
GL
535
536 node = m_states.Last();
537 if (!node)
538 return;
539
a324a7bc 540 state = (wxSocketState *)node->Data();
384b4373 541
a737331d
GL
542 SetFlags(state->socket_flags);
543 m_neededreq = state->evt_notify_state;
544 m_cbk = state->c_callback;
545 m_cdata = state->c_callback_data;
546 Notify(state->notify_state);
f4ada568
GL
547
548 delete node;
549 delete state;
550}
551
552// --------------------------------------------------------------
a737331d 553// --------- wxSocketBase callback functions --------------------
f4ada568 554// --------------------------------------------------------------
db131261 555
a737331d 556wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
f4ada568 557{
a737331d 558 wxSockCbk old_cbk = cbk_;
f4ada568 559
a737331d
GL
560 m_cbk = cbk_;
561 return old_cbk;
f4ada568
GL
562}
563
a737331d 564char *wxSocketBase::CallbackData(char *data)
f4ada568 565{
a737331d 566 char *old_data = m_cdata;
f4ada568 567
a737331d
GL
568 m_cdata = data;
569 return old_data;
f4ada568
GL
570}
571
572// --------------------------------------------------------------
a737331d 573// --------- wxSocketBase wait functions ------------------------
f4ada568
GL
574// --------------------------------------------------------------
575
a324a7bc
GL
576static void wx_socket_wait(GSocket *socket, GSocketEvent event, char *cdata)
577{
578 int *state = (int *)cdata;
579
580 *state = event;
581}
582
a737331d 583bool wxSocketBase::_Wait(long seconds, long milliseconds, int type)
375abe3d 584{
a324a7bc 585 bool old_notify_state = m_notify_state;
39b91eca 586 int state = -1;
a324a7bc 587 _wxSocketInternalTimer timer;
375abe3d 588
a324a7bc 589 if (!m_connected || !m_socket)
a737331d 590 return FALSE;
f4ada568 591
39b91eca 592 // Set the variable to change
a324a7bc 593 timer.m_state = &state;
39b91eca 594 timer.m_new_val = GSOCK_MAX_EVENT;
a324a7bc 595
39b91eca 596 // Disable the previous handler
a324a7bc
GL
597 Notify(FALSE);
598
39b91eca 599 // Set the timeout
a324a7bc 600 timer.Start(seconds * 1000 + milliseconds, TRUE);
39b91eca 601 GSocket_SetCallback(m_socket, type, wx_socket_wait, (char *)&state);
f4ada568 602
39b91eca 603 while (state == -1)
a324a7bc 604 wxYield();
f4ada568 605
39b91eca 606 GSocket_UnsetCallback(m_socket, type);
a324a7bc
GL
607 timer.Stop();
608
39b91eca 609 // Notify will restore automatically the old GSocket flags
a324a7bc
GL
610 Notify(old_notify_state);
611
612 return (state != GSOCK_MAX_EVENT);
f4ada568 613}
f4ada568 614
a737331d 615bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 616{
a324a7bc
GL
617 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
618 GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG);
f4ada568 619}
f4ada568 620
a737331d 621bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 622{
a324a7bc 623 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
f4ada568
GL
624}
625
a737331d 626bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 627{
a324a7bc 628 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG);
a737331d 629}
f4ada568 630
a737331d
GL
631bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
632{
a324a7bc 633 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
f4ada568 634}
a737331d
GL
635
636// --------------------------------------------------------------
637// --------- wxSocketBase callback management -------------------
638// --------------------------------------------------------------
f4ada568 639
a324a7bc 640GSocketEventFlags wxSocketBase::EventToNotify(GSocketEvent evt)
f4ada568 641{
31528cd3 642 switch (evt)
db131261 643 {
a324a7bc
GL
644 case GSOCK_INPUT:
645 return GSOCK_INPUT_FLAG;
646 case GSOCK_OUTPUT:
647 return GSOCK_OUTPUT_FLAG;
648 case GSOCK_CONNECTION:
649 return GSOCK_CONNECTION_FLAG;
259d1674 650 case GSOCK_LOST:
a324a7bc
GL
651 return GSOCK_LOST_FLAG;
652 default:
653 return 0;
f4ada568
GL
654 }
655 return 0;
656}
657
658void wxSocketBase::SetFlags(wxSockFlags _flags)
659{
660 m_flags = _flags;
f4ada568
GL
661}
662
a737331d 663wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const
f4ada568 664{
a737331d 665 return m_flags;
f4ada568
GL
666}
667
a324a7bc 668void wxSocketBase::SetNotify(GSocketEventFlags flags)
f4ada568 669{
a737331d
GL
670 /* Check if server */
671 if (m_type != SOCK_SERVER)
a324a7bc 672 flags &= ~GSOCK_CONNECTION_FLAG;
f4ada568 673
a737331d
GL
674 m_neededreq = flags;
675 if (m_neededreq == 0)
a324a7bc 676 Notify(FALSE);
8c14576d 677 else
a737331d 678 Notify(m_notify_state);
f4ada568
GL
679}
680
a324a7bc
GL
681// --------------------------------------------------------------
682// Automatic notifier
683// --------------------------------------------------------------
684
685static void wx_socket_fallback(GSocket *socket, GSocketEvent event, char *cdata)
686{
687 wxSocketBase *sckobj = (wxSocketBase *)cdata;
688
689 sckobj->OnRequest(event);
690}
691
f4ada568
GL
692void wxSocketBase::Notify(bool notify)
693{
aadbdf11 694 m_notify_state = notify;
a324a7bc 695 if (!m_socket)
aadbdf11
GL
696 return;
697
39b91eca 698 GSocket_UnsetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
a324a7bc
GL
699 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
700 if (!notify)
701 return;
702
39b91eca 703 GSocket_SetCallback(m_socket, m_neededreq, wx_socket_fallback, (char *)this);
f4ada568
GL
704}
705
a324a7bc 706void wxSocketBase::OnRequest(GSocketEvent req_evt)
f4ada568 707{
a737331d 708 wxSocketEvent event(m_id);
a324a7bc
GL
709 GSocketEventFlags notify = EventToNotify(req_evt);
710
711 if (m_defering != NO_DEFER) {
712 DoDefer(req_evt);
713 return;
714 }
f4ada568 715
a737331d
GL
716 if ((m_neededreq & notify) == notify) {
717 event.m_socket = this;
718 event.m_skevt = req_evt;
719 ProcessEvent(event);
a324a7bc 720 OldOnNotify(req_evt);
f4ada568 721 }
f4ada568 722
a324a7bc
GL
723 if (req_evt == GSOCK_LOST)
724 Close();
f4ada568
GL
725}
726
a324a7bc 727void wxSocketBase::OldOnNotify(GSocketEvent evt)
f4ada568 728{
f4ada568
GL
729}
730
a737331d
GL
731// --------------------------------------------------------------
732// --------- wxSocketBase functions [Callback, CallbackData] ----
733// --------------------------------------------------------------
f4ada568
GL
734
735void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
736{
737 SetNextHandler(&h_evt);
738 m_id = id;
739}
740
741// --------------------------------------------------------------
742// --------- wxSocketBase pushback library ----------------------
743// --------------------------------------------------------------
db131261 744
f4ada568
GL
745void wxSocketBase::CreatePushbackAfter(const char *buffer, size_t size)
746{
747 char *curr_pos;
748
375abe3d
GL
749 if (m_unread != NULL)
750 m_unread = (char *) realloc(m_unread, m_unrd_size+size);
751 else
752 m_unread = (char *) malloc(size);
a324a7bc 753
f4ada568
GL
754 curr_pos = m_unread + m_unrd_size;
755
756 memcpy(curr_pos, buffer, size);
757 m_unrd_size += size;
758}
759
760void wxSocketBase::CreatePushbackBefore(const char *buffer, size_t size)
761{
a324a7bc
GL
762 if (m_unread == NULL)
763 m_unread = (char *)malloc(size);
764 else {
765 char *tmp;
f4ada568 766
a324a7bc
GL
767 tmp = (char *)malloc(m_unrd_size + size);
768 memcpy(tmp+size, m_unread, m_unrd_size);
41895a05 769 free(m_unread);
a324a7bc
GL
770
771 m_unread = tmp;
41895a05 772 }
31528cd3 773
f4ada568 774 m_unrd_size += size;
a324a7bc
GL
775
776 memcpy(m_unread, buffer, size);
f4ada568
GL
777}
778
779size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek)
780{
781 if (!m_unrd_size)
782 return 0;
783
a324a7bc
GL
784 if (size > (m_unrd_size-m_unrd_cur))
785 size = m_unrd_size-m_unrd_cur;
786 memcpy(buffer, (m_unread+m_unrd_cur), size);
f4ada568
GL
787
788 if (!peek) {
a324a7bc
GL
789 m_unrd_cur += size;
790 if (m_unrd_size == m_unrd_cur) {
f4ada568
GL
791 free(m_unread);
792 m_unread = NULL;
a324a7bc
GL
793 m_unrd_size = 0;
794 m_unrd_cur = 0;
f4ada568
GL
795 }
796 }
797
798 return size;
799}
800
f4ada568 801// --------------------------------------------------------------
8c14576d 802// wxSocketServer
f4ada568
GL
803// --------------------------------------------------------------
804
f4ada568 805wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
17dff81c 806 wxSockFlags flags) :
f4ada568
GL
807 wxSocketBase(flags, SOCK_SERVER)
808{
a324a7bc 809 m_socket = GSocket_new();
f4ada568 810
a324a7bc 811 if (!m_socket)
f4ada568 812 return;
384b4373 813
a324a7bc
GL
814 GSocket_SetLocal(m_socket, addr_man.GetAddress());
815 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR) {
816 GSocket_destroy(m_socket);
817 m_socket = NULL;
f4ada568
GL
818 return;
819 }
a737331d 820
2a4f27f2 821 Notify(TRUE);
f4ada568
GL
822}
823
824// --------------------------------------------------------------
8c14576d 825// wxSocketServer Accept
f4ada568 826// --------------------------------------------------------------
8c14576d 827
f4ada568
GL
828bool wxSocketServer::AcceptWith(wxSocketBase& sock)
829{
a324a7bc 830 GSocket *child_socket;
f4ada568 831
a324a7bc 832 child_socket = GSocket_WaitConnection(m_socket);
384b4373 833
f4ada568 834 sock.m_type = SOCK_INTERNAL;
a324a7bc 835 sock.m_socket = child_socket;
f4ada568
GL
836 sock.m_connected = TRUE;
837
838 return TRUE;
839}
840
841wxSocketBase *wxSocketServer::Accept()
842{
843 wxSocketBase* sock = new wxSocketBase();
844
845 sock->SetFlags((wxSockFlags)m_flags);
846
847 if (!AcceptWith(*sock))
848 return NULL;
849
f4ada568
GL
850 return sock;
851}
852
f4ada568 853// --------------------------------------------------------------
8c14576d 854// wxSocketClient
f4ada568
GL
855// --------------------------------------------------------------
856
857// --------- wxSocketClient CONSTRUCTOR -------------------------
858// --------------------------------------------------------------
859wxSocketClient::wxSocketClient(wxSockFlags _flags) :
17dff81c 860 wxSocketBase(_flags, SOCK_CLIENT)
f4ada568
GL
861{
862}
863
864// --------------------------------------------------------------
865// --------- wxSocketClient DESTRUCTOR --------------------------
866// --------------------------------------------------------------
867wxSocketClient::~wxSocketClient()
868{
869}
870
871// --------------------------------------------------------------
872// --------- wxSocketClient Connect functions -------------------
873// --------------------------------------------------------------
e22036dc 874bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) )
f4ada568 875{
f4ada568
GL
876 if (IsConnected())
877 Close();
878
a324a7bc
GL
879 // This should never happen.
880 if (m_socket)
881 GSocket_destroy(m_socket);
882
a737331d
GL
883 // Initializes all socket stuff ...
884 // --------------------------------
a324a7bc 885 m_socket = GSocket_new();
384b4373 886
a324a7bc 887 if (!m_socket)
f4ada568 888 return FALSE;
384b4373 889
f4ada568
GL
890 m_connected = FALSE;
891
a324a7bc
GL
892 // Update the flags of m_socket.
893 SetFlags(m_flags);
894 GSocket_SetPeer(m_socket, addr_man.GetAddress());
f61815af 895 if (GSocket_Connect(m_socket, GSOCK_STREAMED) != GSOCK_NOERROR)
f4ada568 896 return FALSE;
9111db68 897
a737331d
GL
898 // Enables bg events.
899 // ------------------
f4ada568
GL
900 Notify(TRUE);
901
902 m_connected = TRUE;
903 return TRUE;
904}
905
75ed1d15 906bool wxSocketClient::WaitOnConnect(long seconds, long microseconds)
f4ada568 907{
a324a7bc 908 int ret = _Wait(seconds, microseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG);
384b4373 909
f4ada568
GL
910 if (ret)
911 m_connected = TRUE;
384b4373
RD
912
913 return m_connected;
f4ada568
GL
914}
915
a324a7bc 916void wxSocketClient::OnRequest(GSocketEvent evt)
f4ada568 917{
31528cd3 918 if (evt == GSOCK_CONNECTION)
8c14576d 919 {
31528cd3 920 if (m_connected)
8c14576d 921 {
a324a7bc 922 m_neededreq &= ~GSOCK_CONNECTION_FLAG;
f4ada568
GL
923 return;
924 }
384b4373 925 m_connected = TRUE;
f4ada568
GL
926 return;
927 }
928 wxSocketBase::OnRequest(evt);
929}
930
f4ada568 931// --------------------------------------------------------------
a324a7bc 932// wxSocketEvent
f4ada568 933// --------------------------------------------------------------
f4ada568 934
a324a7bc
GL
935wxSocketEvent::wxSocketEvent(int id)
936 : wxEvent(id)
f4ada568 937{
a324a7bc 938 wxEventType type = (wxEventType)wxEVT_SOCKET;
f4ada568 939
a324a7bc 940 SetEventType(type);
f4ada568
GL
941}
942
a324a7bc 943void wxSocketEvent::CopyObject(wxObject& obj_d) const
f4ada568 944{
a324a7bc 945 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
f4ada568 946
a324a7bc 947 wxEvent::CopyObject(obj_d);
3b4183d8 948
a324a7bc
GL
949 event->m_skevt = m_skevt;
950 event->m_socket = m_socket;
3b4183d8
GL
951}
952
a58d5df4
GL
953// --------------------------------------------------------------------------
954// wxSocketModule
955// --------------------------------------------------------------------------
956class WXDLLEXPORT wxSocketModule: public wxModule {
957 DECLARE_DYNAMIC_CLASS(wxSocketModule)
958 public:
959 bool OnInit() {
31989b0b 960 return GSocket_Init();
a58d5df4
GL
961 }
962 void OnExit() {
ca17eff3 963 GSocket_Cleanup();
a58d5df4
GL
964 }
965};
966
967IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
968
35a4dab7
GL
969#endif
970 // wxUSE_SOCKETS