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