]>
git.saurik.com Git - wxWidgets.git/blob - src/common/sckint.cpp
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: Socket internal classes
4 // Authors: Guilhem Lavaux
7 // Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux
9 // License: see wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "sckint.h"
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
24 #define WXSOCK_INTERNAL
25 #include <wx/object.h>
27 #include <wx/socket.h>
28 #include <wx/thread.h>
29 #include <wx/sckint.h>
37 // -----------------------
38 // System specific headers
39 // -----------------------
42 // in order to avoid problems with our c library and double definitions
43 #define close closesocket
44 #define ioctl ioctlsocket
46 #include <wx/mac/macsock.h>
49 #if defined(__WINDOWS__)
58 #include <sys/socket.h>
60 #include <sys/ioctl.h>
66 #include <sys/filio.h>
79 #define READ_MASK wxSocketBase::REQ_READ | wxSocketBase::REQ_ACCEPT | wxSocketBase::REQ_LOST
80 #define WRITE_MASK wxSocketBase::REQ_WRITE | wxSocketBase::REQ_CONNECT
82 // --------------------------------------------------------------
83 // --------- SocketWaiter ---------------------------------------
84 // --------------------------------------------------------------
87 SocketWaiter::SocketWaiter(wxSocketBase
*socket
,
88 wxSocketInternal
*internal
)
90 m_socket(socket
), m_internal(internal
), m_fd(internal
->GetFD())
94 SocketWaiter::~SocketWaiter()
98 void SocketWaiter::ProcessReadEvent()
103 m_internal
->AcquireFD();
104 ret
= recv(m_fd
, &c
, 1, MSG_PEEK
);
105 m_internal
->ReleaseFD();
107 // We are a server => emit a EVT_ACCEPT event.
108 if (ret
== -1 && m_socket
->GetType() == wxSocketBase::SOCK_SERVER
) {
109 m_socket
->OnRequest(wxSocketBase::EVT_ACCEPT
);
113 // Else, no error => there is something to be read else
114 // we've lost the connection.
116 m_socket
->OnRequest(wxSocketBase::EVT_READ
);
118 m_socket
->OnRequest(wxSocketBase::EVT_LOST
);
119 m_internal
->ReleaseData(); // In that case, we mustn't forget to unlock the mutex.
124 void SocketWaiter::ProcessWriteEvent()
126 if (m_socket
->IsConnected())
127 m_socket
->OnRequest(wxSocketBase::EVT_CONNECT
);
129 m_socket
->OnRequest(wxSocketBase::EVT_WRITE
);
132 void *SocketWaiter::Entry()
135 fd_set sockrd_set
, sockwr_set
;
144 FD_ZERO(&sockrd_set
);
145 FD_ZERO(&sockwr_set
);
147 m_internal
->AcquireData();
149 if ((m_socket
->NeededReq() & READ_MASK
) != 0)
150 FD_SET(m_fd
, &sockrd_set
);
151 if ((m_socket
->NeededReq() & WRITE_MASK
) != 0)
152 FD_SET(m_fd
, &sockwr_set
);
154 m_internal
->AcquireFD();
155 ret
= select(m_fd
+1, &sockrd_set
, &sockwr_set
, NULL
, &tv
);
156 m_internal
->ReleaseFD();
158 if (FD_ISSET(m_fd
, &sockrd_set
))
161 if (FD_ISSET(m_fd
, &sockwr_set
))
164 m_internal
->ReleaseData();
172 // We wait for 100 ms to prevent the CPU from burning.
175 // Check whether we should exit.
182 // --------------------------------------------------------------
183 // --------- SocketRequester ------------------------------------
184 // --------------------------------------------------------------
186 SocketRequester::SocketRequester(wxSocketBase
*socket
,
187 wxSocketInternal
*internal
)
192 m_socket(socket
), m_internal(internal
), m_fd(internal
->GetFD())
196 SocketRequester::~SocketRequester()
200 bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req
, int millisec
)
204 fd_set sockrd_set
, sockwr_set
;
207 tv
.tv_sec
= millisec
/ 1000;
208 tv
.tv_usec
= (millisec
% 1000) * 1000;
210 FD_ZERO(&sockrd_set
);
211 FD_ZERO(&sockwr_set
);
212 if ((req
& READ_MASK
) != 0)
213 FD_SET(m_fd
, &sockrd_set
);
214 if ((req
& WRITE_MASK
) != 0)
215 FD_SET(m_fd
, &sockwr_set
);
217 m_internal
->AcquireFD();
218 ret
= select(m_fd
+1, &sockrd_set
, &sockwr_set
, NULL
, &tv
);
219 m_internal
->ReleaseFD();
224 void SocketRequester::ProcessReadEvent(SockRequest
*req
)
229 // We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately
230 if (!WaitFor(wxSocketBase::REQ_READ
, req
->timeout
)) {
231 m_internal
->EndRequest(req
);
235 m_internal
->AcquireFD();
236 ret
= recv(m_fd
, req
->buffer
, req
->size
,
237 (req
->type
== wxSocketBase::REQ_PEEK
) ? MSG_PEEK
: 0);
238 m_internal
->ReleaseFD();
240 // An error occured, we exit.
243 m_internal
->EndRequest(req
);
248 // If the buffer isn't full (and we want it to be full), we don't unqueue it.
249 if ((len
< req
->size
) && (m_socket
->GetFlags() & wxSocketBase::WAITALL
)) {
251 req
->io_nbytes
+= len
;
255 m_internal
->EndRequest(req
);
259 req
->io_nbytes
+= len
;
260 m_internal
->EndRequest(req
);
263 void SocketRequester::ProcessWriteEvent(SockRequest
*req
)
268 if (!WaitFor(wxSocketBase::REQ_WRITE
, req
->timeout
)) {
269 m_internal
->EndRequest(req
);
273 m_internal
->AcquireFD();
274 ret
= send(m_fd
, req
->buffer
, req
->size
, 0);
275 m_internal
->ReleaseFD();
278 m_internal
->EndRequest(req
);
282 if ((len
< req
->size
) && ((m_socket
->GetFlags() & wxSocketBase::WAITALL
) != 0)) {
284 req
->io_nbytes
+= len
;
288 req
->io_nbytes
+= len
;
289 m_internal
->EndRequest(req
);
292 void SocketRequester::ProcessWaitEvent(SockRequest
*req
)
294 if (WaitFor(req
->type
, req
->timeout
))
295 req
->io_nbytes
= 1; // We put 1 in the counter to tell the requester
296 // there is no timeout.
300 m_internal
->EndRequest(req
);
303 void *SocketRequester::Entry()
307 m_internal
->m_request_locker
.Lock();
309 // Wait for a new request or a destroy message.
310 req
= m_internal
->WaitForReq();
311 m_internal
->m_end_requester
.Lock();
313 m_internal
->m_invalid_requester
= TRUE
;
314 m_internal
->m_end_requester
.Unlock();
315 m_internal
->m_request_locker
.Unlock();
318 m_internal
->m_end_requester
.Unlock();
320 if ((req
->type
& wxSocketBase::REQ_WAIT
) != 0) {
321 ProcessWaitEvent(req
);
326 case wxSocketBase::REQ_READ
:
327 case wxSocketBase::REQ_PEEK
:
328 ProcessReadEvent(req
);
330 case wxSocketBase::REQ_WRITE
:
331 ProcessWriteEvent(req
);
339 // --------------------------------------------------------------
340 // --------- wxSocketInternal -----------------------------------
341 // --------------------------------------------------------------
343 wxSocketInternal::wxSocketInternal(wxSocketBase
*socket
)
346 m_thread_requester
= NULL
;
347 m_thread_waiter
= NULL
;
348 m_invalid_requester
= TRUE
;
351 wxSocketInternal::~wxSocketInternal()
354 wxASSERT(m_thread_requester
== NULL
);
356 wxASSERT(m_thread_waiter
== NULL
);
359 // ----------------------------------------------------------------------
360 // WaitForReq: it is called by SocketRequester and should return the next
361 // socket request if available
362 // ----------------------------------------------------------------------
363 SockRequest
*wxSocketInternal::WaitForReq()
369 node
= m_requests
.First();
371 m_socket_cond
.Wait(m_request_locker
, 10, 0);
373 // Second try, if it is unsuccessul we give up.
374 node
= m_requests
.First();
379 return (SockRequest
*)node
->Data();
385 // ----------------------------------------------------------------------
386 // EndRequest: Should be called to finalize a request
387 // ----------------------------------------------------------------------
388 void wxSocketInternal::EndRequest(SockRequest
*req
)
394 node
= m_requests
.Member((wxObject
*)req
);
399 void wxSocketInternal::AcquireData()
402 m_socket_locker
.Lock();
406 void wxSocketInternal::ReleaseData()
409 m_socket_locker
.Unlock();
413 void wxSocketInternal::AcquireFD()
420 void wxSocketInternal::ReleaseFD()
423 m_fd_locker
.Unlock();
427 void wxSocketInternal::ResumeRequester()
432 wxASSERT(m_invalid_requester
);
434 m_end_requester
.Lock();
436 if (m_thread_requester
!= NULL
) {
437 m_thread_requester
->Delete(); // We must join it.
438 delete m_thread_requester
;
441 m_invalid_requester
= FALSE
;
443 m_end_requester
.Unlock();
445 m_thread_requester
= new SocketRequester(m_socket
, this);
447 err
= m_thread_requester
->Create();
448 wxASSERT(err
== wxTHREAD_NO_ERROR
);
450 err
= m_thread_requester
->Run();
451 wxASSERT(err
== wxTHREAD_NO_ERROR
);
453 if (!m_invalid_requester
)
455 m_thread_requester
= new SocketRequester(m_socket
, this);
456 m_invalid_requester
= FALSE
;
460 void wxSocketInternal::StopRequester()
463 m_end_requester
.Lock();
464 if (m_invalid_requester
) {
465 m_end_requester
.Unlock();
466 if (m_thread_requester
) {
467 m_thread_requester
->Delete();
468 delete m_thread_requester
;
469 m_thread_requester
= NULL
;
471 m_invalid_requester
= TRUE
;
474 m_end_requester
.Unlock();
476 wxASSERT(m_thread_requester
!= NULL
);
478 m_request_locker
.Lock();
480 // Send a signal to the requester.
481 m_socket_cond
.Signal();
483 m_request_locker
.Unlock();
485 // Finish the destruction of the requester.
486 m_thread_requester
->Delete();
488 delete m_thread_requester
;
489 m_thread_requester
= NULL
;
490 m_invalid_requester
= TRUE
;
492 delete m_thread_requester
;
493 m_thread_requester
= NULL
;
494 m_invalid_requester
= TRUE
;
498 void wxSocketInternal::ResumeWaiter()
503 if (m_thread_waiter
!= NULL
)
506 m_thread_waiter
= new SocketWaiter(m_socket
, this);
508 m_thread_waiter
->SetPriority(WXTHREAD_MIN_PRIORITY
);
510 err
= m_thread_waiter
->Create();
511 wxASSERT(err
== wxTHREAD_NO_ERROR
);
513 err
= m_thread_waiter
->Run();
514 wxASSERT(err
== wxTHREAD_NO_ERROR
);
518 void wxSocketInternal::StopWaiter()
521 if (m_thread_waiter
== NULL
)
524 m_thread_waiter
->Delete();
526 delete m_thread_waiter
;
527 m_thread_waiter
= NULL
;
531 // ----------------------------------------------------------------------
533 // ----------------------------------------------------------------------
534 void wxSocketInternal::QueueRequest(SockRequest
*request
, bool async
)
536 if (m_invalid_requester
)
542 m_request_locker
.Lock();
543 request
->done
= FALSE
;
544 m_requests
.Append((wxObject
*)request
);
545 m_socket_cond
.Signal();
546 m_request_locker
.Unlock();
551 if (wxThread::IsMain())
552 while (!request
->done
) {
556 while (!request
->done
) {
561 m_request_locker
.Lock();
564 if ((request
->type
& wxSocketBase::REQ_WAIT
) != 0) {
565 m_thread_requester
->ProcessWaitEvent(request
);
568 request
->done
= FALSE
;
570 switch (request
->type
) {
571 case wxSocketBase::REQ_PEEK
:
572 case wxSocketBase::REQ_READ
:
573 m_thread_requester
->ProcessReadEvent(request
);
575 case wxSocketBase::REQ_WRITE
:
576 m_thread_requester
->ProcessWriteEvent(request
);
580 request
->done
= TRUE
;
582 m_request_locker
.Unlock();
587 void wxSocketInternal::WaitForEnd(SockRequest
*request
)