]> git.saurik.com Git - wxWidgets.git/blame - src/common/sckint.cpp
Use wxScrollWinEvent instead of wxScrollEvent in
[wxWidgets.git] / src / common / sckint.cpp
CommitLineData
a737331d 1///////////////////////////////////////////////////////////////////////////////
9111db68
GL
2// Name: sckint.cpp
3// Purpose: Socket internal classes
4// Authors: Guilhem Lavaux
5// Created: April 1999
6// Updated:
a737331d
GL
7// Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux
8// RCS_ID: $Id$
9// License: see wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11#ifdef __GNUG__
12#pragma implementation "sckint.h"
13#endif
14
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19#pragma hdrstop
20#endif
21
22#if wxUSE_SOCKETS
23
24#define WXSOCK_INTERNAL
25#include <wx/object.h>
26#include <wx/list.h>
27#include <wx/socket.h>
28#include <wx/thread.h>
29#include <wx/sckint.h>
30
31#ifndef __WXSTUBS__
32
33#include <stdlib.h>
34#include <string.h>
35#include <ctype.h>
36
37// -----------------------
38// System specific headers
39// -----------------------
40
41#ifdef __WXMAC__
42// in order to avoid problems with our c library and double definitions
43#define close closesocket
44#define ioctl ioctlsocket
45
46#include <wx/mac/macsock.h>
47#endif
48
49#if defined(__WINDOWS__)
50#include <winsock.h>
51#endif // __WINDOWS__
52
53#if defined(__UNIX__)
54
55#ifdef VMS
56#include <socket.h>
57#else
58#include <sys/socket.h>
59#endif
60#include <sys/ioctl.h>
61
62#include <sys/time.h>
63#include <unistd.h>
64
65#ifdef sun
66#include <sys/filio.h>
67#endif
68
69#endif // __UNIX__
70
71#include <signal.h>
72#include <errno.h>
73
74#ifdef __VISUALC__
75#include <io.h>
76#endif
77
78// Constants
79#define READ_MASK wxSocketBase::REQ_READ | wxSocketBase::REQ_ACCEPT | wxSocketBase::REQ_LOST
80#define WRITE_MASK wxSocketBase::REQ_WRITE | wxSocketBase::REQ_CONNECT
81
82// --------------------------------------------------------------
83// --------- SocketWaiter ---------------------------------------
84// --------------------------------------------------------------
85
ba9838b9 86#if wxUSE_THREADS
a737331d
GL
87SocketWaiter::SocketWaiter(wxSocketBase *socket,
88 wxSocketInternal *internal)
9111db68
GL
89 : wxThread(),
90 m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
a737331d
GL
91{
92}
93
94SocketWaiter::~SocketWaiter()
95{
96}
97
98void SocketWaiter::ProcessReadEvent()
99{
100 int ret;
101 char c;
102
103 ret = recv(m_fd, &c, 1, MSG_PEEK);
104
105 // We are a server => emit a EVT_ACCEPT event.
106 if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) {
107 m_socket->OnRequest(wxSocketBase::EVT_ACCEPT);
108 return;
109 }
110
111 // Else, no error => there is something to be read else
112 // we've lost the connection.
9111db68 113 if (ret > 0) {
a737331d 114 m_socket->OnRequest(wxSocketBase::EVT_READ);
9111db68 115 } else {
a737331d
GL
116 m_socket->OnRequest(wxSocketBase::EVT_LOST);
117 Exit(NULL);
118 }
119}
120
121void SocketWaiter::ProcessWriteEvent()
122{
123 if (m_socket->IsConnected())
124 m_socket->OnRequest(wxSocketBase::EVT_CONNECT);
125 else
126 m_socket->OnRequest(wxSocketBase::EVT_WRITE);
127}
128
129void *SocketWaiter::Entry()
130{
131 struct timeval tv;
132 fd_set sockrd_set, sockwr_set;
133 wxSocketEvent event;
134 int ret;
135
136 while (1) {
137 // We won't wait.
138 tv.tv_sec = 0;
139 tv.tv_usec = 0;
140
141 FD_ZERO(&sockrd_set);
142 FD_ZERO(&sockwr_set);
9111db68 143
a737331d
GL
144 if ((m_socket->NeededReq() & READ_MASK) != 0)
145 FD_SET(m_fd, &sockrd_set);
146 if ((m_socket->NeededReq() & WRITE_MASK) != 0)
147 FD_SET(m_fd, &sockwr_set);
148
149 m_internal->AcquireFD();
9111db68 150 ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
a737331d
GL
151 m_internal->ReleaseFD();
152
153 if (FD_ISSET(m_fd, &sockrd_set))
154 ProcessReadEvent();
155
156 if (FD_ISSET(m_fd, &sockwr_set))
157 ProcessWriteEvent();
158
70190256
JS
159#if wxUSE_THREADS
160#ifdef Yield
161#undef Yield
162#endif
aadbdf11 163#endif
70190256 164
70190256
JS
165 if (ret == 0)
166 // If nothing happened, we wait for 100 ms.
167 wxUsleep(10);
a737331d
GL
168
169 // Check whether we should exit.
2a4f27f2 170 if (TestDestroy()) {
a737331d 171 return NULL;
2a4f27f2
GL
172 }
173 }
a737331d
GL
174 return NULL;
175}
176
177// --------------------------------------------------------------
178// --------- SocketRequester ------------------------------------
179// --------------------------------------------------------------
180
181SocketRequester::SocketRequester(wxSocketBase *socket,
182 wxSocketInternal *internal)
9111db68
GL
183 : wxThread(),
184 m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
a737331d
GL
185{
186}
187
188SocketRequester::~SocketRequester()
189{
190}
191
192bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec)
193{
194 int ret;
195 struct timeval tv;
196 fd_set sockrd_set, sockwr_set;
197
198 // We won't wait.
199 tv.tv_sec = millisec / 1000;
200 tv.tv_usec = (millisec % 1000) * 1000;
201
202 if ((req & READ_MASK) != 0)
203 FD_ZERO(&sockrd_set);
204 FD_ZERO(&sockwr_set);
205
206 FD_SET(m_fd, &sockrd_set);
207 FD_SET(m_fd, &sockwr_set);
208
209 m_internal->AcquireFD();
9111db68 210 ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
a737331d
GL
211 m_internal->ReleaseFD();
212
213 return (ret != 0);
214}
215
216void SocketRequester::ProcessReadEvent(SockRequest *req)
217{
218 int ret;
219 size_t len;
220
221 // We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately
222 if (!WaitFor(wxSocketBase::REQ_READ, req->timeout)) {
223 m_internal->EndRequest(req);
224 return;
225 }
226
227 m_internal->AcquireFD();
228 ret = recv(m_fd, req->buffer, req->size,
229 (req->type == wxSocketBase::REQ_PEEK) ? MSG_PEEK : 0);
230 m_internal->ReleaseFD();
231
232 // An error occured, we exit.
233 if (ret < 0) {
234 req->error = errno;
235 m_internal->EndRequest(req);
236 return;
237 }
238 len = ret;
239
240 // If the buffer isn't full (and we want it to be full), we don't unqueue it.
241 if ((len < req->size) && (m_socket->GetFlags() & wxSocketBase::WAITALL)) {
242 req->size -= len;
243 req->io_nbytes += len;
244 req->buffer += len;
245 return;
246 }
247 // The End.
248 req->io_nbytes += len;
249 m_internal->EndRequest(req);
250}
251
252void SocketRequester::ProcessWriteEvent(SockRequest *req)
253{
254 int ret;
255 size_t len;
256
9111db68
GL
257 if (!WaitFor(wxSocketBase::REQ_WRITE, req->timeout)) {
258 m_internal->EndRequest(req);
259 return;
260 }
261
a737331d
GL
262 m_internal->AcquireFD();
263 ret = send(m_fd, req->buffer, req->size, 0);
264 m_internal->ReleaseFD();
265 if (ret < 0) {
266 req->error = errno;
267 m_internal->EndRequest(req);
268 return;
269 }
270 len = ret;
271 if ((len < req->size) && ((m_socket->GetFlags() & wxSocketBase::WAITALL) != 0)) {
272 req->size -= len;
273 req->io_nbytes += len;
274 req->buffer += len;
275 return;
276 }
277 req->io_nbytes += len;
278 m_internal->EndRequest(req);
279}
280
281void SocketRequester::ProcessWaitEvent(SockRequest *req)
282{
283 if (WaitFor(req->type, req->timeout))
284 req->io_nbytes = 1; // We put 1 in the counter to tell the requester
285 // there is no timeout.
286 else
287 req->io_nbytes = 0;
288
289 m_internal->EndRequest(req);
290}
291
292void *SocketRequester::Entry()
293{
294 SockRequest *req;
295
9111db68 296 m_internal->m_request_locker.Lock();
a737331d
GL
297 while (1) {
298 // Wait for a new request or a destroy message.
299 req = m_internal->WaitForReq();
63496c98 300 m_internal->m_end_requester.Lock();
9111db68 301 if (req == NULL) {
63496c98
GL
302 m_internal->m_invalid_requester = TRUE;
303 m_internal->m_end_requester.Unlock();
9111db68 304 m_internal->m_request_locker.Unlock();
a737331d 305 return NULL;
63496c98
GL
306 }
307 m_internal->m_end_requester.Unlock();
a737331d
GL
308
309 if ((req->type & wxSocketBase::REQ_WAIT) != 0) {
310 ProcessWaitEvent(req);
311 continue;
312 }
313
314 switch (req->type) {
315 case wxSocketBase::REQ_READ:
316 case wxSocketBase::REQ_PEEK:
317 ProcessReadEvent(req);
318 break;
319 case wxSocketBase::REQ_WRITE:
320 ProcessWriteEvent(req);
321 break;
322 }
323 }
324 return NULL;
325}
ba9838b9 326#endif
a737331d
GL
327
328// --------------------------------------------------------------
329// --------- wxSocketInternal -----------------------------------
330// --------------------------------------------------------------
331
332wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
333{
334 m_socket = socket;
ba9838b9 335#if wxUSE_THREADS
2a4f27f2
GL
336 m_thread_requester = NULL;
337 m_thread_waiter = NULL;
63496c98 338 m_invalid_requester = TRUE;
ba9838b9 339#endif
a737331d
GL
340}
341
342wxSocketInternal::~wxSocketInternal()
343{
ba9838b9 344#if wxUSE_THREADS
63496c98 345 StopRequester();
2a4f27f2 346 wxASSERT(m_thread_requester == NULL);
63496c98 347 StopWaiter();
2a4f27f2 348 wxASSERT(m_thread_waiter == NULL);
ba9838b9 349#endif
a737331d
GL
350}
351
352// ----------------------------------------------------------------------
353// WaitForReq: it is called by SocketRequester and should return the next
354// socket request if available
355// ----------------------------------------------------------------------
356SockRequest *wxSocketInternal::WaitForReq()
357{
ba9838b9 358#if wxUSE_THREADS
a737331d
GL
359 wxNode *node;
360
361 node = m_requests.First();
362 if (node == NULL) {
9111db68 363 m_socket_cond.Wait(m_request_locker, 10, 0);
a737331d
GL
364
365 node = m_requests.First();
366 if (node == NULL)
367 return NULL;
368 }
369
370 return (SockRequest *)node->Data();
ba9838b9
JS
371#else
372 return NULL;
373#endif
a737331d
GL
374}
375
376// ----------------------------------------------------------------------
377// EndRequest: Should be called to finalize a request
378// ----------------------------------------------------------------------
379void wxSocketInternal::EndRequest(SockRequest *req)
380{
381 wxNode *node = NULL;
382
383 req->done = TRUE;
384
385 node = m_requests.Member((wxObject *)req);
386 if (node != NULL)
387 delete node;
388}
389
390void wxSocketInternal::AcquireFD()
391{
ba9838b9 392#if wxUSE_THREADS
a737331d 393 m_fd_locker.Lock();
ba9838b9 394#endif
a737331d
GL
395}
396
397void wxSocketInternal::ReleaseFD()
398{
ba9838b9 399#if wxUSE_THREADS
a737331d 400 m_fd_locker.Unlock();
ba9838b9 401#endif
a737331d
GL
402}
403
2a4f27f2 404void wxSocketInternal::ResumeRequester()
a737331d 405{
ba9838b9 406#if wxUSE_THREADS
2a4f27f2 407 wxThreadError err;
a737331d 408
9111db68 409 wxASSERT(m_thread_requester == NULL || m_invalid_requester);
a737331d 410
63496c98
GL
411 m_end_requester.Lock();
412 if (m_invalid_requester) {
9111db68
GL
413 if (m_thread_requester != NULL)
414 delete m_thread_requester;
415 m_invalid_requester = FALSE;
416 }
417 m_end_requester.Unlock();
a737331d 418
9111db68 419 m_thread_requester = new SocketRequester(m_socket, this);
aadbdf11 420
9111db68
GL
421 err = m_thread_requester->Create();
422 wxASSERT(err == wxTHREAD_NO_ERROR);
63496c98 423
9111db68
GL
424 err = m_thread_requester->Run();
425 wxASSERT(err == wxTHREAD_NO_ERROR);
63496c98 426
ba9838b9 427#endif
a737331d
GL
428}
429
2a4f27f2 430void wxSocketInternal::StopRequester()
a737331d 431{
ba9838b9 432#if wxUSE_THREADS
9111db68 433 m_end_requester.Lock();
63496c98 434 if (m_invalid_requester) {
9111db68 435 m_end_requester.Unlock();
63496c98
GL
436 delete m_thread_requester;
437 m_thread_requester = NULL;
438 m_invalid_requester = FALSE;
439 return;
440 }
9111db68 441 m_end_requester.Unlock();
63496c98 442
2a4f27f2 443 wxASSERT(m_thread_requester != NULL);
aadbdf11 444
a737331d 445 m_socket_locker.Lock();
2a4f27f2
GL
446
447 // Send a signal to the requester.
9111db68 448 m_socket_cond.Signal();
2a4f27f2 449
a737331d
GL
450 m_socket_locker.Unlock();
451
2a4f27f2 452 // Finish the destruction of the requester.
a737331d 453 m_thread_requester->Delete();
a737331d 454
2a4f27f2
GL
455 delete m_thread_requester;
456 m_thread_requester = NULL;
ba9838b9 457#endif
a737331d
GL
458}
459
2a4f27f2 460void wxSocketInternal::ResumeWaiter()
a737331d 461{
ba9838b9 462#if wxUSE_THREADS
2a4f27f2 463 wxThreadError err;
a737331d 464
2a4f27f2 465 if (m_thread_waiter != NULL)
aadbdf11
GL
466 return;
467
2a4f27f2 468 m_thread_waiter = new SocketWaiter(m_socket, this);
2a4f27f2
GL
469
470 err = m_thread_waiter->Create();
471 wxASSERT(err == wxTHREAD_NO_ERROR);
472
473 err = m_thread_waiter->Run();
474 wxASSERT(err == wxTHREAD_NO_ERROR);
ba9838b9 475#endif
a737331d
GL
476}
477
2a4f27f2 478void wxSocketInternal::StopWaiter()
a737331d 479{
ba9838b9 480#if wxUSE_THREADS
2a4f27f2 481 if (m_thread_waiter == NULL)
aadbdf11
GL
482 return;
483
2a4f27f2
GL
484 m_thread_waiter->Delete();
485
486 delete m_thread_waiter;
487 m_thread_waiter = NULL;
ba9838b9 488#endif
a737331d
GL
489}
490
491// ----------------------------------------------------------------------
492// QueueRequest:
493// ----------------------------------------------------------------------
494void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
495{
ba9838b9 496#if wxUSE_THREADS
9111db68
GL
497/*
498 if (m_invalid_requester)
499 ResumeRequester();
500*/
501 m_thread_requester = new SocketRequester(m_socket, this);
502
503/*
a737331d 504 if (async) {
2a4f27f2 505
a737331d
GL
506 m_request_locker.Lock();
507 request->done = FALSE;
508 m_requests.Append((wxObject *)request);
aadbdf11 509 m_socket_cond.Signal();
a737331d
GL
510 m_request_locker.Unlock();
511
512 // Wake up
a737331d
GL
513
514 if (request->wait) {
515 if (wxThread::IsMain())
516 while (!request->done) {
517 wxYield();
518 }
519 else
520 while (!request->done) {
521 wxThread::Yield();
522 }
523 }
a737331d 524 } else {
9111db68 525*/
a737331d
GL
526 m_request_locker.Lock();
527
528 if ((request->type & wxSocketBase::REQ_WAIT) != 0) {
529 m_thread_requester->ProcessWaitEvent(request);
530 } else {
531
532 request->done = FALSE;
533
534 switch (request->type) {
535 case wxSocketBase::REQ_PEEK:
536 case wxSocketBase::REQ_READ:
537 m_thread_requester->ProcessReadEvent(request);
538 break;
539 case wxSocketBase::REQ_WRITE:
540 m_thread_requester->ProcessWriteEvent(request);
541 break;
542 }
543 }
544 request->done = TRUE;
545 m_request_locker.Unlock();
9111db68
GL
546// }
547 delete m_thread_requester;
548 m_thread_requester = NULL;
ba9838b9 549#endif
a737331d
GL
550}
551
552void wxSocketInternal::WaitForEnd(SockRequest *request)
553{
ba9838b9 554#if wxUSE_THREADS
a737331d 555 // TODOTODO
ba9838b9 556#endif
a737331d
GL
557}
558
559#endif
560 // __WXSTUBS__
561
562#endif
563 // wxUSE_SOCKETS