]> git.saurik.com Git - wxWidgets.git/blob - src/common/sckint.cpp
wxFileIn/OutputStream fix
[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 m_internal->ReleaseData(); // In that case, we mustn't forget to unlock the mutex.
118 Exit(NULL);
119 }
120 }
121
122 void SocketWaiter::ProcessWriteEvent()
123 {
124 if (m_socket->IsConnected())
125 m_socket->OnRequest(wxSocketBase::EVT_CONNECT);
126 else
127 m_socket->OnRequest(wxSocketBase::EVT_WRITE);
128 }
129
130 void *SocketWaiter::Entry()
131 {
132 struct timeval tv;
133 fd_set sockrd_set, sockwr_set;
134 wxSocketEvent event;
135 int ret;
136
137 while (1) {
138 // We won't wait.
139 tv.tv_sec = 0;
140 tv.tv_usec = 0;
141
142 FD_ZERO(&sockrd_set);
143 FD_ZERO(&sockwr_set);
144
145 m_internal->AcquireData();
146
147 if ((m_socket->NeededReq() & READ_MASK) != 0)
148 FD_SET(m_fd, &sockrd_set);
149 if ((m_socket->NeededReq() & WRITE_MASK) != 0)
150 FD_SET(m_fd, &sockwr_set);
151
152 m_internal->AcquireFD();
153 ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
154 m_internal->ReleaseFD();
155
156 if (FD_ISSET(m_fd, &sockrd_set))
157 ProcessReadEvent();
158
159 if (FD_ISSET(m_fd, &sockwr_set))
160 ProcessWriteEvent();
161
162 m_internal->ReleaseData();
163
164 #if wxUSE_THREADS
165 #ifdef Yield
166 #undef Yield
167 #endif
168 #endif
169
170 if (ret == 0)
171 // If nothing happened, we wait for 100 ms.
172 wxUsleep(10);
173
174 // Check whether we should exit.
175 if (TestDestroy()) {
176 return NULL;
177 }
178 }
179 return NULL;
180 }
181
182 // --------------------------------------------------------------
183 // --------- SocketRequester ------------------------------------
184 // --------------------------------------------------------------
185
186 SocketRequester::SocketRequester(wxSocketBase *socket,
187 wxSocketInternal *internal)
188 : wxThread(),
189 m_socket(socket), m_internal(internal), m_fd(internal->GetFD())
190 {
191 }
192
193 SocketRequester::~SocketRequester()
194 {
195 }
196
197 bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec)
198 {
199 int ret;
200 struct timeval tv;
201 fd_set sockrd_set, sockwr_set;
202
203 // We won't wait.
204 tv.tv_sec = millisec / 1000;
205 tv.tv_usec = (millisec % 1000) * 1000;
206
207 if ((req & READ_MASK) != 0)
208 FD_ZERO(&sockrd_set);
209 FD_ZERO(&sockwr_set);
210
211 FD_SET(m_fd, &sockrd_set);
212 FD_SET(m_fd, &sockwr_set);
213
214 m_internal->AcquireFD();
215 ret = select(m_fd+1, &sockrd_set, &sockwr_set, NULL, &tv);
216 m_internal->ReleaseFD();
217
218 return (ret != 0);
219 }
220
221 void SocketRequester::ProcessReadEvent(SockRequest *req)
222 {
223 int ret;
224 size_t len;
225
226 // We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately
227 if (!WaitFor(wxSocketBase::REQ_READ, req->timeout)) {
228 m_internal->EndRequest(req);
229 return;
230 }
231
232 m_internal->AcquireFD();
233 ret = recv(m_fd, req->buffer, req->size,
234 (req->type == wxSocketBase::REQ_PEEK) ? MSG_PEEK : 0);
235 m_internal->ReleaseFD();
236
237 // An error occured, we exit.
238 if (ret < 0) {
239 req->error = errno;
240 m_internal->EndRequest(req);
241 return;
242 }
243 len = ret;
244
245 // If the buffer isn't full (and we want it to be full), we don't unqueue it.
246 if ((len < req->size) && (m_socket->GetFlags() & wxSocketBase::WAITALL)) {
247 req->size -= len;
248 req->io_nbytes += len;
249 req->buffer += len;
250 return;
251 }
252 // The End.
253 req->io_nbytes += len;
254 m_internal->EndRequest(req);
255 }
256
257 void SocketRequester::ProcessWriteEvent(SockRequest *req)
258 {
259 int ret;
260 size_t len;
261
262 if (!WaitFor(wxSocketBase::REQ_WRITE, req->timeout)) {
263 m_internal->EndRequest(req);
264 return;
265 }
266
267 m_internal->AcquireFD();
268 ret = send(m_fd, req->buffer, req->size, 0);
269 m_internal->ReleaseFD();
270 if (ret < 0) {
271 req->error = errno;
272 m_internal->EndRequest(req);
273 return;
274 }
275 len = ret;
276 if ((len < req->size) && ((m_socket->GetFlags() & wxSocketBase::WAITALL) != 0)) {
277 req->size -= len;
278 req->io_nbytes += len;
279 req->buffer += len;
280 return;
281 }
282 req->io_nbytes += len;
283 m_internal->EndRequest(req);
284 }
285
286 void SocketRequester::ProcessWaitEvent(SockRequest *req)
287 {
288 if (WaitFor(req->type, req->timeout))
289 req->io_nbytes = 1; // We put 1 in the counter to tell the requester
290 // there is no timeout.
291 else
292 req->io_nbytes = 0;
293
294 m_internal->EndRequest(req);
295 }
296
297 void *SocketRequester::Entry()
298 {
299 SockRequest *req;
300
301 m_internal->m_request_locker.Lock();
302 while (1) {
303 // Wait for a new request or a destroy message.
304 req = m_internal->WaitForReq();
305 m_internal->m_end_requester.Lock();
306 if (req == NULL) {
307 m_internal->m_invalid_requester = TRUE;
308 m_internal->m_end_requester.Unlock();
309 m_internal->m_request_locker.Unlock();
310 return NULL;
311 }
312 m_internal->m_end_requester.Unlock();
313
314 if ((req->type & wxSocketBase::REQ_WAIT) != 0) {
315 ProcessWaitEvent(req);
316 continue;
317 }
318
319 switch (req->type) {
320 case wxSocketBase::REQ_READ:
321 case wxSocketBase::REQ_PEEK:
322 ProcessReadEvent(req);
323 break;
324 case wxSocketBase::REQ_WRITE:
325 ProcessWriteEvent(req);
326 break;
327 }
328 }
329 return NULL;
330 }
331 #endif
332
333 // --------------------------------------------------------------
334 // --------- wxSocketInternal -----------------------------------
335 // --------------------------------------------------------------
336
337 wxSocketInternal::wxSocketInternal(wxSocketBase *socket)
338 {
339 m_socket = socket;
340 #if wxUSE_THREADS
341 m_thread_requester = NULL;
342 m_thread_waiter = NULL;
343 m_invalid_requester = TRUE;
344 #endif
345 }
346
347 wxSocketInternal::~wxSocketInternal()
348 {
349 #if wxUSE_THREADS
350 StopRequester();
351 wxASSERT(m_thread_requester == NULL);
352 StopWaiter();
353 wxASSERT(m_thread_waiter == NULL);
354 #endif
355 }
356
357 // ----------------------------------------------------------------------
358 // WaitForReq: it is called by SocketRequester and should return the next
359 // socket request if available
360 // ----------------------------------------------------------------------
361 SockRequest *wxSocketInternal::WaitForReq()
362 {
363 #if wxUSE_THREADS
364 wxNode *node;
365
366 node = m_requests.First();
367 if (node == NULL) {
368 m_socket_cond.Wait(m_request_locker, 10, 0);
369
370 node = m_requests.First();
371 if (node == NULL)
372 return NULL;
373 }
374
375 return (SockRequest *)node->Data();
376 #else
377 return NULL;
378 #endif
379 }
380
381 // ----------------------------------------------------------------------
382 // EndRequest: Should be called to finalize a request
383 // ----------------------------------------------------------------------
384 void wxSocketInternal::EndRequest(SockRequest *req)
385 {
386 wxNode *node = NULL;
387
388 req->done = TRUE;
389
390 node = m_requests.Member((wxObject *)req);
391 if (node != NULL)
392 delete node;
393 }
394
395 void wxSocketInternal::AcquireData()
396 {
397 #if wxUSE_THREADS
398 m_socket_locker.Lock();
399 #endif
400 }
401
402 void wxSocketInternal::ReleaseData()
403 {
404 #if wxUSE_THREADS
405 m_socket_locker.Unlock();
406 #endif
407 }
408
409 void wxSocketInternal::AcquireFD()
410 {
411 #if wxUSE_THREADS
412 m_fd_locker.Lock();
413 #endif
414 }
415
416 void wxSocketInternal::ReleaseFD()
417 {
418 #if wxUSE_THREADS
419 m_fd_locker.Unlock();
420 #endif
421 }
422
423 void wxSocketInternal::ResumeRequester()
424 {
425 #if wxUSE_THREADS
426 wxThreadError err;
427
428 wxASSERT(m_thread_requester == NULL || m_invalid_requester);
429
430 m_end_requester.Lock();
431 if (m_invalid_requester) {
432 if (m_thread_requester != NULL)
433 delete m_thread_requester;
434 m_invalid_requester = FALSE;
435 }
436 m_end_requester.Unlock();
437
438 m_thread_requester = new SocketRequester(m_socket, this);
439
440 err = m_thread_requester->Create();
441 wxASSERT(err == wxTHREAD_NO_ERROR);
442
443 err = m_thread_requester->Run();
444 wxASSERT(err == wxTHREAD_NO_ERROR);
445
446 #endif
447 }
448
449 void wxSocketInternal::StopRequester()
450 {
451 #if wxUSE_THREADS
452 m_end_requester.Lock();
453 if (m_invalid_requester) {
454 m_end_requester.Unlock();
455 if (m_thread_requester) {
456 delete m_thread_requester;
457 m_thread_requester = NULL;
458 }
459 m_invalid_requester = TRUE;
460 return;
461 }
462 m_end_requester.Unlock();
463
464 wxASSERT(m_thread_requester != NULL);
465
466 m_request_locker.Lock();
467
468 // Send a signal to the requester.
469 m_socket_cond.Signal();
470
471 m_request_locker.Unlock();
472
473 // Finish the destruction of the requester.
474 m_thread_requester->Delete();
475
476 delete m_thread_requester;
477 m_thread_requester = NULL;
478 #endif
479 }
480
481 void wxSocketInternal::ResumeWaiter()
482 {
483 #if wxUSE_THREADS
484 wxThreadError err;
485
486 if (m_thread_waiter != NULL)
487 return;
488
489 m_thread_waiter = new SocketWaiter(m_socket, this);
490
491 err = m_thread_waiter->Create();
492 wxASSERT(err == wxTHREAD_NO_ERROR);
493
494 err = m_thread_waiter->Run();
495 wxASSERT(err == wxTHREAD_NO_ERROR);
496 #endif
497 }
498
499 void wxSocketInternal::StopWaiter()
500 {
501 #if wxUSE_THREADS
502 if (m_thread_waiter == NULL)
503 return;
504
505 m_thread_waiter->Delete();
506
507 delete m_thread_waiter;
508 m_thread_waiter = NULL;
509 #endif
510 }
511
512 // ----------------------------------------------------------------------
513 // QueueRequest:
514 // ----------------------------------------------------------------------
515 void wxSocketInternal::QueueRequest(SockRequest *request, bool async)
516 {
517 #if wxUSE_THREADS
518 if (m_invalid_requester)
519 ResumeRequester();
520
521 async = FALSE;
522 if (async) {
523
524 m_request_locker.Lock();
525 request->done = FALSE;
526 m_requests.Append((wxObject *)request);
527 m_socket_cond.Signal();
528 m_request_locker.Unlock();
529
530 // Wake up
531
532 if (request->wait) {
533 if (wxThread::IsMain())
534 while (!request->done) {
535 wxYield();
536 }
537 else
538 while (!request->done) {
539 wxThread::Yield();
540 }
541 }
542 } else {
543 m_request_locker.Lock();
544
545 if ((request->type & wxSocketBase::REQ_WAIT) != 0) {
546 m_thread_requester->ProcessWaitEvent(request);
547 } else {
548
549 request->done = FALSE;
550
551 switch (request->type) {
552 case wxSocketBase::REQ_PEEK:
553 case wxSocketBase::REQ_READ:
554 m_thread_requester->ProcessReadEvent(request);
555 break;
556 case wxSocketBase::REQ_WRITE:
557 m_thread_requester->ProcessWriteEvent(request);
558 break;
559 }
560 }
561 request->done = TRUE;
562 m_request_locker.Unlock();
563 }
564 #endif
565 }
566
567 void wxSocketInternal::WaitForEnd(SockRequest *request)
568 {
569 #if wxUSE_THREADS
570 // TODOTODO
571 #endif
572 }
573
574 #endif
575 // __WXSTUBS__
576
577 #endif
578 // wxUSE_SOCKETS