]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
2 warnings from Solaris build log fixed
[wxWidgets.git] / src / common / socket.cpp
CommitLineData
56d8adc0 1/////////////////////////////////////////////////////////////////////////////
f4ada568
GL
2// Name: socket.cpp
3// Purpose: Socket handler classes
56d8adc0 4// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
f4ada568 5// Created: April 1997
d3ea6527
GRG
6// Copyright: (C) 1999-1997, Guilhem Lavaux
7// (C) 2000-1999, Guillermo Rodriguez Garcia
f4ada568
GL
8// RCS_ID: $Id$
9// License: see wxWindows license
56d8adc0
GRG
10/////////////////////////////////////////////////////////////////////////////
11
384b4373 12#ifdef __GNUG__
f4ada568 13#pragma implementation "socket.h"
f4ada568
GL
14#endif
15
fcc6dddd
JS
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
35a4dab7
GL
23#if wxUSE_SOCKETS
24
f4ada568
GL
25/////////////////////////////////////////////////////////////////////////////
26// wxWindows headers
27/////////////////////////////////////////////////////////////////////////////
81b92e17 28
dc5c1114 29#include "wx/app.h"
56d8adc0
GRG
30#include "wx/defs.h"
31#include "wx/object.h"
32#include "wx/string.h"
33#include "wx/timer.h"
34#include "wx/utils.h"
35#include "wx/module.h"
36#include "wx/log.h"
58c837a4 37#include "wx/intl.h"
7f555861 38
f4ada568
GL
39/////////////////////////////////////////////////////////////////////////////
40// wxSocket headers
41/////////////////////////////////////////////////////////////////////////////
81b92e17 42
56d8adc0
GRG
43#include "wx/sckaddr.h"
44#include "wx/socket.h"
3b4183d8 45
dc5c1114
GRG
46// discard buffer
47#define MAX_DISCARD_SIZE (10 * 1024)
96db102a 48
dc5c1114 49// what to do within waits
81b92e17 50#define PROCESS_EVENTS() wxYield()
96db102a 51
dc5c1114
GRG
52// use wxPostEvent or not
53#define EXPERIMENTAL_USE_POST 1
54
f4ada568
GL
55// --------------------------------------------------------------
56// ClassInfos
57// --------------------------------------------------------------
81b92e17 58
a737331d
GL
59IMPLEMENT_CLASS(wxSocketBase, wxObject)
60IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
61IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
dc5c1114 62IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
a737331d 63IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
f4ada568 64
56d8adc0
GRG
65class wxSocketState : public wxObject
66{
a324a7bc 67public:
81b92e17
GRG
68 bool m_notify_state;
69 GSocketEventFlags m_neededreq;
70 wxSockFlags m_flags;
71 wxSocketBase::wxSockCbk m_cbk;
72 char *m_cdata;
a324a7bc
GL
73
74public:
75 wxSocketState() : wxObject() {}
76};
77
f4ada568 78// --------------------------------------------------------------
56d8adc0 79// wxSocketBase ctor and dtor
f4ada568 80// --------------------------------------------------------------
56d8adc0 81
a64a02ef 82wxSocketBase::wxSocketBase(wxSockFlags _flags, wxSockType _type) :
f4ada568 83 wxEvtHandler(),
dc5c1114 84 m_socket(NULL), m_evt_handler(NULL), m_id(-1),
96db102a
GRG
85 m_flags(_flags), m_type(_type),
86 m_neededreq(0), m_notify_state(FALSE),
d80d1aba 87 m_connected(FALSE), m_establishing(FALSE),
96db102a
GRG
88 m_reading(FALSE), m_writing(FALSE),
89 m_error(FALSE), m_lcount(0), m_timeout(600), m_states(),
90 m_unread(NULL), m_unrd_size(0), m_unrd_cur(0),
96db102a 91 m_cbk(NULL), m_cdata(NULL)
f4ada568 92{
f4ada568
GL
93}
94
95wxSocketBase::wxSocketBase() :
96 wxEvtHandler(),
dc5c1114 97 m_socket(NULL), m_evt_handler(NULL), m_id(-1),
96db102a
GRG
98 m_flags(NONE), m_type(SOCK_UNINIT),
99 m_neededreq(0), m_notify_state(FALSE),
d80d1aba 100 m_connected(FALSE), m_establishing(FALSE),
96db102a
GRG
101 m_reading(FALSE), m_writing(FALSE),
102 m_error(FALSE), m_lcount(0), m_timeout(600), m_states(),
103 m_unread(NULL), m_unrd_size(0), m_unrd_cur(0),
96db102a 104 m_cbk(NULL), m_cdata(NULL)
f4ada568 105{
f4ada568
GL
106}
107
f4ada568
GL
108wxSocketBase::~wxSocketBase()
109{
f4ada568
GL
110 if (m_unread)
111 free(m_unread);
a737331d 112
56d8adc0 113 // Shutdown and close the socket
a324a7bc 114 Close();
f4ada568 115
56d8adc0 116 // Destroy the GSocket object
a324a7bc
GL
117 if (m_socket)
118 GSocket_destroy(m_socket);
f4ada568
GL
119}
120
121bool wxSocketBase::Close()
122{
81b92e17
GRG
123 // Interrupt pending waits
124 InterruptAllWaits();
125
31528cd3 126 if (m_socket)
8c14576d 127 {
56d8adc0
GRG
128 // Disable callbacks
129 GSocket_UnsetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
130 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
f4ada568 131
56d8adc0 132 // Shutdown the connection
a324a7bc 133 GSocket_Shutdown(m_socket);
f4ada568 134 m_connected = FALSE;
d80d1aba 135 m_establishing = FALSE;
f4ada568
GL
136 }
137
138 return TRUE;
139}
140
141// --------------------------------------------------------------
56d8adc0 142// wxSocketBase basic IO operations
f4ada568 143// --------------------------------------------------------------
56d8adc0 144
96db102a
GRG
145// All IO operations {Read, Write, ReadMsg, WriteMsg, Peek,
146// Unread, Discard} update m_error and m_lcount.
147//
148// TODO: Should Connect, Accept and AcceptWith update m_error?
17aa2bec 149
56d8adc0
GRG
150class _wxSocketInternalTimer: public wxTimer
151{
152public:
39b91eca 153 int *m_state;
e00f35bb 154 unsigned long m_new_val;
39b91eca
GL
155
156 void Notify()
56d8adc0 157 {
479cd5de 158 *m_state = (int)m_new_val; // Change the value
56d8adc0 159 }
39b91eca 160};
8c14576d 161
aa6d9706 162wxSocketBase& wxSocketBase::Read(char* buffer, wxUint32 nbytes)
f4ada568 163{
96db102a
GRG
164 // Mask read events
165 m_reading = TRUE;
a324a7bc 166
96db102a 167 m_lcount = _Read(buffer, nbytes);
17aa2bec 168
d3ea6527
GRG
169 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
170 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
171 m_error = (m_lcount != nbytes);
172 else
173 m_error = (m_lcount == 0);
f4ada568 174
dc5c1114 175 // Allow read events from now on
96db102a 176 m_reading = FALSE;
17aa2bec 177
96db102a
GRG
178 return *this;
179}
180
181wxUint32 wxSocketBase::_Read(char* buffer, wxUint32 nbytes)
182{
183 int total;
184 int ret = 1;
a324a7bc 185
96db102a
GRG
186 // we try this even if the connection has already been closed.
187 total = GetPushback(buffer, nbytes, FALSE);
188 nbytes -= total;
189 buffer += total;
190
191 // If the socket is not connected, or we have got the whole
192 // needed buffer, return immedately
dc5c1114 193 if (!m_socket || !m_connected || !nbytes)
96db102a 194 return total;
f4ada568 195
af2fd961 196 // Possible combinations (they are checked in this order)
81b92e17
GRG
197 // wxSOCKET_NOWAIT
198 // wxSOCKET_WAITALL | wxSOCKET_BLOCK
199 // wxSOCKET_WAITALL
200 // wxSOCKET_BLOCK
201 // wxSOCKET_NONE
af2fd961 202 //
81b92e17 203 if (m_flags & wxSOCKET_NOWAIT)
af2fd961
GRG
204 {
205 GSocket_SetNonBlocking(m_socket, TRUE);
206 ret = GSocket_Read(m_socket, buffer, nbytes);
207 GSocket_SetNonBlocking(m_socket, FALSE);
208
209 if (ret > 0)
96db102a 210 total += ret;
af2fd961 211 }
dc5c1114 212 else if (m_flags & wxSOCKET_WAITALL)
56d8adc0
GRG
213 {
214 while (ret > 0 && nbytes > 0)
215 {
d3ea6527 216 if (!(m_flags & wxSOCKET_BLOCK) && !WaitForRead())
81b92e17
GRG
217 break;
218
a324a7bc 219 ret = GSocket_Read(m_socket, buffer, nbytes);
a324a7bc 220
81b92e17
GRG
221 if (ret > 0)
222 {
223 total += ret;
224 buffer += ret;
225 nbytes -= ret;
226 }
227 }
56d8adc0 228 }
81b92e17 229 else
56d8adc0 230 {
81b92e17
GRG
231 if ((m_flags & wxSOCKET_BLOCK) || WaitForRead())
232 {
233 ret = GSocket_Read(m_socket, buffer, nbytes);
a324a7bc 234
81b92e17
GRG
235 if (ret > 0)
236 total += ret;
237 }
a324a7bc 238 }
f4ada568 239
96db102a 240 return total;
f4ada568
GL
241}
242
aa6d9706 243wxSocketBase& wxSocketBase::ReadMsg(char* buffer, wxUint32 nbytes)
062c4861 244{
96db102a
GRG
245 wxUint32 len, len2, sig, total;
246 bool error;
17aa2bec 247 int old_flags;
17aa2bec
GRG
248 struct
249 {
96db102a
GRG
250 unsigned char sig[4];
251 unsigned char len[4];
062c4861
GL
252 } msg;
253
96db102a
GRG
254 // Mask read events
255 m_reading = TRUE;
062c4861 256
96db102a
GRG
257 total = 0;
258 error = TRUE;
17aa2bec 259 old_flags = m_flags;
81b92e17 260 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
17aa2bec 261
96db102a
GRG
262 if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
263 goto exit;
062c4861 264
96db102a
GRG
265 sig = (wxUint32)msg.sig[0];
266 sig |= (wxUint32)(msg.sig[1] << 8);
267 sig |= (wxUint32)(msg.sig[2] << 16);
268 sig |= (wxUint32)(msg.sig[3] << 24);
062c4861
GL
269
270 if (sig != 0xfeeddead)
17aa2bec 271 {
58c837a4 272 wxLogWarning( _("TCP: invalid signature returned to ReadMsg."));
96db102a 273 goto exit;
17aa2bec
GRG
274 }
275
96db102a
GRG
276 len = (wxUint32)msg.len[0];
277 len |= (wxUint32)(msg.len[1] << 8);
278 len |= (wxUint32)(msg.len[2] << 16);
279 len |= (wxUint32)(msg.len[3] << 24);
280
281 //wxLogMessage("Readmsg: %d %d %d %d -> len == %d",
282 // msg.len[0], msg.len[1], msg.len[2], msg.len[3], len);
062c4861 283
17aa2bec
GRG
284 if (len > nbytes)
285 {
062c4861
GL
286 len2 = len - nbytes;
287 len = nbytes;
288 }
289 else
290 len2 = 0;
291
96db102a
GRG
292 // This check is necessary so that we don't attemp to read if
293 // the msg was zero bytes long.
294 if (len)
17aa2bec 295 {
96db102a
GRG
296 total = _Read(buffer, len);
297
298 if (total != len)
299 goto exit;
17aa2bec
GRG
300 }
301 if (len2)
302 {
96db102a 303 char *discard_buffer = new char[MAX_DISCARD_SIZE];
17aa2bec
GRG
304 long discard_len;
305
96db102a 306 // NOTE: discarded bytes don't add to m_lcount.
17aa2bec
GRG
307 do
308 {
96db102a 309 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
479cd5de
VZ
310 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
311 len2 -= (wxUint32)discard_len;
17aa2bec
GRG
312 }
313 while ((discard_len > 0) && len2);
314
315 delete [] discard_buffer;
316
317 if (len2 != 0)
96db102a 318 goto exit;
17aa2bec 319 }
96db102a
GRG
320 if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
321 goto exit;
062c4861 322
96db102a
GRG
323 sig = (wxUint32)msg.sig[0];
324 sig |= (wxUint32)(msg.sig[1] << 8);
325 sig |= (wxUint32)(msg.sig[2] << 16);
326 sig |= (wxUint32)(msg.sig[3] << 24);
a324a7bc 327
062c4861 328 if (sig != 0xdeadfeed)
17aa2bec 329 {
223d09f6 330 //wxLogMessage(wxT("Warning: invalid signature returned to ReadMsg"));
96db102a 331 goto exit;
17aa2bec 332 }
062c4861 333
96db102a
GRG
334 // everything was OK
335 error = FALSE;
336
337exit:
338 m_error = error;
339 m_lcount = total;
340 m_reading = FALSE;
17aa2bec 341 SetFlags(old_flags);
96db102a 342
062c4861
GL
343 return *this;
344}
345
aa6d9706 346wxSocketBase& wxSocketBase::Peek(char* buffer, wxUint32 nbytes)
f4ada568 347{
96db102a
GRG
348 // Mask read events
349 m_reading = TRUE;
350
351 m_lcount = _Read(buffer, nbytes);
dc5c1114 352 Pushback(buffer, m_lcount);
96db102a 353
81b92e17
GRG
354 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
355 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
356 m_error = (m_lcount != nbytes);
357 else
358 m_error = (m_lcount == 0);
359
dc5c1114 360 // Allow read events again
96db102a 361 m_reading = FALSE;
f4ada568
GL
362
363 return *this;
364}
365
aa6d9706 366wxSocketBase& wxSocketBase::Write(const char *buffer, wxUint32 nbytes)
f4ada568 367{
96db102a
GRG
368 // Mask write events
369 m_writing = TRUE;
56d8adc0 370
96db102a
GRG
371 m_lcount = _Write(buffer, nbytes);
372
81b92e17
GRG
373 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
374 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
375 m_error = (m_lcount != nbytes);
376 else
377 m_error = (m_lcount == 0);
378
dc5c1114 379 // Allow write events again
96db102a
GRG
380 m_writing = FALSE;
381
96db102a
GRG
382 return *this;
383}
384
385wxUint32 wxSocketBase::_Write(const char *buffer, wxUint32 nbytes)
386{
387 wxUint32 total = 0;
388 int ret = 1;
56d8adc0 389
17aa2bec 390 if (!m_connected || !m_socket)
96db102a 391 return 0;
a324a7bc 392
af2fd961 393 // Possible combinations (they are checked in this order)
81b92e17
GRG
394 // wxSOCKET_NOWAIT
395 // wxSOCKET_WAITALL | wxSOCKET_BLOCK
396 // wxSOCKET_WAITALL
397 // wxSOCKET_BLOCK
398 // wxSOCKET_NONE
af2fd961 399 //
81b92e17 400 if (m_flags & wxSOCKET_NOWAIT)
af2fd961
GRG
401 {
402 GSocket_SetNonBlocking(m_socket, TRUE);
403 ret = GSocket_Write(m_socket, buffer, nbytes);
404 GSocket_SetNonBlocking(m_socket, FALSE);
405
406 if (ret > 0)
96db102a 407 total = ret;
af2fd961 408 }
81b92e17 409 else if (m_flags & wxSOCKET_WAITALL)
56d8adc0
GRG
410 {
411 while (ret > 0 && nbytes > 0)
412 {
d3ea6527 413 if (!(m_flags & wxSOCKET_BLOCK) && !WaitForWrite())
81b92e17
GRG
414 break;
415
56d8adc0 416 ret = GSocket_Write(m_socket, buffer, nbytes);
56d8adc0 417
81b92e17
GRG
418 if (ret > 0)
419 {
420 total += ret;
421 buffer += ret;
422 nbytes -= ret;
423 }
424 }
56d8adc0 425 }
81b92e17 426 else
56d8adc0 427 {
81b92e17
GRG
428 if ((m_flags & wxSOCKET_BLOCK) || WaitForWrite())
429 {
430 ret = GSocket_Write(m_socket, buffer, nbytes);
a324a7bc 431
81b92e17
GRG
432 if (ret > 0)
433 total = ret;
434 }
56d8adc0 435 }
a324a7bc 436
96db102a 437 return total;
f4ada568
GL
438}
439
aa6d9706 440wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, wxUint32 nbytes)
062c4861 441{
96db102a
GRG
442 wxUint32 total;
443 bool error;
17aa2bec 444 int old_flags;
062c4861 445 struct {
96db102a
GRG
446 unsigned char sig[4];
447 unsigned char len[4];
062c4861
GL
448 } msg;
449
96db102a
GRG
450 // Mask write events
451 m_writing = TRUE;
452
453 error = TRUE;
454 total = 0;
455 old_flags = m_flags;
81b92e17 456 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
96db102a 457
062c4861
GL
458 // warning about 'cast truncates constant value'
459#ifdef __VISUALC__
96db102a 460# pragma warning(disable: 4310)
062c4861
GL
461#endif // __VISUALC__
462
96db102a
GRG
463 msg.sig[0] = (unsigned char) 0xad;
464 msg.sig[1] = (unsigned char) 0xde;
465 msg.sig[2] = (unsigned char) 0xed;
466 msg.sig[3] = (unsigned char) 0xfe;
062c4861 467
96db102a
GRG
468 msg.len[0] = (unsigned char) nbytes & 0xff;
469 msg.len[1] = (unsigned char) (nbytes >> 8) & 0xff;
470 msg.len[2] = (unsigned char) (nbytes >> 16) & 0xff;
471 msg.len[3] = (unsigned char) (nbytes >> 24) & 0xff;
062c4861 472
96db102a
GRG
473 //wxLogMessage("Writemsg: %d %d %d %d -> %d",
474 // nbytes & 0xff,
475 // (nbytes >> 8) & 0xff,
476 // (nbytes >> 16) & 0xff,
477 // (nbytes >> 24) & 0xff,
478 // nbytes
479 // );
17aa2bec 480
96db102a
GRG
481 if (_Write((char *)&msg, sizeof(msg)) < sizeof(msg))
482 goto exit;
483
484 total = _Write(buffer, nbytes);
485
486 if (total < nbytes)
487 goto exit;
062c4861 488
96db102a
GRG
489 msg.sig[0] = (unsigned char) 0xed;
490 msg.sig[1] = (unsigned char) 0xfe;
491 msg.sig[2] = (unsigned char) 0xad;
492 msg.sig[3] = (unsigned char) 0xde;
062c4861 493 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
062c4861 494
96db102a
GRG
495 if ((_Write((char *)&msg, sizeof(msg))) < sizeof(msg))
496 goto exit;
17aa2bec 497
96db102a
GRG
498 // everything was OK
499 error = FALSE;
500
501exit:
502 m_error = error;
503 m_lcount = total;
504 m_writing = FALSE;
505
062c4861
GL
506 return *this;
507
508#ifdef __VISUALC__
96db102a 509# pragma warning(default: 4310)
062c4861
GL
510#endif // __VISUALC__
511}
512
aa6d9706 513wxSocketBase& wxSocketBase::Unread(const char *buffer, wxUint32 nbytes)
f4ada568 514{
56d8adc0 515 if (nbytes != 0)
96db102a 516 Pushback(buffer, nbytes);
f4ada568 517
96db102a
GRG
518 m_error = FALSE;
519 m_lcount = nbytes;
f4ada568 520
96db102a 521 return *this;
a324a7bc
GL
522}
523
96db102a 524wxSocketBase& wxSocketBase::Discard()
f4ada568 525{
96db102a 526 int old_flags;
dc5c1114
GRG
527 char *my_data = new char[MAX_DISCARD_SIZE];
528 wxUint32 recv_size = MAX_DISCARD_SIZE;
17aa2bec 529 wxUint32 total = 0;
f4ada568 530
96db102a
GRG
531 // Mask read events
532 m_reading = TRUE;
533
534 old_flags = m_flags;
81b92e17 535 SetFlags(wxSOCKET_NOWAIT);
384b4373 536
dc5c1114 537 while (recv_size == MAX_DISCARD_SIZE)
8c14576d 538 {
dc5c1114 539 recv_size = _Read(my_data, MAX_DISCARD_SIZE);
17aa2bec 540 total += recv_size;
f4ada568
GL
541 }
542
f4ada568 543 delete [] my_data;
17aa2bec
GRG
544 m_lcount = total;
545 m_error = FALSE;
546
dc5c1114 547 // Allow read events again
96db102a
GRG
548 m_reading = FALSE;
549
96db102a 550 return *this;
f4ada568
GL
551}
552
553// --------------------------------------------------------------
56d8adc0 554// wxSocketBase get local or peer addresses
f4ada568 555// --------------------------------------------------------------
8c14576d 556
f4ada568
GL
557bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
558{
a324a7bc 559 GAddress *peer;
f4ada568 560
a324a7bc 561 if (!m_socket)
f4ada568
GL
562 return FALSE;
563
a324a7bc
GL
564 peer = GSocket_GetPeer(m_socket);
565 addr_man.SetAddress(peer);
566 GAddress_destroy(peer);
a737331d 567
f4ada568
GL
568 return TRUE;
569}
570
571bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
572{
a324a7bc 573 GAddress *local;
f4ada568 574
a324a7bc 575 if (!m_socket)
f4ada568
GL
576 return FALSE;
577
a324a7bc
GL
578 local = GSocket_GetLocal(m_socket);
579 addr_man.SetAddress(local);
580 GAddress_destroy(local);
f4ada568 581
f4ada568
GL
582 return TRUE;
583}
584
585// --------------------------------------------------------------
56d8adc0 586// wxSocketBase save and restore socket state
f4ada568 587// --------------------------------------------------------------
db131261 588
f4ada568
GL
589void wxSocketBase::SaveState()
590{
a324a7bc
GL
591 wxSocketState *state;
592
593 state = new wxSocketState();
f4ada568 594
81b92e17
GRG
595 state->m_notify_state = m_notify_state;
596 state->m_neededreq = m_neededreq;
597 state->m_flags = m_flags;
598 state->m_cbk = m_cbk;
599 state->m_cdata = m_cdata;
f4ada568 600
a324a7bc 601 m_states.Append(state);
f4ada568
GL
602}
603
604void wxSocketBase::RestoreState()
605{
606 wxNode *node;
a324a7bc 607 wxSocketState *state;
f4ada568
GL
608
609 node = m_states.Last();
610 if (!node)
611 return;
612
a324a7bc 613 state = (wxSocketState *)node->Data();
384b4373 614
81b92e17
GRG
615 SetFlags(state->m_flags);
616 m_cbk = state->m_cbk;
617 m_cdata = state->m_cdata;
618 m_neededreq = state->m_neededreq;
619 Notify(state->m_notify_state);
f4ada568
GL
620
621 delete node;
622 delete state;
623}
624
f4ada568
GL
625
626// --------------------------------------------------------------
56d8adc0 627// wxSocketBase Wait functions
f4ada568
GL
628// --------------------------------------------------------------
629
d3ea6527
GRG
630// These WaitXXX unctions do not depend on the event system any
631// longer; instead, they poll the socket, using GSocket_Select()
632// to check for the specified combination of event flags, until
633// an event occurs or until the timeout ellapses. The polling
634// loop calls PROCESS_EVENTS(), so this won't block the GUI.
635//
636// XXX: Should it honour the wxSOCKET_BLOCK flag ?
637//
638bool wxSocketBase::_Wait(long seconds, long milliseconds,
639 wxSocketEventFlags flags)
375abe3d 640{
56d8adc0 641 GSocketEventFlags result;
a324a7bc 642 _wxSocketInternalTimer timer;
56d8adc0
GRG
643 long timeout;
644 int state = -1;
375abe3d 645
81b92e17
GRG
646 // Set this to TRUE to interrupt ongoing waits
647 m_interrupt = FALSE;
648
56d8adc0 649 // Check for valid socket
af2fd961
GRG
650 if (!m_socket)
651 return FALSE;
652
653 // If it is not a server, it must be connected or establishing connection
654 if ((m_type != SOCK_SERVER) && (!m_connected && !m_establishing))
a737331d 655 return FALSE;
f4ada568 656
56d8adc0
GRG
657 // Check for valid timeout value
658 if (seconds != -1)
659 timeout = seconds * 1000 + milliseconds;
660 else
661 timeout = m_timeout * 1000;
a324a7bc 662
56d8adc0 663 // Activate timer
96db102a
GRG
664 if (timeout)
665 {
666 timer.m_state = &state;
667 timer.m_new_val = 0;
479cd5de 668 timer.Start((int)timeout, TRUE);
96db102a 669 }
a324a7bc 670
56d8adc0 671 // Active polling (without using events)
af2fd961
GRG
672 //
673 // NOTE: this duplicates some of the code in OnRequest (lost
674 // connection and connection establishment handling) but this
675 // doesn't hurt. It has to be here because the event might
676 // be a bit delayed, and it has to be in OnRequest as well
677 // because maybe the WaitXXX functions are not being used.
678 //
96db102a 679 // Do this at least once (important if timeout == 0, when
d3ea6527 680 // we are just polling). Also, if just polling, do not yield.
81b92e17
GRG
681 //
682 while (state == -1)
56d8adc0 683 {
af2fd961
GRG
684 result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG);
685
686 // Connection lost
687 if (result & GSOCK_LOST_FLAG)
688 {
689 timer.Stop();
af2fd961
GRG
690 Close();
691 return TRUE;
692 }
693
694 // Incoming connection (server) or connection established (client)
695 if (result & GSOCK_CONNECTION_FLAG)
696 {
697 timer.Stop();
698 m_connected = TRUE;
699 m_establishing = FALSE;
700 return TRUE;
701 }
702
81b92e17 703 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
af2fd961 704 {
81b92e17
GRG
705 timer.Stop();
706 return TRUE;
af2fd961
GRG
707 }
708
81b92e17
GRG
709 // Wait more?
710 if ((timeout == 0) || (m_interrupt))
711 break;
d3ea6527
GRG
712 else
713 PROCESS_EVENTS();
56d8adc0 714 }
f4ada568 715
a324a7bc 716 timer.Stop();
af2fd961 717 return FALSE;
f4ada568 718}
f4ada568 719
a737331d 720bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 721{
d80d1aba
GRG
722 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
723 GSOCK_OUTPUT_FLAG |
724 GSOCK_CONNECTION_FLAG |
725 GSOCK_LOST_FLAG);
f4ada568 726}
f4ada568 727
a737331d 728bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 729{
96db102a
GRG
730 // Check pushback buffer
731 if (m_unread)
732 return TRUE;
733
af2fd961 734 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG);
f4ada568
GL
735}
736
a737331d 737bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 738{
af2fd961 739 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
a737331d 740}
f4ada568 741
a737331d
GL
742bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
743{
a324a7bc 744 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
f4ada568 745}
a737331d 746
17aa2bec
GRG
747void wxSocketBase::SetTimeout(long seconds)
748{
749 m_timeout = seconds;
750
751 if (m_socket)
e8f4c584 752 GSocket_SetTimeout(m_socket, m_timeout * 1000);
17aa2bec
GRG
753}
754
a737331d 755// --------------------------------------------------------------
56d8adc0 756// wxSocketBase flags
a737331d 757// --------------------------------------------------------------
f4ada568 758
f4ada568
GL
759void wxSocketBase::SetFlags(wxSockFlags _flags)
760{
761 m_flags = _flags;
f4ada568 762}
f0a56ab0 763
56d8adc0
GRG
764// --------------------------------------------------------------
765// wxSocketBase callback management
766// --------------------------------------------------------------
767
768wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
f4ada568 769{
56d8adc0 770 wxSockCbk old_cbk = cbk_;
f4ada568 771
56d8adc0
GRG
772 m_cbk = cbk_;
773 return old_cbk;
774}
775
776char *wxSocketBase::CallbackData(char *data)
777{
778 char *old_data = m_cdata;
779
780 m_cdata = data;
781 return old_data;
f4ada568
GL
782}
783
a324a7bc 784// --------------------------------------------------------------
56d8adc0 785// wxSocketBase automatic notifier
a324a7bc
GL
786// --------------------------------------------------------------
787
96db102a
GRG
788// All events (INPUT, OUTPUT, CONNECTION, LOST) are now always
789// internally watched; but users will only be notified of those
790// events they are interested in.
791
6e31e940
VZ
792static void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
793 GSocketEvent event, char *cdata)
a324a7bc
GL
794{
795 wxSocketBase *sckobj = (wxSocketBase *)cdata;
796
aa8fb7a0 797 sckobj->OnRequest((wxSocketNotify)event);
a324a7bc
GL
798}
799
56d8adc0 800wxSocketEventFlags wxSocketBase::EventToNotify(wxSocketNotify evt)
f4ada568 801{
56d8adc0
GRG
802 switch (evt)
803 {
804 case GSOCK_INPUT: return GSOCK_INPUT_FLAG;
805 case GSOCK_OUTPUT: return GSOCK_OUTPUT_FLAG;
806 case GSOCK_CONNECTION: return GSOCK_CONNECTION_FLAG;
807 case GSOCK_LOST: return GSOCK_LOST_FLAG;
808 }
809 return 0;
810}
aadbdf11 811
56d8adc0
GRG
812void wxSocketBase::SetNotify(wxSocketEventFlags flags)
813{
814 m_neededreq = flags;
815}
a324a7bc 816
56d8adc0
GRG
817void wxSocketBase::Notify(bool notify)
818{
819 m_notify_state = notify;
f4ada568
GL
820}
821
aa8fb7a0 822void wxSocketBase::OnRequest(wxSocketNotify req_evt)
f4ada568 823{
a737331d 824 wxSocketEvent event(m_id);
56d8adc0 825 wxSocketEventFlags flag = EventToNotify(req_evt);
a324a7bc 826
d3ea6527 827 // dbg("Entering OnRequest (evt %d)\n", req_evt);
96db102a 828
81b92e17 829 switch (req_evt)
d80d1aba 830 {
d3ea6527
GRG
831 // This duplicates some code in _Wait(), but this doesn't
832 // hurt. It has to be here because we don't know whether
833 // WaitXXX will be used, and it has to be in _Wait as well
834 // because the event might be a bit delayed.
835 //
81b92e17 836 case wxSOCKET_CONNECTION :
d80d1aba
GRG
837 m_establishing = FALSE;
838 m_connected = TRUE;
839 break;
840 case wxSOCKET_LOST:
841 Close();
842 break;
f4ada568 843
d3ea6527
GRG
844 // If we are in the middle of a R/W operation, do not
845 // propagate events to users. Also, filter 'late' events
846 // which are no longer valid.
847 //
81b92e17 848 case wxSOCKET_INPUT:
d3ea6527
GRG
849 if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
850 return;
851 else
852 break;
81b92e17
GRG
853
854 case wxSOCKET_OUTPUT:
d3ea6527
GRG
855 if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
856 return;
857 else
858 break;
96db102a
GRG
859 }
860
56d8adc0 861 if (((m_neededreq & flag) == flag) && m_notify_state)
d80d1aba 862 {
d3ea6527 863 // dbg("Evt %d delivered\n", req_evt);
a737331d 864 event.m_socket = this;
de3131e7 865 event.m_skevt = req_evt;
dc5c1114
GRG
866
867 if (m_evt_handler)
868#if EXPERIMENTAL_USE_POST
869 wxPostEvent(m_evt_handler, event);
870#else
871 ProcessEvent(event);
872#endif
56d8adc0 873
81b92e17 874 OldOnNotify(req_evt);
56d8adc0
GRG
875 if (m_cbk)
876 m_cbk(*this, req_evt, m_cdata);
81b92e17 877
f4ada568 878 }
96db102a 879
d3ea6527 880 // dbg("Exiting OnRequest (evt %d)\n", req_evt);
f4ada568
GL
881}
882
6e31e940 883void wxSocketBase::OldOnNotify(wxSocketNotify WXUNUSED(evt))
f4ada568 884{
f4ada568
GL
885}
886
a737331d 887// --------------------------------------------------------------
56d8adc0 888// wxSocketBase set event handler
a737331d 889// --------------------------------------------------------------
f4ada568
GL
890
891void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
892{
dc5c1114 893 m_evt_handler = &h_evt;
f4ada568 894 m_id = id;
dc5c1114
GRG
895
896 SetNextHandler(&h_evt);
f4ada568
GL
897}
898
899// --------------------------------------------------------------
96db102a 900// wxSocketBase pushback
f4ada568 901// --------------------------------------------------------------
db131261 902
96db102a 903void wxSocketBase::Pushback(const char *buffer, wxUint32 size)
f4ada568 904{
dc5c1114
GRG
905 if (!size) return;
906
a324a7bc
GL
907 if (m_unread == NULL)
908 m_unread = (char *)malloc(size);
dc5c1114
GRG
909 else
910 {
a324a7bc 911 char *tmp;
f4ada568 912
a324a7bc
GL
913 tmp = (char *)malloc(m_unrd_size + size);
914 memcpy(tmp+size, m_unread, m_unrd_size);
41895a05 915 free(m_unread);
a324a7bc
GL
916
917 m_unread = tmp;
41895a05 918 }
31528cd3 919
f4ada568 920 m_unrd_size += size;
a324a7bc
GL
921
922 memcpy(m_unread, buffer, size);
f4ada568
GL
923}
924
aa6d9706 925wxUint32 wxSocketBase::GetPushback(char *buffer, wxUint32 size, bool peek)
f4ada568
GL
926{
927 if (!m_unrd_size)
928 return 0;
929
a324a7bc
GL
930 if (size > (m_unrd_size-m_unrd_cur))
931 size = m_unrd_size-m_unrd_cur;
96db102a 932
a324a7bc 933 memcpy(buffer, (m_unread+m_unrd_cur), size);
f4ada568 934
dc5c1114
GRG
935 if (!peek)
936 {
a324a7bc 937 m_unrd_cur += size;
dc5c1114
GRG
938 if (m_unrd_size == m_unrd_cur)
939 {
f4ada568
GL
940 free(m_unread);
941 m_unread = NULL;
a324a7bc
GL
942 m_unrd_size = 0;
943 m_unrd_cur = 0;
f4ada568
GL
944 }
945 }
946
947 return size;
948}
949
f4ada568 950// --------------------------------------------------------------
8c14576d 951// wxSocketServer
f4ada568
GL
952// --------------------------------------------------------------
953
56d8adc0
GRG
954// --------------------------------------------------------------
955// wxSocketServer ctor and dtor
956// --------------------------------------------------------------
957
f4ada568 958wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
17dff81c 959 wxSockFlags flags) :
f4ada568
GL
960 wxSocketBase(flags, SOCK_SERVER)
961{
56d8adc0 962 // Create the socket
a324a7bc 963 m_socket = GSocket_new();
f4ada568 964
a324a7bc 965 if (!m_socket)
f4ada568 966 return;
384b4373 967
56d8adc0 968 // Setup the socket as server
a324a7bc 969 GSocket_SetLocal(m_socket, addr_man.GetAddress());
56d8adc0
GRG
970 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
971 {
a324a7bc
GL
972 GSocket_destroy(m_socket);
973 m_socket = NULL;
f4ada568
GL
974 return;
975 }
a737331d 976
e8f4c584 977 GSocket_SetTimeout(m_socket, m_timeout * 1000);
56d8adc0
GRG
978 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
979 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
980 wx_socket_callback, (char *)this);
981
f4ada568
GL
982}
983
984// --------------------------------------------------------------
8c14576d 985// wxSocketServer Accept
f4ada568 986// --------------------------------------------------------------
8c14576d 987
d80d1aba 988bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 989{
a324a7bc 990 GSocket *child_socket;
f4ada568 991
17aa2bec
GRG
992 if (!m_socket)
993 return FALSE;
994
56d8adc0
GRG
995 // GRG: If wait == FALSE, then the call should be nonblocking.
996 // When we are finished, we put the socket to blocking mode
997 // again.
d80d1aba
GRG
998
999 if (!wait)
1000 GSocket_SetNonBlocking(m_socket, TRUE);
1001
a324a7bc 1002 child_socket = GSocket_WaitConnection(m_socket);
384b4373 1003
d80d1aba
GRG
1004 if (!wait)
1005 GSocket_SetNonBlocking(m_socket, FALSE);
1006
1007 // GRG: this was not being handled!
1008 if (child_socket == NULL)
1009 return FALSE;
1010
f4ada568 1011 sock.m_type = SOCK_INTERNAL;
a324a7bc 1012 sock.m_socket = child_socket;
f4ada568
GL
1013 sock.m_connected = TRUE;
1014
e8f4c584 1015 GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
56d8adc0
GRG
1016 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1017 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1018 wx_socket_callback, (char *)&sock);
1019
f4ada568
GL
1020 return TRUE;
1021}
1022
d80d1aba 1023wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568
GL
1024{
1025 wxSocketBase* sock = new wxSocketBase();
1026
1027 sock->SetFlags((wxSockFlags)m_flags);
1028
d80d1aba 1029 if (!AcceptWith(*sock, wait))
f4ada568
GL
1030 return NULL;
1031
f4ada568
GL
1032 return sock;
1033}
1034
17aa2bec 1035bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1036{
af2fd961 1037 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
d80d1aba
GRG
1038}
1039
f4ada568 1040// --------------------------------------------------------------
8c14576d 1041// wxSocketClient
f4ada568
GL
1042// --------------------------------------------------------------
1043
f4ada568 1044// --------------------------------------------------------------
56d8adc0
GRG
1045// wxSocketClient ctor and dtor
1046// --------------------------------------------------------------
1047
f4ada568 1048wxSocketClient::wxSocketClient(wxSockFlags _flags) :
17dff81c 1049 wxSocketBase(_flags, SOCK_CLIENT)
f4ada568
GL
1050{
1051}
1052
f4ada568
GL
1053wxSocketClient::~wxSocketClient()
1054{
1055}
1056
1057// --------------------------------------------------------------
56d8adc0 1058// wxSocketClient Connect functions
f4ada568 1059// --------------------------------------------------------------
dc5c1114 1060
791b24c4 1061bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
f4ada568 1062{
791b24c4
GRG
1063 GSocketError err;
1064
f4ada568
GL
1065 if (IsConnected())
1066 Close();
1067
a324a7bc
GL
1068 // This should never happen.
1069 if (m_socket)
1070 GSocket_destroy(m_socket);
1071
56d8adc0 1072 // Initialize all socket stuff ...
a324a7bc 1073 m_socket = GSocket_new();
d80d1aba
GRG
1074 m_connected = FALSE;
1075 m_establishing = FALSE;
384b4373 1076
a324a7bc 1077 if (!m_socket)
f4ada568 1078 return FALSE;
384b4373 1079
e8f4c584 1080 GSocket_SetTimeout(m_socket, m_timeout * 1000);
96db102a
GRG
1081 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1082 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1083 wx_socket_callback, (char *)this);
56d8adc0
GRG
1084
1085 // GRG: If wait == FALSE, then the call should be nonblocking.
1086 // When we are finished, we put the socket to blocking mode
1087 // again.
f4ada568 1088
791b24c4
GRG
1089 if (!wait)
1090 GSocket_SetNonBlocking(m_socket, TRUE);
1091
a324a7bc 1092 GSocket_SetPeer(m_socket, addr_man.GetAddress());
791b24c4
GRG
1093 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
1094
1095 if (!wait)
1096 GSocket_SetNonBlocking(m_socket, FALSE);
1097
1098 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1099 {
1100 if (err == GSOCK_WOULDBLOCK)
1101 m_establishing = TRUE;
1102
f4ada568 1103 return FALSE;
56d8adc0 1104 }
9111db68 1105
f4ada568
GL
1106 m_connected = TRUE;
1107 return TRUE;
1108}
1109
d80d1aba 1110bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1111{
af2fd961 1112 if (m_connected) // Already connected
d80d1aba
GRG
1113 return TRUE;
1114
af2fd961 1115 if (!m_establishing || !m_socket) // No connection in progress
d80d1aba
GRG
1116 return FALSE;
1117
af2fd961 1118 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
f4ada568
GL
1119}
1120
dc5c1114
GRG
1121// --------------------------------------------------------------
1122// wxDatagramSocket
1123// --------------------------------------------------------------
1124
1125/* NOTE: experimental stuff - might change */
1126
1127wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr, wxSockFlags flags )
1128 : wxSocketBase( flags, SOCK_DATAGRAM )
1129{
1130 // Create the socket
1131 m_socket = GSocket_new();
1132
1133 if(!m_socket)
1134 return;
1135
1136 // Setup the socket as non connection oriented
1137 GSocket_SetLocal(m_socket, addr.GetAddress());
1138 if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
1139 {
1140 GSocket_destroy(m_socket);
1141 m_socket = NULL;
1142 return;
1143 }
1144
1145 // Initialize all stuff
1146 m_connected = FALSE;
1147 m_establishing = FALSE;
1148 GSocket_SetTimeout( m_socket, m_timeout );
1149 GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1150 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1151 wx_socket_callback, (char*)this );
1152
1153}
1154
1155wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1156 char* buf,
1157 wxUint32 nBytes )
1158{
1159 Read(buf, nBytes);
1160 GetPeer(addr);
1161 return (*this);
1162}
1163
1164wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
1165 const char* buf,
1166 wxUint32 nBytes )
1167{
1168 GSocket_SetPeer(m_socket, addr.GetAddress());
1169 Write(buf, nBytes);
1170 return (*this);
1171}
1172
f4ada568 1173// --------------------------------------------------------------
a324a7bc 1174// wxSocketEvent
f4ada568 1175// --------------------------------------------------------------
f4ada568 1176
a324a7bc
GL
1177wxSocketEvent::wxSocketEvent(int id)
1178 : wxEvent(id)
f4ada568 1179{
a324a7bc 1180 wxEventType type = (wxEventType)wxEVT_SOCKET;
f4ada568 1181
a324a7bc 1182 SetEventType(type);
f4ada568
GL
1183}
1184
a324a7bc 1185void wxSocketEvent::CopyObject(wxObject& obj_d) const
f4ada568 1186{
a324a7bc 1187 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
f4ada568 1188
a324a7bc 1189 wxEvent::CopyObject(obj_d);
3b4183d8 1190
a324a7bc
GL
1191 event->m_skevt = m_skevt;
1192 event->m_socket = m_socket;
3b4183d8
GL
1193}
1194
a58d5df4
GL
1195// --------------------------------------------------------------------------
1196// wxSocketModule
1197// --------------------------------------------------------------------------
dc5c1114
GRG
1198
1199class WXDLLEXPORT wxSocketModule: public wxModule
1200{
a58d5df4 1201 DECLARE_DYNAMIC_CLASS(wxSocketModule)
dc5c1114
GRG
1202public:
1203 bool OnInit()
1204 {
31989b0b 1205 return GSocket_Init();
a58d5df4 1206 }
dc5c1114
GRG
1207 void OnExit()
1208 {
ca17eff3 1209 GSocket_Cleanup();
a58d5df4
GL
1210 }
1211};
1212
1213IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1214
35a4dab7
GL
1215#endif
1216 // wxUSE_SOCKETS