]> git.saurik.com Git - wxWidgets.git/blob - src/common/sckint.cpp
* prgodlgg.h: Update() use wxString instead of 'char *'
[wxWidgets.git] / src / common / sckint.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: sckint.cpp
3 // Purpose: Socket internal classes
4 // Authors: Guilhem Lavaux
5 // Created: April 1999
6 // Updated:
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
86 #if wxUSE_THREADS
87 SocketWaiter::SocketWaiter(wxSocketBase *socket,
88 wxSocketInternal *internal)
89 : wxThread(),
90 m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
91 {
92 }
93
94 SocketWaiter::~SocketWaiter()
95 {
96 }
97
98 void 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.
113 if (ret > 0) {
114 m_socket->OnRequest(wxSocketBase::EVT_READ);
115 } else {
116 m_socket->OnRequest(wxSocketBase::EVT_LOST);
117 Exit(NULL);
118 }
119 }
120
121 void 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
129 void *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);
143
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();
150 ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
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
159 #if wxUSE_THREADS
160 #ifdef Yield
161 #undef Yield
162 #endif
163 #endif
164
165 if (ret == 0)
166 // If nothing happened, we wait for 100 ms.
167 wxUsleep(10);
168
169 // Check whether we should exit.
170 if (TestDestroy()) {
171 return NULL;
172 }
173 }
174 return NULL;
175 }
176
177 // --------------------------------------------------------------
178 // --------- SocketRequester ------------------------------------
179 // --------------------------------------------------------------
180
181 SocketRequester::SocketRequester(wxSocketBase *socket,
182 wxSocketInternal *internal)
183 : wxThread(),
184 m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
185 {
186 }
187
188 SocketRequester::~SocketRequester()
189 {
190 }
191
192 bool 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();
210 ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
211 m_internal->ReleaseFD();
212
213 return (ret != 0);
214 }
215
216 void 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
252 void SocketRequester::ProcessWriteEvent(SockRequest *req)
253 {
254 int ret;
255 size_t len;
256
257 if (!WaitFor(wxSocketBase::REQ_WRITE, req->timeout)) {
258 m_internal->EndRequest(req);
259 return;
260 }
261
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
281 void 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
292 void *SocketRequester::Entry()
293 {
294 SockRequest *req;
295
296 m_internal->m_request_locker.Lock();
297 while (1) {
298 // Wait for a new request or a destroy message.
299 req = m_internal->WaitForReq();
300 m_internal->m_end_requester.Lock();
301 if (req == NULL) {
302 m_internal->m_invalid_requester = TRUE;
303 m_internal->m_end_requester.Unlock();
304 m_internal->m_request_locker.Unlock();
305 return NULL;
306 }
307 m_internal->m_end_requester.Unlock();
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 }
326 #endif
327
328 // --------------------------------------------------------------
329 // --------- wxSocketInternal -----------------------------------
330 // --------------------------------------------------------------
331
332 wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
333 {
334 m_socket = socket;
335 #if wxUSE_THREADS
336 m_thread_requester = NULL;
337 m_thread_waiter = NULL;
338 m_invalid_requester = TRUE;
339 #endif
340 }
341
342 wxSocketInternal::~wxSocketInternal()
343 {
344 #if wxUSE_THREADS
345 StopRequester();
346 wxASSERT(m_thread_requester == NULL);
347 StopWaiter();
348 wxASSERT(m_thread_waiter == NULL);
349 #endif
350 }
351
352 // ----------------------------------------------------------------------
353 // WaitForReq: it is called by SocketRequester and should return the next
354 // socket request if available
355 // ----------------------------------------------------------------------
356 SockRequest *wxSocketInternal::WaitForReq()
357 {
358 #if wxUSE_THREADS
359 wxNode *node;
360
361 node = m_requests.First();
362 if (node == NULL) {
363 m_socket_cond.Wait(m_request_locker, 10, 0);
364
365 node = m_requests.First();
366 if (node == NULL)
367 return NULL;
368 }
369
370 return (SockRequest *)node->Data();
371 #else
372 return NULL;
373 #endif
374 }
375
376 // ----------------------------------------------------------------------
377 // EndRequest: Should be called to finalize a request
378 // ----------------------------------------------------------------------
379 void 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
390 void wxSocketInternal::AcquireFD()
391 {
392 #if wxUSE_THREADS
393 m_fd_locker.Lock();
394 #endif
395 }
396
397 void wxSocketInternal::ReleaseFD()
398 {
399 #if wxUSE_THREADS
400 m_fd_locker.Unlock();
401 #endif
402 }
403
404 void wxSocketInternal::ResumeRequester()
405 {
406 #if wxUSE_THREADS
407 wxThreadError err;
408
409 wxASSERT(m_thread_requester == NULL || m_invalid_requester);
410
411 m_end_requester.Lock();
412 if (m_invalid_requester) {
413 if (m_thread_requester != NULL)
414 delete m_thread_requester;
415 m_invalid_requester = FALSE;
416 }
417 m_end_requester.Unlock();
418
419 m_thread_requester = new SocketRequester(m_socket, this);
420
421 err = m_thread_requester->Create();
422 wxASSERT(err == wxTHREAD_NO_ERROR);
423
424 err = m_thread_requester->Run();
425 wxASSERT(err == wxTHREAD_NO_ERROR);
426
427 #endif
428 }
429
430 void wxSocketInternal::StopRequester()
431 {
432 #if wxUSE_THREADS
433 m_end_requester.Lock();
434 if (m_invalid_requester) {
435 m_end_requester.Unlock();
436 delete m_thread_requester;
437 m_thread_requester = NULL;
438 m_invalid_requester = FALSE;
439 return;
440 }
441 m_end_requester.Unlock();
442
443 wxASSERT(m_thread_requester != NULL);
444
445 m_socket_locker.Lock();
446
447 // Send a signal to the requester.
448 m_socket_cond.Signal();
449
450 m_socket_locker.Unlock();
451
452 // Finish the destruction of the requester.
453 m_thread_requester->Delete();
454
455 delete m_thread_requester;
456 m_thread_requester = NULL;
457 #endif
458 }
459
460 void wxSocketInternal::ResumeWaiter()
461 {
462 #if wxUSE_THREADS
463 wxThreadError err;
464
465 if (m_thread_waiter != NULL)
466 return;
467
468 m_thread_waiter = new SocketWaiter(m_socket, this);
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);
475 #endif
476 }
477
478 void wxSocketInternal::StopWaiter()
479 {
480 #if wxUSE_THREADS
481 if (m_thread_waiter == NULL)
482 return;
483
484 m_thread_waiter->Delete();
485
486 delete m_thread_waiter;
487 m_thread_waiter = NULL;
488 #endif
489 }
490
491 // ----------------------------------------------------------------------
492 // QueueRequest:
493 // ----------------------------------------------------------------------
494 void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
495 {
496 #if wxUSE_THREADS
497 /*
498 if (m_invalid_requester)
499 ResumeRequester();
500 */
501 m_thread_requester = new SocketRequester(m_socket, this);
502
503 /*
504 if (async) {
505
506 m_request_locker.Lock();
507 request->done = FALSE;
508 m_requests.Append((wxObject *)request);
509 m_socket_cond.Signal();
510 m_request_locker.Unlock();
511
512 // Wake up
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 }
524 } else {
525 */
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();
546 // }
547 delete m_thread_requester;
548 m_thread_requester = NULL;
549 #endif
550 }
551
552 void wxSocketInternal::WaitForEnd(SockRequest *request)
553 {
554 #if wxUSE_THREADS
555 // TODOTODO
556 #endif
557 }
558
559 #endif
560 // __WXSTUBS__
561
562 #endif
563 // wxUSE_SOCKETS