]>
git.saurik.com Git - wxWidgets.git/blob - src/common/sckint.cpp
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: Socket handler classes
4 // Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew
5 // Davidson(1995) in wxWeb)
8 // Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux
10 // License: see wxWindows license
11 ///////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "sckint.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #define WXSOCK_INTERNAL
26 #include <wx/object.h>
28 #include <wx/socket.h>
29 #include <wx/thread.h>
30 #include <wx/sckint.h>
38 // -----------------------
39 // System specific headers
40 // -----------------------
43 // in order to avoid problems with our c library and double definitions
44 #define close closesocket
45 #define ioctl ioctlsocket
47 #include <wx/mac/macsock.h>
50 #if defined(__WINDOWS__)
59 #include <sys/socket.h>
61 #include <sys/ioctl.h>
67 #include <sys/filio.h>
80 #define READ_MASK wxSocketBase::REQ_READ | wxSocketBase::REQ_ACCEPT | wxSocketBase::REQ_LOST
81 #define WRITE_MASK wxSocketBase::REQ_WRITE | wxSocketBase::REQ_CONNECT
83 // --------------------------------------------------------------
84 // --------- SocketWaiter ---------------------------------------
85 // --------------------------------------------------------------
88 SocketWaiter::SocketWaiter(wxSocketBase
*socket
,
89 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(FD_SETSIZE
, &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
)
183 : m_socket(socket
), m_internal(internal
), m_fd(internal
->GetFD())
187 SocketRequester::~SocketRequester()
191 bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req
, int millisec
)
195 fd_set sockrd_set
, sockwr_set
;
198 tv
.tv_sec
= millisec
/ 1000;
199 tv
.tv_usec
= (millisec
% 1000) * 1000;
201 if ((req
& READ_MASK
) != 0)
202 FD_ZERO(&sockrd_set
);
203 FD_ZERO(&sockwr_set
);
205 FD_SET(m_fd
, &sockrd_set
);
206 FD_SET(m_fd
, &sockwr_set
);
208 m_internal
->AcquireFD();
209 ret
= select(FD_SETSIZE
, &sockrd_set
, &sockwr_set
, NULL
, &tv
);
210 m_internal
->ReleaseFD();
215 void SocketRequester::ProcessReadEvent(SockRequest
*req
)
220 // We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately
221 if (!WaitFor(wxSocketBase::REQ_READ
, req
->timeout
)) {
222 m_internal
->EndRequest(req
);
226 m_internal
->AcquireFD();
227 ret
= recv(m_fd
, req
->buffer
, req
->size
,
228 (req
->type
== wxSocketBase::REQ_PEEK
) ? MSG_PEEK
: 0);
229 m_internal
->ReleaseFD();
231 // An error occured, we exit.
234 m_internal
->EndRequest(req
);
239 // If the buffer isn't full (and we want it to be full), we don't unqueue it.
240 if ((len
< req
->size
) && (m_socket
->GetFlags() & wxSocketBase::WAITALL
)) {
242 req
->io_nbytes
+= len
;
247 req
->io_nbytes
+= len
;
248 m_internal
->EndRequest(req
);
251 void SocketRequester::ProcessWriteEvent(SockRequest
*req
)
256 m_internal
->AcquireFD();
257 ret
= send(m_fd
, req
->buffer
, req
->size
, 0);
258 m_internal
->ReleaseFD();
261 m_internal
->EndRequest(req
);
265 if ((len
< req
->size
) && ((m_socket
->GetFlags() & wxSocketBase::WAITALL
) != 0)) {
267 req
->io_nbytes
+= len
;
271 req
->io_nbytes
+= len
;
272 m_internal
->EndRequest(req
);
275 void SocketRequester::ProcessWaitEvent(SockRequest
*req
)
277 if (WaitFor(req
->type
, req
->timeout
))
278 req
->io_nbytes
= 1; // We put 1 in the counter to tell the requester
279 // there is no timeout.
283 m_internal
->EndRequest(req
);
286 void *SocketRequester::Entry()
291 // Wait for a new request or a destroy message.
292 req
= m_internal
->WaitForReq();
293 m_internal
->m_end_requester
.Lock();
294 if (TestDestroy() || req
== NULL
) {
295 m_internal
->m_invalid_requester
= TRUE
;
296 m_internal
->m_end_requester
.Unlock();
299 m_internal
->m_end_requester
.Unlock();
301 if ((req
->type
& wxSocketBase::REQ_WAIT
) != 0) {
302 ProcessWaitEvent(req
);
307 case wxSocketBase::REQ_READ
:
308 case wxSocketBase::REQ_PEEK
:
309 ProcessReadEvent(req
);
311 case wxSocketBase::REQ_WRITE
:
312 ProcessWriteEvent(req
);
320 // --------------------------------------------------------------
321 // --------- wxSocketInternal -----------------------------------
322 // --------------------------------------------------------------
324 wxSocketInternal::wxSocketInternal(wxSocketBase
*socket
)
328 m_thread_requester
= NULL
;
329 m_thread_waiter
= NULL
;
330 m_invalid_requester
= TRUE
;
331 m_request_locker
.Lock();
335 wxSocketInternal::~wxSocketInternal()
339 wxASSERT(m_thread_requester
== NULL
);
341 wxASSERT(m_thread_waiter
== NULL
);
342 m_request_locker
.Unlock();
346 // ----------------------------------------------------------------------
347 // WaitForReq: it is called by SocketRequester and should return the next
348 // socket request if available
349 // ----------------------------------------------------------------------
350 SockRequest
*wxSocketInternal::WaitForReq()
355 node
= m_requests
.First();
357 m_socket_cond
.Wait(m_request_locker
, 1, 0);
359 node
= m_requests
.First();
364 return (SockRequest
*)node
->Data();
370 // ----------------------------------------------------------------------
371 // EndRequest: Should be called to finalize a request
372 // ----------------------------------------------------------------------
373 void wxSocketInternal::EndRequest(SockRequest
*req
)
379 node
= m_requests
.Member((wxObject
*)req
);
384 void wxSocketInternal::AcquireFD()
391 void wxSocketInternal::ReleaseFD()
394 m_fd_locker
.Unlock();
398 void wxSocketInternal::ResumeRequester()
403 wxASSERT(m_thread_requester
== NULL
);
405 m_end_requester
.Lock();
406 if (m_invalid_requester
) {
407 delete m_thread_requester
;
409 m_thread_requester
= new SocketRequester(m_socket
, this);
410 m_thread_requester
->m_fd
= m_socket
->m_fd
;
412 err
= m_thread_requester
->Create();
413 wxASSERT(err
== wxTHREAD_NO_ERROR
);
415 err
= m_thread_requester
->Run();
416 wxASSERT(err
== wxTHREAD_NO_ERROR
);
418 m_invalid_requester
= FALSE
;
420 m_end_requester
.Unlock();
424 void wxSocketInternal::StopRequester()
427 if (m_invalid_requester
) {
428 delete m_thread_requester
;
429 m_thread_requester
= NULL
;
430 m_invalid_requester
= FALSE
;
434 wxASSERT(m_thread_requester
!= NULL
);
436 m_socket_locker
.Lock();
438 // Send a signal to the requester.
439 if (m_requests
.Number() == 0)
440 m_socket_cond
.Signal();
442 m_socket_locker
.Unlock();
444 // Finish the destruction of the requester.
445 m_thread_requester
->Delete();
447 delete m_thread_requester
;
448 m_thread_requester
= NULL
;
452 void wxSocketInternal::ResumeWaiter()
457 if (m_thread_waiter
!= NULL
)
460 m_thread_waiter
= new SocketWaiter(m_socket
, this);
461 m_thread_waiter
->m_fd
= m_socket
->m_fd
;
463 err
= m_thread_waiter
->Create();
464 wxASSERT(err
== wxTHREAD_NO_ERROR
);
466 err
= m_thread_waiter
->Run();
467 wxASSERT(err
== wxTHREAD_NO_ERROR
);
471 void wxSocketInternal::StopWaiter()
474 if (m_thread_waiter
== NULL
)
477 m_thread_waiter
->Delete();
479 delete m_thread_waiter
;
480 m_thread_waiter
= NULL
;
484 // ----------------------------------------------------------------------
486 // ----------------------------------------------------------------------
487 void wxSocketInternal::QueueRequest(SockRequest
*request
, bool async
)
491 if (m_thread_requester
== NULL
)
494 m_request_locker
.Lock();
495 request
->done
= FALSE
;
496 m_requests
.Append((wxObject
*)request
);
497 m_socket_cond
.Signal();
498 m_request_locker
.Unlock();
503 if (wxThread::IsMain())
504 while (!request
->done
) {
508 while (!request
->done
) {
513 m_request_locker
.Lock();
515 if ((request
->type
& wxSocketBase::REQ_WAIT
) != 0) {
516 m_thread_requester
->ProcessWaitEvent(request
);
519 request
->done
= FALSE
;
521 switch (request
->type
) {
522 case wxSocketBase::REQ_PEEK
:
523 case wxSocketBase::REQ_READ
:
524 m_thread_requester
->ProcessReadEvent(request
);
526 case wxSocketBase::REQ_WRITE
:
527 m_thread_requester
->ProcessWriteEvent(request
);
531 request
->done
= TRUE
;
532 m_request_locker
.Unlock();
537 void wxSocketInternal::WaitForEnd(SockRequest
*request
)