]>
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 ret
= recv(m_fd
, &c
, 1, MSG_PEEK
);
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
);
111 // Else, no error => there is something to be read else
112 // we've lost the connection.
114 m_socket
->OnRequest(wxSocketBase::EVT_READ
);
116 m_socket
->OnRequest(wxSocketBase::EVT_LOST
);
121 void SocketWaiter::ProcessWriteEvent()
123 if (m_socket
->IsConnected())
124 m_socket
->OnRequest(wxSocketBase::EVT_CONNECT
);
126 m_socket
->OnRequest(wxSocketBase::EVT_WRITE
);
129 void *SocketWaiter::Entry()
132 fd_set sockrd_set
, sockwr_set
;
141 FD_ZERO(&sockrd_set
);
142 FD_ZERO(&sockwr_set
);
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
);
149 m_internal
->AcquireFD();
150 ret
= select(m_fd
+1, &sockrd_set
, &sockwr_set
, NULL
, &tv
);
151 m_internal
->ReleaseFD();
153 if (FD_ISSET(m_fd
, &sockrd_set
))
156 if (FD_ISSET(m_fd
, &sockwr_set
))
166 // If nothing happened, we wait for 100 ms.
169 // Check whether we should exit.
177 // --------------------------------------------------------------
178 // --------- SocketRequester ------------------------------------
179 // --------------------------------------------------------------
181 SocketRequester::SocketRequester(wxSocketBase
*socket
,
182 wxSocketInternal
*internal
)
184 m_socket(socket
), m_internal(internal
), m_fd(internal
->GetFD())
188 SocketRequester::~SocketRequester()
192 bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req
, int millisec
)
196 fd_set sockrd_set
, sockwr_set
;
199 tv
.tv_sec
= millisec
/ 1000;
200 tv
.tv_usec
= (millisec
% 1000) * 1000;
202 if ((req
& READ_MASK
) != 0)
203 FD_ZERO(&sockrd_set
);
204 FD_ZERO(&sockwr_set
);
206 FD_SET(m_fd
, &sockrd_set
);
207 FD_SET(m_fd
, &sockwr_set
);
209 m_internal
->AcquireFD();
210 ret
= select(m_fd
+1, &sockrd_set
, &sockwr_set
, NULL
, &tv
);
211 m_internal
->ReleaseFD();
216 void SocketRequester::ProcessReadEvent(SockRequest
*req
)
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
);
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();
232 // An error occured, we exit.
235 m_internal
->EndRequest(req
);
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
)) {
243 req
->io_nbytes
+= len
;
248 req
->io_nbytes
+= len
;
249 m_internal
->EndRequest(req
);
252 void SocketRequester::ProcessWriteEvent(SockRequest
*req
)
257 if (!WaitFor(wxSocketBase::REQ_WRITE
, req
->timeout
)) {
258 m_internal
->EndRequest(req
);
262 m_internal
->AcquireFD();
263 ret
= send(m_fd
, req
->buffer
, req
->size
, 0);
264 m_internal
->ReleaseFD();
267 m_internal
->EndRequest(req
);
271 if ((len
< req
->size
) && ((m_socket
->GetFlags() & wxSocketBase::WAITALL
) != 0)) {
273 req
->io_nbytes
+= len
;
277 req
->io_nbytes
+= len
;
278 m_internal
->EndRequest(req
);
281 void SocketRequester::ProcessWaitEvent(SockRequest
*req
)
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.
289 m_internal
->EndRequest(req
);
292 void *SocketRequester::Entry()
296 m_internal
->m_request_locker
.Lock();
298 // Wait for a new request or a destroy message.
299 req
= m_internal
->WaitForReq();
300 m_internal
->m_end_requester
.Lock();
302 m_internal
->m_invalid_requester
= TRUE
;
303 m_internal
->m_end_requester
.Unlock();
304 m_internal
->m_request_locker
.Unlock();
307 m_internal
->m_end_requester
.Unlock();
309 if ((req
->type
& wxSocketBase::REQ_WAIT
) != 0) {
310 ProcessWaitEvent(req
);
315 case wxSocketBase::REQ_READ
:
316 case wxSocketBase::REQ_PEEK
:
317 ProcessReadEvent(req
);
319 case wxSocketBase::REQ_WRITE
:
320 ProcessWriteEvent(req
);
328 // --------------------------------------------------------------
329 // --------- wxSocketInternal -----------------------------------
330 // --------------------------------------------------------------
332 wxSocketInternal::wxSocketInternal(wxSocketBase
*socket
)
336 m_thread_requester
= NULL
;
337 m_thread_waiter
= NULL
;
338 m_invalid_requester
= TRUE
;
342 wxSocketInternal::~wxSocketInternal()
346 wxASSERT(m_thread_requester
== NULL
);
348 wxASSERT(m_thread_waiter
== NULL
);
352 // ----------------------------------------------------------------------
353 // WaitForReq: it is called by SocketRequester and should return the next
354 // socket request if available
355 // ----------------------------------------------------------------------
356 SockRequest
*wxSocketInternal::WaitForReq()
361 node
= m_requests
.First();
363 m_socket_cond
.Wait(m_request_locker
, 10, 0);
365 node
= m_requests
.First();
370 return (SockRequest
*)node
->Data();
376 // ----------------------------------------------------------------------
377 // EndRequest: Should be called to finalize a request
378 // ----------------------------------------------------------------------
379 void wxSocketInternal::EndRequest(SockRequest
*req
)
385 node
= m_requests
.Member((wxObject
*)req
);
390 void wxSocketInternal::AcquireFD()
397 void wxSocketInternal::ReleaseFD()
400 m_fd_locker
.Unlock();
404 void wxSocketInternal::ResumeRequester()
409 wxASSERT(m_thread_requester
== NULL
|| m_invalid_requester
);
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
;
417 m_end_requester
.Unlock();
419 m_thread_requester
= new SocketRequester(m_socket
, this);
421 err
= m_thread_requester
->Create();
422 wxASSERT(err
== wxTHREAD_NO_ERROR
);
424 err
= m_thread_requester
->Run();
425 wxASSERT(err
== wxTHREAD_NO_ERROR
);
430 void wxSocketInternal::StopRequester()
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
;
441 m_end_requester
.Unlock();
443 wxASSERT(m_thread_requester
!= NULL
);
445 m_socket_locker
.Lock();
447 // Send a signal to the requester.
448 m_socket_cond
.Signal();
450 m_socket_locker
.Unlock();
452 // Finish the destruction of the requester.
453 m_thread_requester
->Delete();
455 delete m_thread_requester
;
456 m_thread_requester
= NULL
;
460 void wxSocketInternal::ResumeWaiter()
465 if (m_thread_waiter
!= NULL
)
468 m_thread_waiter
= new SocketWaiter(m_socket
, this);
470 err
= m_thread_waiter
->Create();
471 wxASSERT(err
== wxTHREAD_NO_ERROR
);
473 err
= m_thread_waiter
->Run();
474 wxASSERT(err
== wxTHREAD_NO_ERROR
);
478 void wxSocketInternal::StopWaiter()
481 if (m_thread_waiter
== NULL
)
484 m_thread_waiter
->Delete();
486 delete m_thread_waiter
;
487 m_thread_waiter
= NULL
;
491 // ----------------------------------------------------------------------
493 // ----------------------------------------------------------------------
494 void wxSocketInternal::QueueRequest(SockRequest
*request
, bool async
)
498 if (m_invalid_requester)
501 m_thread_requester
= new SocketRequester(m_socket
, this);
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();
515 if (wxThread::IsMain())
516 while (!request->done) {
520 while (!request->done) {
526 m_request_locker
.Lock();
528 if ((request
->type
& wxSocketBase::REQ_WAIT
) != 0) {
529 m_thread_requester
->ProcessWaitEvent(request
);
532 request
->done
= FALSE
;
534 switch (request
->type
) {
535 case wxSocketBase::REQ_PEEK
:
536 case wxSocketBase::REQ_READ
:
537 m_thread_requester
->ProcessReadEvent(request
);
539 case wxSocketBase::REQ_WRITE
:
540 m_thread_requester
->ProcessWriteEvent(request
);
544 request
->done
= TRUE
;
545 m_request_locker
.Unlock();
547 delete m_thread_requester
;
548 m_thread_requester
= NULL
;
552 void wxSocketInternal::WaitForEnd(SockRequest
*request
)