From a737331db68b754c8bf31fa0a15f6d1f207b40bf Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Mon, 26 Apr 1999 18:16:56 +0000 Subject: [PATCH] * Committing new wxSocket core (socket.cpp sckint.cpp). It has to be improved ... * Adding sckint.cpp to various makefiles. * Fixes in threadpsx.cpp (Pause/Resume) * Fixes in threaded event dispatching * Added Clone() to wxObject * Implemented Clone() in wxEvent and wxSocketEvent * wxSocket sample save the data got from the URL in test.url (this will change) * As I only tested wxSocket on Linux Redhat 5.2 I disabled it by default on Windows, Mac and Unix platforms. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2289 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- configure.in | 2 +- include/wx/event.h | 2 + include/wx/msw/setup0.h | 2 +- include/wx/object.h | 1 + include/wx/sckint.h | 144 ++++ include/wx/socket.h | 100 +-- include/wx/thread.h | 2 +- include/wx/wfstream.h | 4 +- samples/wxsocket/client.cpp | 29 +- samples/wxsocket/server.cpp | 73 ++- src/common/event.cpp | 21 +- src/common/ftp.cpp | 12 +- src/common/http.cpp | 15 +- src/common/object.cpp | 5 + src/common/sckint.cpp | 504 ++++++++++++++ src/common/socket.cpp | 1236 ++++++----------------------------- src/gtk.inc | 1 + src/mac/app.cpp | 2 +- src/mac/carbon/app.cpp | 2 +- src/mac/carbon/makefile.unx | 1 + src/mac/makefile.unx | 1 + src/msw/makefile.b32 | 1 + src/msw/makefile.sl | 4 + src/msw/makefile.vc | 1 + src/msw/thread.cpp | 7 + src/unix/threadpsx.cpp | 19 +- 26 files changed, 1007 insertions(+), 1184 deletions(-) create mode 100644 include/wx/sckint.h create mode 100644 src/common/sckint.cpp diff --git a/configure.in b/configure.in index 0ba2e53a66..657a3acd14 100644 --- a/configure.in +++ b/configure.in @@ -855,7 +855,7 @@ DEFAULT_wxUSE_TIMEDATE=1 DEFAULT_wxUSE_INTL=1 DEFAULT_wxUSE_CONFIG=1 DEFAULT_wxUSE_STREAMS=1 -DEFAULT_wxUSE_SOCKETS=1 +DEFAULT_wxUSE_SOCKETS=0 DEFAULT_wxUSE_SERIAL=1 DEFAULT_wxUSE_DYNLIB_CLASS=1 diff --git a/include/wx/event.h b/include/wx/event.h index 6a1fd599d9..61e6cec495 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -290,6 +290,8 @@ public: // exists only for optimization purposes bool IsCommandEvent() const { return m_isCommandEvent; } + wxObject *Clone() const; + public: bool m_skipped; wxObject* m_eventObject; diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h index d4182eda14..04503152e2 100644 --- a/include/wx/msw/setup0.h +++ b/include/wx/msw/setup0.h @@ -167,7 +167,7 @@ #define wxUSE_TOOLTIPS 1 // Define to use wxToolTip class and // wxWindow::SetToolTip() method -#define wxUSE_SOCKETS 1 +#define wxUSE_SOCKETS 0 // Set to 1 to use socket classes /* diff --git a/include/wx/object.h b/include/wx/object.h index b54f8c528a..c98a826e98 100644 --- a/include/wx/object.h +++ b/include/wx/object.h @@ -192,6 +192,7 @@ class WXDLLEXPORT wxObject virtual ~wxObject(void); virtual wxClassInfo *GetClassInfo(void) const { return &sm_classwxObject; } + virtual wxObject *Clone(void) const; bool IsKindOf(wxClassInfo *info) const; diff --git a/include/wx/sckint.h b/include/wx/sckint.h new file mode 100644 index 0000000000..e90dfb939c --- /dev/null +++ b/include/wx/sckint.h @@ -0,0 +1,144 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: sckint.h +// Purpose: Socket internal classes +// Author: Guilhem Lavaux +// Modified by: +// Created: April 1999 +// RCS-ID: $Id$ +// Copyright: (c) Guilhem Lavaux +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// +#ifndef _WX_NETWORK_SOCKET_INT_H +#define _WX_NETWORK_SOCKET_INT_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#if wxUSE_SOCKETS + +#include +#include +#include +#include + +// Socket state +class SocketState +{ + public: + // TRUE if the background notifyier is on. + bool notify_state; + // Specifies which events we want to be notified. + wxSocketBase::wxRequestNotify evt_notify_state; + // Socket flags. + wxSocketBase::wxSockFlags socket_flags; + // Pointer to the C callback function. + wxSocketBase::wxSockCbk c_callback; + char *c_callback_data; +}; + +// Socket request +class SockRequest +{ + public: + // Buffer where to get/put data. + char *buffer; + // Size of the buffer. + size_t size; + // Number of bytes really read/written. + size_t io_nbytes; + // Error. + unsigned int error; + // Type of the request. + wxSocketBase::wxRequestNotify type; + // Timeout (in milliseconds). + unsigned int timeout; + // TRUE if the buffer has been processed. + bool done; + // TRUE if we must wait for the request completion, in the other case an + // event will be sent to the main thread when the request is finished. + bool wait; +}; + +class wxSocketInternal; +class SocketWaiter: public wxThread { + public: + SocketWaiter(wxSocketBase *socket, wxSocketInternal *internal); + ~SocketWaiter(); + + // Thread Entry point + // --- + virtual void *Entry(); + + protected: + void ProcessReadEvent(); + void ProcessWriteEvent(); + + public: + wxSocketBase *m_socket; + wxSocketInternal *m_internal; + int m_fd; +}; + +class SocketRequester: public wxThread { + public: + SocketRequester(wxSocketBase *socket, wxSocketInternal *internal); + ~SocketRequester(); + + void ProcessWaitEvent(SockRequest *req); + void ProcessReadEvent(SockRequest *req); + void ProcessWriteEvent(SockRequest *req); + + bool WaitFor(wxSocketBase::wxRequestNotify req, int millisec); + + // Thread Entry point + // --- + virtual void *Entry(); + + public: + wxSocketBase *m_socket; + wxSocketInternal *m_internal; + int m_fd; +}; + +class wxSocketInternal { + public: + wxSocketInternal(wxSocketBase *socket); + ~wxSocketInternal(); + + // wxSocket thread manager + // ----------------------- + void AcquireData(); + void ReleaseData(); + void AcquireFD(); + void ReleaseFD(); + + int GetFD() { return m_fd; } + + void InitializeSocket(); + void FinalizeSocket(); + void PauseSocket(); + void ResumeSocket(); + void EnableWaiter(); + void DisableWaiter(); + + void QueueRequest(SockRequest *request, bool async); + void WaitForEnd(SockRequest *request); + + SockRequest *WaitForReq(); + void EndRequest(SockRequest *req); + public: + wxMutex m_socket_locker, m_fd_locker, m_request_locker; + wxCondition m_socket_cond; + wxSocketBase *m_socket; + SocketWaiter *m_thread_waiter; + SocketRequester *m_thread_requester; + wxList m_requests; + int m_fd; +}; + +#endif + // wxUSE_SOCKETS + +#endif + // _WX_NETWORK_SOCKET_INT_H diff --git a/include/wx/socket.h b/include/wx/socket.h index 9037f92c7b..23b6b2b8d3 100644 --- a/include/wx/socket.h +++ b/include/wx/socket.h @@ -22,15 +22,6 @@ #if defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) #include #include - -struct wxSockInternal { - UINT my_msg; -}; - -struct wxSockHandlerInternal { - HWND sockWin; - UINT firstAvailableMsg; -}; #endif // defined(__WINDOWS__) && defined(WXSOCK_INTERNAL) // --------------------------------------------------------------------------- @@ -40,29 +31,6 @@ struct wxSockHandlerInternal { #include #include #include - -// --------------------------------------------------------------------------- -// Athena specific -// --------------------------------------------------------------------------- -#if defined(__WXXT__) || defined(__WXMOTIF__) -#include - -struct wxSockInternal { - XtInputId sock_inputid, sock_outputid, sock_exceptid; -}; -#endif - -// --------------------------------------------------------------------------- -// GTK specific -// --------------------------------------------------------------------------- -#if defined(__WXGTK__) -#include - -struct wxSockInternal { - gint sock_inputid, sock_outputid, sock_exceptid; -}; -#endif - #endif // defined(__UNIX__) && defined(WXSOCK_INTERNAL) // --------------------------------------------------------------------------- @@ -77,70 +45,46 @@ struct wxSockInternal { class WXDLLEXPORT wxSocketEvent; class WXDLLEXPORT wxSocketHandler; +class wxSocketInternal; class WXDLLEXPORT wxSocketBase : public wxEvtHandler { DECLARE_CLASS(wxSocketBase) #ifdef __WXMAC__ friend void wxMacSocketOnRequestProc(void *refcon , short event) ; #endif -#if defined(__WXGTK__) && defined(WXSOCK_INTERNAL) - friend void wxPrereadSocket(wxSocketBase *sock); -#endif public: enum wxSockFlags { NONE=0, NOWAIT=1, WAITALL=2, SPEED=4 }; // Type of request enum { REQ_READ=0x1, REQ_PEEK=0x2, REQ_WRITE=0x4, REQ_LOST=0x8, - REQ_ACCEPT=0x10, REQ_CONNECT=0x20}; + REQ_ACCEPT=0x10, REQ_CONNECT=0x20, REQ_WAIT=0x40}; enum { EVT_READ=0, EVT_PEEK=1, EVT_WRITE=2, EVT_LOST=3, EVT_ACCEPT=4, EVT_CONNECT=5 }; typedef int wxRequestNotify; typedef int wxRequestEvent; + enum wxSockType { SOCK_CLIENT, SOCK_SERVER, SOCK_INTERNAL, SOCK_UNINIT }; typedef void (*wxSockCbk)(wxSocketBase& sock,wxRequestEvent evt,char *cdata); protected: - wxList req_list[EVT_WRITE+1]; - - // Internal use for SaveState() and RestoreState() - class wxSockState : public wxObject { - public: - bool cbk_on; - wxSockCbk cbk; - char *cdata; - bool notif; - wxRequestNotify cbk_set; - wxSockFlags flags; - }; - typedef struct { - char sig[4]; - char len[4]; - } SockMsg; - enum wxSockType { SOCK_CLIENT, SOCK_SERVER, SOCK_INTERNAL, SOCK_UNINIT }; - wxSockFlags m_flags; wxSockType m_type; // wxSocket type bool m_connected, m_connecting; // State of the socket int m_fd; // Socket file descriptors - int m_waitflags; // Wait flags wxList m_states; // States list - wxSockCbk m_cbk; // C callback - char *m_cdata; // C callback data int m_id; // Socket id (for event handler) wxSocketHandler *m_handler; // the current socket handler wxRequestNotify m_neededreq; // Specify which requet signals we need - bool m_cbkon; - char *m_unread; // The unread buf - size_t m_unrd_size; // The size of the unread buf - bool m_processing; // To prevent some endless loop unsigned long m_timeout; - int m_wantbuf; size_t m_lcount; // Last IO request size int m_error; // Last IO error - bool m_notifyme; - - struct wxSockInternal *m_internal; // System specific variables - + wxSocketInternal *m_internal; + char *m_unread; // Pushback buffer + size_t m_unrd_size; // Pushback buffer size + wxSockCbk m_cbk; + char *m_cdata; + bool m_notify_state; + public: wxSocketBase(); virtual ~wxSocketBase(); @@ -150,8 +94,6 @@ public: wxSocketBase& Peek(char* buffer, size_t nbytes); wxSocketBase& Read(char* buffer, size_t nbytes); wxSocketBase& Write(const char *buffer, size_t nbytes); - wxSocketBase& WriteMsg(const char *buffer, size_t nbytes); - wxSocketBase& ReadMsg(char* buffer, size_t nbytes); wxSocketBase& Unread(const char *buffer, size_t nbytes); void Discard(); @@ -168,8 +110,10 @@ public: bool IsData() const; inline size_t LastCount() const { return m_lcount; } inline int LastError() const { return m_error; } + inline wxSockType GetType() const { return m_type; } void SetFlags(wxSockFlags _flags); + wxSockFlags GetFlags() const; inline void SetTimeout(unsigned long sec) { m_timeout = sec; } // seconds = -1 means infinite wait @@ -213,6 +157,7 @@ public: protected: friend class wxSocketServer; friend class wxSocketHandler; + friend class wxSocketInternal; #ifdef __SALFORDC__ public: @@ -230,10 +175,6 @@ protected: inline virtual void SetHandler(wxSocketHandler *handler) { m_handler = handler; } - // Activate or disactivate callback - void SetupCallbacks(); - void DestroyCallbacks(); - // Pushback library size_t GetPushback(char *buffer, size_t size, bool peek); @@ -241,8 +182,6 @@ protected: // ==> cause strange things :-) void WantSpeedBuffer(char *buffer, size_t size, wxRequestEvent req); void WantBuffer(char *buffer, size_t size, wxRequestEvent req); - - virtual bool DoRequests(wxRequestEvent req); }; //////////////////////////////////////////////////////////////////////// @@ -258,7 +197,6 @@ public: wxSocketBase* Accept(); bool AcceptWith(wxSocketBase& sock); - virtual void OnRequest(wxRequestEvent flags); }; //////////////////////////////////////////////////////////////////////// @@ -284,10 +222,6 @@ class WXDLLEXPORT wxSocketHandler : public wxObject { DECLARE_CLASS(wxSocketHandler) protected: -#if defined(__WINDOWS__) - wxList *smsg_list; - struct wxSockHandlerInternal *internal; -#endif wxList *socks; public: @@ -337,15 +271,17 @@ public: wxSocketEvent(int id = 0); wxSocketBase::wxRequestEvent SocketEvent() const { return m_skevt; } + wxSocketBase *Socket() const { return m_socket; } + + wxObject *Clone() const; public: wxSocketBase::wxRequestEvent m_skevt; + wxSocketBase *m_socket; }; typedef void (wxEvtHandler::*wxSocketEventFunction)(wxSocketEvent&); -#define wxEVT_SOCKET wxEVT_FIRST+301 - -#define EVT_SOCKET(id, func) { wxEVT_SOCKET, id, 0, \ +#define EVT_SOCKET(id, func) { wxEVT_SOCKET, id, -1, \ (wxObjectEventFunction) (wxEventFunction) (wxSocketEventFunction) & func, \ (wxObject *) NULL }, diff --git a/include/wx/thread.h b/include/wx/thread.h index 82c7847447..b0bbc261f7 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -301,7 +301,7 @@ public: // Returns true if the thread is running (not paused, not killed). bool IsRunning() const; // Returns true if the thread is suspended - bool IsPaused() const { return IsAlive() && !IsRunning(); } + bool IsPaused() const; // called when the thread exits - in the context of this thread // diff --git a/include/wx/wfstream.h b/include/wx/wfstream.h index 29f13ca1e4..b0f4dbb02a 100644 --- a/include/wx/wfstream.h +++ b/include/wx/wfstream.h @@ -53,8 +53,8 @@ class wxFileOutputStream: public wxOutputStream { virtual ~wxFileOutputStream(); // To solve an ambiguity on GCC - inline wxOutputStream& Write(const void *buffer, size_t size) - { return wxOutputStream::Write(buffer, size); } +// inline wxOutputStream& Write(const void *buffer, size_t size) +// { return wxOutputStream::Write(buffer, size); } void Sync(); size_t StreamSize() const; diff --git a/samples/wxsocket/client.cpp b/samples/wxsocket/client.cpp index 27051c68a8..bbda2d7525 100644 --- a/samples/wxsocket/client.cpp +++ b/samples/wxsocket/client.cpp @@ -23,6 +23,7 @@ #include "wx/wx.h" #endif +#include "wx/wfstream.h" #include "wx/socket.h" #include "wx/url.h" #include "wx/protocol/http.h" @@ -204,12 +205,12 @@ void MyFrame::UpdateStatus() SetStatusText("", 1); } else { wxIPV4address addr; - char s[100]; + wxChar s[100]; sock->GetPeer(addr); - sprintf(s, "Connected to %s", (const char *)addr.Hostname()); + wxSprintf(s, _T("Connected to %s"), WXSTRINGCAST addr.Hostname()); SetStatusText(s, 0); - sprintf(s, "Service: %d", addr.Service()); + wxSprintf(s, _T("Service: %d"), addr.Service()); SetStatusText(s, 1); } } @@ -225,7 +226,7 @@ void MyFrame::OnExecTest1(wxCommandEvent& WXUNUSED(evt)) wxTE_MULTILINE); (void)new wxButton(dlgbox, ID_TEST_CLOSE, "Close", wxPoint(100, 210), wxSize(100, -1)); - char *buf, *buf2; + wxChar *buf, *buf2; dlgbox->Layout(); dlgbox->Show(TRUE); @@ -235,21 +236,25 @@ void MyFrame::OnExecTest1(wxCommandEvent& WXUNUSED(evt)) wxYield(); /* Init */ - buf = copystring("Hi ! Hi ! Hi !\n"); - buf2 = new char[strlen(buf)+1]; + buf = copystring(_T("Hi ! Hi ! Hi !\n")); + buf2 = new wxChar[wxStrlen(buf)+1]; char c = 0xbe; - sock->WriteMsg(&c, 1); + sock->Write(&c, 1); /* No 1 */ text_win->WriteText("Sending some byte to the server ..."); - sock->Write(buf, strlen(buf)+1); + wxYield(); + sock->Write((char *)buf, wxStrlen(buf)+1); text_win->WriteText("done\n"); + wxYield(); text_win->WriteText("Receiving some byte from the server ..."); - sock->Read(buf2, strlen(buf)+1); + wxYield(); + sock->Read((char *)buf2, wxStrlen(buf)+1); text_win->WriteText("done\n"); + wxYield(); text_win->WriteText("Comparing the two buffers ..."); - if (memcmp(buf, buf2, strlen(buf)+1) != 0) { + if (memcmp(buf, buf2, wxStrlen(buf)+1) != 0) { text_win->WriteText("Fail\n"); sock->Close(); UpdateStatus(); @@ -276,7 +281,11 @@ void MyFrame::OnExecUrlTest(wxCommandEvent& WXUNUSED(evt)) if (!datas) wxMessageBox("Error in getting data from the URL.", "Alert !"); else { + wxFileOutputStream *str_out = new wxFileOutputStream("test.url"); + str_out->Write(*datas); + wxMessageBox("Success !! Click on OK to see the text.", "OK"); delete datas; + delete str_out; } } diff --git a/samples/wxsocket/server.cpp b/samples/wxsocket/server.cpp index 8eefa8ca1e..45825d88fb 100644 --- a/samples/wxsocket/server.cpp +++ b/samples/wxsocket/server.cpp @@ -42,37 +42,28 @@ class MyFrame: public wxFrame { DECLARE_EVENT_TABLE() public: - MyServer *sock; + wxSocketServer *sock; int nb_clients; MyFrame(wxFrame *frame); virtual ~MyFrame(); void Menu_Exit(wxCommandEvent& evt); + void OnSockRequest(wxSocketEvent& evt); + void OnSockRequestServer(wxSocketEvent& evt); void ExecTest1(wxSocketBase *sock_o); void UpdateStatus(int incr); }; #define SKDEMO_QUIT 101 +#define SKDEMO_SOCKET_SERV 102 +#define SKDEMO_SOCKET 103 BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(SKDEMO_QUIT, MyFrame::Menu_Exit) + EVT_SOCKET(SKDEMO_SOCKET_SERV, MyFrame::OnSockRequestServer) + EVT_SOCKET(SKDEMO_SOCKET, MyFrame::OnSockRequest) END_EVENT_TABLE() -class MySock: public wxSocketBase { -public: - MyFrame *frame; - - void OldOnNotify(wxRequestEvent flags); -}; - -class MyServer: public wxSocketServer { -public: - MyFrame *frame; - - MyServer(wxSockAddress& addr) : wxSocketServer(addr) { } - void OldOnNotify(wxRequestEvent flags); -}; - IMPLEMENT_APP(MyApp) // `Main program' equivalent, creating windows and returning main app frame @@ -102,40 +93,50 @@ bool MyApp::OnInit(void) return TRUE; } -void MySock::OldOnNotify(wxRequestEvent flags) +extern wxList wxPendingDelete; + +void MyFrame::OnSockRequest(wxSocketEvent& evt) { - extern wxList WXDLLEXPORT wxPendingDelete; + wxSocketBase *sock = evt.Socket(); - switch (flags) { - case EVT_READ: + printf("OnSockRequest OK\n"); + printf("OnSockRequest (event = %d)\n",evt.SocketEvent()); + switch (evt.SocketEvent()) { + case wxSocketBase::EVT_READ: unsigned char c; - ReadMsg((char *)&c, 1); + sock->Read((char *)&c, 1); if (c == 0xbe) - frame->ExecTest1(this); + ExecTest1(sock); break; - case EVT_LOST: - frame->UpdateStatus(-1); - wxPendingDelete.Append(this); + case wxSocketBase::EVT_LOST: + UpdateStatus(-1); + printf("Destroying socket\n"); + wxPendingDelete.Append(sock); + return; break; } + printf("OnSockRequest Exiting\n"); + sock->SetNotify(wxSocketBase::REQ_READ | wxSocketBase::REQ_LOST); } -void MyServer::OldOnNotify(wxRequestEvent WXUNUSED(flags)) +void MyFrame::OnSockRequestServer(wxSocketEvent& evt) { - MySock *sock2 = new MySock(); + wxSocketBase *sock2; + wxSocketServer *server = (wxSocketServer *) evt.Socket(); - if (!AcceptWith(*sock2)) - return; + printf("OnSockRequestServer OK\n"); - m_handler->Register(sock2); + sock2 = server->Accept(); + if (sock2 == NULL) + return; - sock2->SetFlags(NONE); - sock2->frame = frame; - sock2->SetNotify(REQ_READ | REQ_LOST); + sock2->SetFlags(wxSocketBase::NONE); sock2->Notify(TRUE); - frame->UpdateStatus(1); + sock2->SetEventHandler(*this, SKDEMO_SOCKET); + server->SetNotify(wxSocketBase::REQ_ACCEPT); + UpdateStatus(1); } // My frame Constructor @@ -149,10 +150,10 @@ MyFrame::MyFrame(wxFrame *frame): // Init all wxSocketHandler::Master(); - sock = new MyServer(addr); + sock = new wxSocketServer(addr); wxSocketHandler::Master().Register(sock); - sock->frame = this; sock->SetNotify(wxSocketBase::REQ_ACCEPT); + sock->SetEventHandler(*this, SKDEMO_SOCKET_SERV); sock->Notify(TRUE); nb_clients = 0; diff --git a/src/common/event.cpp b/src/common/event.cpp index 6a44755477..2f4f8be170 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -105,6 +105,22 @@ wxEvent::wxEvent(int theId) m_isCommandEvent = FALSE; } +wxObject *wxEvent::Clone() const +{ + wxEvent *event = (wxEvent *)wxObject::Clone(); + + event->m_eventType = m_eventType; + event->m_eventObject = m_eventObject; + event->m_eventHandle = m_eventHandle; + event->m_timeStamp = m_timeStamp; + event->m_id = m_id; + event->m_skipped = m_skipped; + event->m_callbackUserData = m_callbackUserData; + event->m_isCommandEvent = m_isCommandEvent; + + return event; +} + /* * Command events * @@ -317,10 +333,10 @@ wxEvtHandler::~wxEvtHandler() delete m_dynamicEvents; }; +#if wxUSE_THREADS if (m_pendingEvents) delete m_pendingEvents; -#if wxUSE_THREADS delete m_eventsLocker; #endif } @@ -337,8 +353,7 @@ bool wxEvtHandler::ProcessThreadEvent(wxEvent& event) if (m_pendingEvents == NULL) m_pendingEvents = new wxList(); - event_main = (wxEvent *)event.GetClassInfo()->CreateObject(); - *event_main = event; + event_main = (wxEvent *)event.Clone(); m_pendingEvents->Append(event_main); diff --git a/src/common/ftp.cpp b/src/common/ftp.cpp index 5e8ce27493..fddfb1d185 100644 --- a/src/common/ftp.cpp +++ b/src/common/ftp.cpp @@ -60,16 +60,13 @@ IMPLEMENT_PROTOCOL(wxFTP, _T("ftp"), _T("ftp"), TRUE) wxFTP::wxFTP() : wxProtocol() { - wxChar tmp[256]; - m_lastError = wxPROTO_NOERR; m_streaming = FALSE; m_user = _T("anonymous"); - wxGetUserName(tmp, 256); - m_passwd.sprintf(_T("%s@"),tmp); - wxGetHostName(tmp, 256); - m_passwd += tmp; + m_passwd = wxGetUserId(); + m_passwd += '@'; + m_passwd += wxGetHostName(); SetNotify(0); } @@ -404,9 +401,12 @@ wxList *wxFTP::GetList(const wxString& wildcard) return NULL; } + // Ininterresting ?! + /* sock->SetEventHandler(*GetNextHandler(), m_id); sock->Notify(m_notifyme); sock->SetNotify(m_neededreq); + */ return file_list; } diff --git a/src/common/http.cpp b/src/common/http.cpp index a50e3ea140..38cb120b72 100644 --- a/src/common/http.cpp +++ b/src/common/http.cpp @@ -116,6 +116,7 @@ void wxHTTP::SendHeaders() bool wxHTTP::ParseHeaders() { wxString line; + wxStringTokenizer tokenzr; m_headers.Clear(); m_read = TRUE; @@ -128,17 +129,13 @@ bool wxHTTP::ParseHeaders() if (line.Length() == 0) break; - wxPrintf(_T("Header: %s\n"), WXSTRINGCAST line); - int pos = line.Find(':'); - if (pos == -1) + printf("Header: %s\n", WXSTRINGCAST line); + tokenzr.SetString(line, " :\t\n\r"); + if (!tokenzr.HasMoreToken()) return FALSE; - wxString left_str = line(0, pos); - wxString right_str = line(pos+1, line.Length()); - - right_str = right_str.Strip(wxString::leading); - - wxString *str = new wxString(right_str); + wxString left_str = tokenzr.GetNextToken(); + wxString *str = new wxString(tokenzr.GetNextToken()); m_headers.Append(left_str, (wxObject *) str); } diff --git a/src/common/object.cpp b/src/common/object.cpp index c5b9737d3d..5b65936689 100644 --- a/src/common/object.cpp +++ b/src/common/object.cpp @@ -87,6 +87,11 @@ bool wxObject::IsKindOf(wxClassInfo *info) const return FALSE; } +wxObject *wxObject::Clone() const +{ + return GetClassInfo()->CreateObject(); +} + #if defined(__WXDEBUG__) || wxUSE_DEBUG_CONTEXT void wxObject::Dump(ostream& str) { diff --git a/src/common/sckint.cpp b/src/common/sckint.cpp new file mode 100644 index 0000000000..712f1006e3 --- /dev/null +++ b/src/common/sckint.cpp @@ -0,0 +1,504 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: socket.cpp +// Purpose: Socket handler classes +// Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew +// Davidson(1995) in wxWeb) +// Created: April 1997 +// Updated: April 1999 +// Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux +// RCS_ID: $Id$ +// License: see wxWindows license +/////////////////////////////////////////////////////////////////////////////// +#ifdef __GNUG__ +#pragma implementation "sckint.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#if wxUSE_SOCKETS + +#define WXSOCK_INTERNAL +#include +#include +#include +#include +#include + +#ifndef __WXSTUBS__ + +#include +#include +#include + +// ----------------------- +// System specific headers +// ----------------------- + +#ifdef __WXMAC__ +// in order to avoid problems with our c library and double definitions +#define close closesocket +#define ioctl ioctlsocket + +#include +#endif + +#if defined(__WINDOWS__) +#include +#endif // __WINDOWS__ + +#if defined(__UNIX__) + +#ifdef VMS +#include +#else +#include +#endif +#include + +#include +#include + +#ifdef sun +#include +#endif + +#endif // __UNIX__ + +#include +#include + +#ifdef __VISUALC__ +#include +#endif + +// Constants +#define READ_MASK wxSocketBase::REQ_READ | wxSocketBase::REQ_ACCEPT | wxSocketBase::REQ_LOST +#define WRITE_MASK wxSocketBase::REQ_WRITE | wxSocketBase::REQ_CONNECT + +// -------------------------------------------------------------- +// --------- SocketWaiter --------------------------------------- +// -------------------------------------------------------------- + +SocketWaiter::SocketWaiter(wxSocketBase *socket, + wxSocketInternal *internal) + : m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) +{ +} + +SocketWaiter::~SocketWaiter() +{ +} + +void SocketWaiter::ProcessReadEvent() +{ + int ret; + char c; + + ret = recv(m_fd, &c, 1, MSG_PEEK); + + // We are a server => emit a EVT_ACCEPT event. + if (ret == -1 && m_socket->GetType() == wxSocketBase::SOCK_SERVER) { + m_socket->OnRequest(wxSocketBase::EVT_ACCEPT); + return; + } + + // Else, no error => there is something to be read else + // we've lost the connection. + if (ret > 0) + m_socket->OnRequest(wxSocketBase::EVT_READ); + else { + m_socket->OnRequest(wxSocketBase::EVT_LOST); + Exit(NULL); + } +} + +void SocketWaiter::ProcessWriteEvent() +{ + if (m_socket->IsConnected()) + m_socket->OnRequest(wxSocketBase::EVT_CONNECT); + else + m_socket->OnRequest(wxSocketBase::EVT_WRITE); +} + +void *SocketWaiter::Entry() +{ + struct timeval tv; + fd_set sockrd_set, sockwr_set; + wxSocketEvent event; + int ret; + + while (1) { + // We won't wait. + tv.tv_sec = 0; + tv.tv_usec = 0; + + FD_ZERO(&sockrd_set); + FD_ZERO(&sockwr_set); + + if ((m_socket->NeededReq() & READ_MASK) != 0) + FD_SET(m_fd, &sockrd_set); + if ((m_socket->NeededReq() & WRITE_MASK) != 0) + FD_SET(m_fd, &sockwr_set); + + m_internal->AcquireFD(); + ret = select(FD_SETSIZE, &sockrd_set, &sockwr_set, NULL, &tv); + m_internal->ReleaseFD(); + + if (FD_ISSET(m_fd, &sockrd_set)) + ProcessReadEvent(); + + if (FD_ISSET(m_fd, &sockwr_set)) + ProcessWriteEvent(); + + if (ret == 0) + // If nothing happened, we wait for 100 ms. + wxThread::Sleep(10); + else + wxThread::Yield(); + + // Check whether we should exit. + if (TestDestroy()) + return NULL; + } + return NULL; +} + +// -------------------------------------------------------------- +// --------- SocketRequester ------------------------------------ +// -------------------------------------------------------------- + +SocketRequester::SocketRequester(wxSocketBase *socket, + wxSocketInternal *internal) + : m_socket(socket), m_internal(internal), m_fd(internal->GetFD()) +{ +} + +SocketRequester::~SocketRequester() +{ +} + +bool SocketRequester::WaitFor(wxSocketBase::wxRequestNotify req, int millisec) +{ + int ret; + struct timeval tv; + fd_set sockrd_set, sockwr_set; + + // We won't wait. + tv.tv_sec = millisec / 1000; + tv.tv_usec = (millisec % 1000) * 1000; + + if ((req & READ_MASK) != 0) + FD_ZERO(&sockrd_set); + FD_ZERO(&sockwr_set); + + FD_SET(m_fd, &sockrd_set); + FD_SET(m_fd, &sockwr_set); + + m_internal->AcquireFD(); + ret = select(FD_SETSIZE, &sockrd_set, &sockwr_set, NULL, &tv); + m_internal->ReleaseFD(); + + return (ret != 0); +} + +void SocketRequester::ProcessReadEvent(SockRequest *req) +{ + int ret; + size_t len; + + // We'll wait for the first byte, in case a "timeout event" occurs it returns // immediately + if (!WaitFor(wxSocketBase::REQ_READ, req->timeout)) { + m_internal->EndRequest(req); + return; + } + + m_internal->AcquireFD(); + ret = recv(m_fd, req->buffer, req->size, + (req->type == wxSocketBase::REQ_PEEK) ? MSG_PEEK : 0); + m_internal->ReleaseFD(); + + // An error occured, we exit. + if (ret < 0) { + req->error = errno; + m_internal->EndRequest(req); + return; + } + len = ret; + + // If the buffer isn't full (and we want it to be full), we don't unqueue it. + if ((len < req->size) && (m_socket->GetFlags() & wxSocketBase::WAITALL)) { + req->size -= len; + req->io_nbytes += len; + req->buffer += len; + return; + } + // The End. + req->io_nbytes += len; + m_internal->EndRequest(req); +} + +void SocketRequester::ProcessWriteEvent(SockRequest *req) +{ + int ret; + size_t len; + + m_internal->AcquireFD(); + ret = send(m_fd, req->buffer, req->size, 0); + m_internal->ReleaseFD(); + if (ret < 0) { + req->error = errno; + m_internal->EndRequest(req); + return; + } + len = ret; + if ((len < req->size) && ((m_socket->GetFlags() & wxSocketBase::WAITALL) != 0)) { + req->size -= len; + req->io_nbytes += len; + req->buffer += len; + return; + } + req->io_nbytes += len; + m_internal->EndRequest(req); +} + +void SocketRequester::ProcessWaitEvent(SockRequest *req) +{ + if (WaitFor(req->type, req->timeout)) + req->io_nbytes = 1; // We put 1 in the counter to tell the requester + // there is no timeout. + else + req->io_nbytes = 0; + + m_internal->EndRequest(req); +} + +void *SocketRequester::Entry() +{ + SockRequest *req; + + while (1) { + // Wait for a new request or a destroy message. + req = m_internal->WaitForReq(); + if (TestDestroy() || req == NULL) + return NULL; + + if ((req->type & wxSocketBase::REQ_WAIT) != 0) { + ProcessWaitEvent(req); + continue; + } + + switch (req->type) { + case wxSocketBase::REQ_READ: + case wxSocketBase::REQ_PEEK: + ProcessReadEvent(req); + break; + case wxSocketBase::REQ_WRITE: + ProcessWriteEvent(req); + break; + } + } + return NULL; +} + +// -------------------------------------------------------------- +// --------- wxSocketInternal ----------------------------------- +// -------------------------------------------------------------- + +wxSocketInternal::wxSocketInternal(wxSocketBase *socket) +{ + m_socket = socket; + m_thread_waiter = new SocketWaiter(socket, this); + m_thread_requester = new SocketRequester(socket, this); + m_request_locker.Lock(); +} + +wxSocketInternal::~wxSocketInternal() +{ + wxASSERT(!m_finalized); + m_request_locker.Unlock(); + delete m_thread_waiter; + delete m_thread_requester; +} + +// ---------------------------------------------------------------------- +// WaitForReq: it is called by SocketRequester and should return the next +// socket request if available +// ---------------------------------------------------------------------- +SockRequest *wxSocketInternal::WaitForReq() +{ + wxNode *node; + + node = m_requests.First(); + if (node == NULL) { + m_socket_cond.Wait(m_request_locker); + + node = m_requests.First(); + if (node == NULL) + return NULL; + } + + return (SockRequest *)node->Data(); +} + +// ---------------------------------------------------------------------- +// EndRequest: Should be called to finalize a request +// ---------------------------------------------------------------------- +void wxSocketInternal::EndRequest(SockRequest *req) +{ + wxNode *node = NULL; + + req->done = TRUE; + + node = m_requests.Member((wxObject *)req); + if (node != NULL) + delete node; +} + +void wxSocketInternal::AcquireFD() +{ + m_fd_locker.Lock(); +} + +void wxSocketInternal::ReleaseFD() +{ + m_fd_locker.Unlock(); +} + +// ---------------------------------------------------------------------- +// InitializeSocket: called by wxSocketBase to initialize the daemons with +// a new file descriptor and to create them +// ---------------------------------------------------------------------- +void wxSocketInternal::InitializeSocket() +{ + wxASSERT( ((m_thread_waiter->IsAlive() && !m_thread_waiter->IsPaused()) || + (m_thread_requester->IsAlive() && !m_thread_requester->IsPaused()))); + + m_thread_waiter->m_fd = m_socket->m_fd; + m_thread_requester->m_fd = m_socket->m_fd; + + if (m_thread_waiter->IsPaused()) + ResumeSocket(); + else { + + if (m_thread_waiter->Create() != wxTHREAD_NO_ERROR) { + // Something should be done here. + return; + } + + if (m_thread_requester->Create() != wxTHREAD_NO_ERROR) { + // Something should be done here. + return; + } + + m_thread_waiter->Run(); + m_thread_requester->Run(); + } +} + + +// ---------------------------------------------------------------------- +// InitializeSocket: called by wxSocketBase to destroy daemons +// ---------------------------------------------------------------------- +void wxSocketInternal::FinalizeSocket() +{ + wxASSERT( (!m_thread_waiter->IsAlive() && !m_thread_requester->IsAlive()) ); + + ResumeSocket(); + + m_thread_waiter->Delete(); + m_socket_locker.Lock(); + if (m_requests.Number() == 0) + m_socket_cond.Signal(); + m_socket_locker.Unlock(); + + m_thread_requester->Delete(); +} + +void wxSocketInternal::PauseSocket() +{ + if (m_thread_waiter != NULL && !m_thread_waiter->IsPaused()) + m_thread_waiter->Pause(); +} + +void wxSocketInternal::ResumeSocket() +{ + if (m_thread_waiter != NULL && m_thread_waiter->IsPaused()) + m_thread_waiter->Resume(); +} + +void wxSocketInternal::EnableWaiter() +{ + if (m_thread_waiter != NULL && m_thread_waiter->IsPaused()) + m_thread_waiter->Resume(); +} + +void wxSocketInternal::DisableWaiter() +{ + if (m_thread_waiter != NULL && !m_thread_waiter->IsPaused()) + m_thread_waiter->Pause(); +} + +// ---------------------------------------------------------------------- +// QueueRequest: +// ---------------------------------------------------------------------- +void wxSocketInternal::QueueRequest(SockRequest *request, bool async) +{ + if (async) { + m_request_locker.Lock(); + request->done = FALSE; + m_requests.Append((wxObject *)request); + m_request_locker.Unlock(); + + // Wake up + m_socket_cond.Signal(); + + if (request->wait) { + if (wxThread::IsMain()) + while (!request->done) { + wxYield(); + } + else + while (!request->done) { + wxThread::Yield(); + } + } + + } else { + m_request_locker.Lock(); + + if ((request->type & wxSocketBase::REQ_WAIT) != 0) { + m_thread_requester->ProcessWaitEvent(request); + } else { + + request->done = FALSE; + + switch (request->type) { + case wxSocketBase::REQ_PEEK: + case wxSocketBase::REQ_READ: + m_thread_requester->ProcessReadEvent(request); + break; + case wxSocketBase::REQ_WRITE: + m_thread_requester->ProcessWriteEvent(request); + break; + } + } + request->done = TRUE; + m_request_locker.Unlock(); + } +} + +void wxSocketInternal::WaitForEnd(SockRequest *request) +{ + // TODOTODO +} + +#endif + // __WXSTUBS__ + +#endif + // wxUSE_SOCKETS diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 8c576605c1..0585cddd1b 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -4,8 +4,8 @@ // Authors: Guilhem Lavaux (completely rewritten from a basic API of Andrew // Davidson(1995) in wxWeb) // Created: April 1997 -// Updated: March 1998 -// Copyright: (C) 1998, 1997, Guilhem Lavaux +// Updated: April 1999 +// Copyright: (C) 1999 1998, 1997, Guilhem Lavaux // RCS_ID: $Id$ // License: see wxWindows license //////////////////////////////////////////////////////////////////////////////// @@ -51,46 +51,27 @@ typedef int socklen_t ; #define ioctl ioctlsocket #include -extern GUSISpinFn GUSISpin; -#define PROCESS_EVENTS() wxMacProcessEvents() -const short kwxMacNetEventsMax = 1000 ; -short wxMacNetEventsTop = 0 ; -short wxMacNetEventsBottom = 0 ; -short wxMacNetEventsEvents[kwxMacNetEventsMax] ; -void *wxMacNetEventsReferences[kwxMacNetEventsMax] ; - -#define FD_READ 1 -#define FD_WRITE 2 -#define FD_CLOSE 4 -#define FD_ACCEPT 8 -#define FD_CONNECT 16 -#define FD_READY 32 - -extern "C" void wxMacSocketHandlerProc( void *refcon , short event ) ; // adds events -extern "C" void wxMacSocketOnRequestProc( void *refcon , short event ) ; // consumes them -extern "C" void GUSISetReference( short sock , short eventmask , void * data ) ; -void wxMacProcessEvents() ; + #endif #if defined(__WINDOWS__) - #include +#include #endif // __WINDOWS__ #if defined(__UNIX__) #ifdef VMS - #include -#else // !VMS - #include -#endif // VMS/!VMS - +#include +#else +#include +#endif #include #include #include #ifdef sun - #include +#include #endif #endif // __UNIX__ @@ -99,37 +80,21 @@ void wxMacProcessEvents() ; #include #ifdef __VISUALC__ - #include -#endif - -#if defined(__WXMOTIF__) || defined(__WXXT__) - #include - - ///////////////////////////// - // Needs internal variables - ///////////////////////////// - #ifdef __WXXT__ - #define Uses_XtIntrinsic - #endif -#endif // Motif or Xt - -#if defined(__WXGTK__) - #include +#include #endif ///////////////////////////////////////////////////////////////////////////// // wxSocket headers ///////////////////////////////////////////////////////////////////////////// -#include "wx/module.h" - +#include #define WXSOCK_INTERNAL +#include +#include +#include -#include "wx/sckaddr.h" -#include "wx/socket.h" - -///////////////////////////////////////////////////////////////////////////// -// Some patch ///// BEGIN -///////////////////////////////////////////////////////////////////////////// +// ---------------------- +// Some patch ----- BEGIN +// ---------------------- #ifdef __WINDOWS__ #define close closesocket #define ioctl ioctlsocket @@ -150,10 +115,6 @@ void wxMacProcessEvents() ; #define INVALID_SOCKET -1 #endif -#ifdef __WXMOTIF__ -#define wxAPP_CONTEXT ((XtAppContext)wxTheApp->GetAppContext()) -#endif - #ifdef __WINDOWS__ // This is an MS TCP/IP routine and is not needed here. Some WinSock // implementations (such as PC-NFS) will require you to include this @@ -175,17 +136,9 @@ int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set) #endif #endif -#if defined(__WINDOWS__) - #define PROCESS_EVENTS() wxYield() -#elif defined(__WXXT__) || defined(__WXMOTIF__) - #define PROCESS_EVENTS() XtAppProcessEvent(wxAPP_CONTEXT, XtIMAll) -#elif defined(__WXGTK__) - #define PROCESS_EVENTS() gtk_main_iteration() -#endif - -///////////////////////////////////////////////////////////////////////////// -// Some patch ///// END -///////////////////////////////////////////////////////////////////////////// +// ------------------- +// Some patch ---- END +// ------------------- #ifdef GetClassInfo #undef GetClassInfo @@ -207,50 +160,14 @@ public: // ClassInfos // -------------------------------------------------------------- #if !USE_SHARED_LIBRARY - IMPLEMENT_CLASS(wxSocketBase, wxObject) - IMPLEMENT_CLASS(wxSocketServer, wxSocketBase) - IMPLEMENT_CLASS(wxSocketClient, wxSocketBase) - IMPLEMENT_CLASS(wxSocketHandler, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent) - IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule) +IMPLEMENT_CLASS(wxSocketBase, wxObject) +IMPLEMENT_CLASS(wxSocketServer, wxSocketBase) +IMPLEMENT_CLASS(wxSocketClient, wxSocketBase) +IMPLEMENT_CLASS(wxSocketHandler, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent) +IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule) #endif -class wxSockWakeUp : public wxTimer -{ -public: - int *my_id; - int n_val; - wxSocketBase *sock; - - wxSockWakeUp(wxSocketBase *_sock, int *id, int new_val) - { - my_id = id; n_val = new_val; - sock = _sock; - } - virtual void Notify() - { - *my_id = n_val; - if (sock) sock->Notify(FALSE); - } -}; - -/// Socket request -class SockRequest : public wxObject -{ -public: - char *buffer; - size_t size, nbytes; - bool done; - int error; - wxSockWakeUp *auto_wakeup; - wxSocketBase::wxRequestNotify type; -}; - - -///////////////////////////////////////////////////////////////////////////// -// Some internal define -///////////////////////////////////////////////////////////////////////////// - // -------------------------------------------------------------- // --------- wxSocketBase CONSTRUCTOR --------------------------- // -------------------------------------------------------------- @@ -258,46 +175,29 @@ wxSocketBase::wxSocketBase(wxSocketBase::wxSockFlags _flags, wxSocketBase::wxSockType _type) : wxEvtHandler(), m_flags(_flags), m_type(_type), m_connected(FALSE), m_connecting(FALSE), - m_fd(INVALID_SOCKET), m_waitflags(0), m_cbk(0), m_cdata(0), m_id(-1), + m_fd(INVALID_SOCKET), m_id(-1), m_handler(0), m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)), - m_cbkon(FALSE), + m_timeout(3600), m_unread(NULL), m_unrd_size(0), - m_processing(FALSE), - m_timeout(3600), m_wantbuf(0) + m_cbk(NULL), m_cdata(NULL), + m_notify_state(FALSE) { - m_internal = new wxSockInternal; -#if defined(__WXXT__) || defined(__WXMOTIF__) || defined(__WXGTK__) - m_internal->sock_inputid = 0; - m_internal->sock_outputid = 0; - m_internal->sock_exceptid = 0; -#endif -#ifdef __WINDOWS__ - m_internal->my_msg = 0; -#endif + m_internal = new wxSocketInternal(this); } wxSocketBase::wxSocketBase() : wxEvtHandler(), m_flags(WAITALL), m_type(SOCK_UNINIT), m_connected(FALSE), - m_connecting(FALSE), m_fd(INVALID_SOCKET), m_waitflags(0), - m_cbk(0), m_cdata(0), + m_connecting(FALSE), m_fd(INVALID_SOCKET), m_id(-1), m_handler(0), m_neededreq((wxRequestNotify)(REQ_READ | REQ_LOST)), - m_cbkon(FALSE), + m_timeout(3600), m_unread(NULL), m_unrd_size(0), - m_processing(FALSE), - m_timeout(3600), m_wantbuf(0) + m_cbk(NULL), m_cdata(NULL), + m_notify_state(FALSE) { - m_internal = new wxSockInternal; -#if defined(__WXXT__) || defined(__WXMOTIF__) || defined(__WXGTK__) - m_internal->sock_inputid = 0; - m_internal->sock_outputid = 0; - m_internal->sock_exceptid = 0; -#endif -#ifdef __WINDOWS__ - m_internal->my_msg = 0; -#endif + m_internal = new wxSocketInternal(this); } // -------------------------------------------------------------- @@ -306,21 +206,21 @@ wxSocketBase::wxSocketBase() : wxSocketBase::~wxSocketBase() { - DestroyCallbacks(); + // First, close the file descriptor. Close(); + m_internal->FinalizeSocket(); + if (m_unread) free(m_unread); + // Unregister from the handler database. if (m_handler) - { -#ifdef __WINDOWS__ - if (m_internal->my_msg) - m_handler->DestroyMessage(m_internal->my_msg); -#endif m_handler->UnRegister(this); - } + + // Destroy all saved states. m_states.DeleteContents(TRUE); + // Destroy the socket manager. delete m_internal; } @@ -328,22 +228,10 @@ bool wxSocketBase::Close() { if (m_fd != INVALID_SOCKET) { - for (int i=0;i<3;i++) - { - wxNode *n, *node = req_list[i].First(); - - while (node) - { - SockRequest *req = (SockRequest *)node->Data(); - req->done = TRUE; - - n = node->Next(); - delete node; - node = n; - } - } + // Pause all running socket thread. + m_internal->PauseSocket(); - DestroyCallbacks(); + // Shutdown the connection. shutdown(m_fd, 2); close(m_fd); m_fd = INVALID_SOCKET; @@ -359,134 +247,43 @@ bool wxSocketBase::Close() wxSocketBase& wxSocketBase::Read(char* buffer, size_t nbytes) { - size_t count; - - count = GetPushback(buffer, nbytes, FALSE); - nbytes -= count; - buffer += count; + m_lcount = GetPushback(buffer, nbytes, FALSE); + nbytes -= m_lcount; + buffer += m_lcount; // If we have got the whole needed buffer or if we don't want to // wait then it returns immediately. - if (!nbytes || (count && !(m_flags & WAITALL)) ) { - m_lcount = count; + if (!nbytes || (m_lcount && !(m_flags & WAITALL)) ) { return *this; } - m_lcount = 0; WantBuffer(buffer, nbytes, EVT_READ); - m_lcount += count; return *this; } wxSocketBase& wxSocketBase::Peek(char* buffer, size_t nbytes) { - size_t count; - - count = GetPushback(buffer, nbytes, TRUE); - if (nbytes-count == 0) + m_lcount = GetPushback(buffer, nbytes, TRUE); + if (nbytes-m_lcount == 0) { - m_lcount = nbytes; return *this; } - buffer += count; - nbytes -= count; + buffer += m_lcount; + nbytes -= m_lcount; - m_lcount = 0; WantBuffer(buffer, nbytes, EVT_PEEK); - m_lcount += count; return *this; } wxSocketBase& wxSocketBase::Write(const char *buffer, size_t nbytes) { + m_lcount = 0; WantBuffer((char *)buffer, nbytes, EVT_WRITE); return *this; } -wxSocketBase& wxSocketBase::ReadMsg(char* buffer, size_t nbytes) -{ - SockMsg msg; - size_t len, len2, sig; - - Read((char *)&msg, sizeof(msg)); - if (m_lcount != sizeof(msg)) - return *this; - - sig = msg.sig[0] & 0xff; - sig |= (size_t)(msg.sig[1] & 0xff) << 8; - sig |= (size_t)(msg.sig[2] & 0xff) << 16; - sig |= (size_t)(msg.sig[3] & 0xff) << 24; - - if (sig != 0xfeeddead) - return *this; - len = msg.len[0] & 0xff; - len |= (size_t)(msg.len[1] & 0xff) << 8; - len |= (size_t)(msg.len[2] & 0xff) << 16; - len |= (size_t)(msg.len[3] & 0xff) << 24; - len2 = len; - if (len > nbytes) - len = nbytes; - else - len2 = 0; - - if (Read(buffer, len).LastCount() != len) - return *this; - if (len2 && (Read(NULL, len2).LastCount() != len2)) - return *this; - if (Read((char *)&msg, sizeof(msg)).LastCount() != sizeof(msg)) - return *this; - - sig = msg.sig[0] & 0xff; - sig |= (size_t)(msg.sig[1] & 0xff) << 8; - sig |= (size_t)(msg.sig[2] & 0xff) << 16; - sig |= (size_t)(msg.sig[3] & 0xff) << 24; -// ERROR - if (sig != 0xdeadfeed) - return *this; - - return *this; -} - -wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, size_t nbytes) -{ - SockMsg msg; - - // warning about 'cast truncates constant value' -#ifdef __VISUALC__ - #pragma warning(disable: 4310) -#endif // __VISUALC__ - - msg.sig[0] = (char) 0xad; - msg.sig[1] = (char) 0xde; - msg.sig[2] = (char) 0xed; - msg.sig[3] = (char) 0xfe; - - msg.len[0] = (char) nbytes & 0xff; - msg.len[1] = (char) (nbytes >> 8) & 0xff; - msg.len[2] = (char) (nbytes >> 16) & 0xff; - msg.len[3] = (char) (nbytes >> 24) & 0xff; - - if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg)) - return *this; - if (Write(buffer, nbytes).LastCount() < nbytes) - return *this; - - msg.sig[0] = (char) 0xed; - msg.sig[1] = (char) 0xfe; - msg.sig[2] = (char) 0xad; - msg.sig[3] = (char) 0xde; - msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0; - Write((char *)&msg, sizeof(msg)); - - return *this; - -#ifdef __VISUALC__ - #pragma warning(default: 4310) -#endif // __VISUALC__ -} - wxSocketBase& wxSocketBase::Unread(const char *buffer, size_t nbytes) { CreatePushbackAfter(buffer, nbytes); @@ -503,11 +300,16 @@ bool wxSocketBase::IsData() const if (m_unrd_size > 0) return TRUE; + m_internal->AcquireFD(); + tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&sock_set); FD_SET(m_fd, &sock_set); select(FD_SETSIZE, &sock_set, NULL, NULL, &tv); + + m_internal->ReleaseFD(); + return (FD_ISSET(m_fd, &sock_set) != 0); } @@ -534,14 +336,22 @@ void wxSocketBase::Discard() #undef MAX_BUFSIZE } -// this is normally defined by configure, but if it wasn't try to do it here -#ifndef SOCKLEN_T - #if wxHAVE_GLIBC2 - typedef socklen_t SOCKLEN_T; - #else - typedef int SOCKLEN_T; - #endif -#endif // SOCKLEN_T +// If what? Who seems to need unsigned int? +// BTW uint isn't even defined on wxMSW for VC++ for some reason. Even if it +// were, getpeername/getsockname don't take unsigned int*, they take int*. +// +// Under glibc 2.0.7, socketbits.h declares socklen_t to be unsigned int +// and it uses *socklen_t as the 3rd parameter. Robert. + +// JACS - How can we detect this? +// Meanwhile, if your compiler complains about socklen_t, +// switch lines below. + +#if wxHAVE_GLIBC2 +# define wxSOCKET_INT socklen_t +#else +# define wxSOCKET_INT int +#endif // -------------------------------------------------------------- // wxSocketBase socket info functions @@ -550,14 +360,19 @@ void wxSocketBase::Discard() bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const { struct sockaddr my_addr; - SOCKLEN_T len_addr = (SOCKLEN_T)sizeof(my_addr); + wxSOCKET_INT len_addr = sizeof(my_addr); if (m_fd < 0) return FALSE; - if (getpeername(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) + m_internal->AcquireFD(); + + if (getpeername(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) { + m_internal->ReleaseFD(); return FALSE; + } + m_internal->ReleaseFD(); addr_man.Disassemble(&my_addr, len_addr); return TRUE; } @@ -565,13 +380,18 @@ bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const { struct sockaddr my_addr; - SOCKLEN_T len_addr = (SOCKLEN_T)sizeof(my_addr); + wxSOCKET_INT len_addr = sizeof(my_addr); if (m_fd < 0) return FALSE; - if (getsockname(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) + m_internal->AcquireFD(); + + if (getsockname(m_fd, (struct sockaddr *)&my_addr, &len_addr) < 0) { + m_internal->ReleaseFD(); return FALSE; + } + m_internal->ReleaseFD(); addr_man.Disassemble(&my_addr, len_addr); return TRUE; @@ -583,232 +403,107 @@ bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const void wxSocketBase::SaveState() { - wxSockState *state = new wxSockState; + SocketState *state = new SocketState; - state->cbk_on = m_cbkon; - state->cbk_set= m_neededreq; - state->cbk = m_cbk; - state->cdata = m_cdata; - state->flags = m_flags; - state->notif = m_notifyme; + state->notify_state = m_notify_state; + state->evt_notify_state = m_neededreq; + state->socket_flags = m_flags; + state->c_callback = m_cbk; + state->c_callback_data = m_cdata; - m_states.Append(state); + m_states.Append((wxObject *)state); } void wxSocketBase::RestoreState() { wxNode *node; + SocketState *state; node = m_states.Last(); if (!node) return; - wxSockState *state = (wxSockState *)node->Data(); + state = (SocketState *)node->Data(); - SetFlags(state->flags); - m_neededreq = state->cbk_set; - m_cbk = state->cbk; - m_cdata = state->cdata; - m_notifyme = state->notif; - if (state->cbk_on) - SetupCallbacks(); - else - DestroyCallbacks(); + SetFlags(state->socket_flags); + m_neededreq = state->evt_notify_state; + m_cbk = state->c_callback; + m_cdata = state->c_callback_data; + Notify(state->notify_state); delete node; delete state; } // -------------------------------------------------------------- -// --------- wxSocketBase wait functions ------------------------ +// --------- wxSocketBase callback functions -------------------- // -------------------------------------------------------------- -bool wxSocketBase::_Wait(long seconds, long microseconds, int type) +wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_) { - if ((!m_connected && !m_connecting) || m_fd < 0) - return FALSE; - - wxSockWakeUp wakeup(this, &m_waitflags, 0); - - SaveState(); - SetNotify((wxRequestNotify)type); - SetupCallbacks(); - - if (seconds != -1) - wakeup.Start((int)(seconds*1000 + (microseconds / 1000)), TRUE); - - m_waitflags = 0x80 | type; - while (m_waitflags & 0x80) - PROCESS_EVENTS(); - - RestoreState(); - - if (m_waitflags & 0x40) - { - m_waitflags = 0; - return TRUE; - } - m_waitflags = 0; - - return FALSE; -} + wxSockCbk old_cbk = cbk_; -bool wxSocketBase::Wait(long seconds, long microseconds) -{ - return _Wait(seconds, microseconds, REQ_ACCEPT | REQ_CONNECT | - REQ_READ | REQ_WRITE | REQ_LOST); -} - -bool wxSocketBase::WaitForRead(long seconds, long microseconds) -{ - return _Wait(seconds, microseconds, REQ_READ | REQ_LOST); + m_cbk = cbk_; + return old_cbk; } -bool wxSocketBase::WaitForWrite(long seconds, long microseconds) +char *wxSocketBase::CallbackData(char *data) { - return _Wait(seconds, microseconds, REQ_WRITE); -} + char *old_data = m_cdata; -bool wxSocketBase::WaitForLost(long seconds, long microseconds) -{ - return _Wait(seconds, microseconds, REQ_LOST); + m_cdata = data; + return old_data; } // -------------------------------------------------------------- -// --------- wxSocketBase callback management ------------------- +// --------- wxSocketBase wait functions ------------------------ // -------------------------------------------------------------- -#ifdef __WXGTK__ -void wxPrereadSocket(wxSocketBase *sock) +bool wxSocketBase::_Wait(long seconds, long milliseconds, int type) { - char tmp_buf[1024]; - int got = 0; - - do { - got = recv(sock->m_fd, tmp_buf, 1024, 0); - if (got > 0) - sock->CreatePushbackAfter(tmp_buf, got); - } while (got > 0); -} -#endif + SockRequest *req; -#if defined(__WXMOTIF__) || defined(__WXXT__) || defined(__WXGTK__) -#if defined(__WXMOTIF__) || defined(__WXXT__) -static void wx_socket_read(XtPointer client, int *fid, - XtInputId *WXUNUSED(id)) -#define fd *fid -#else -static void wx_socket_read(gpointer client, gint fd, - GdkInputCondition WXUNUSED(cond)) -#define fd fd -#endif -{ - wxSocketBase *sock = (wxSocketBase *)client; - char c; - int i; - - i = recv(fd, &c, 1, MSG_PEEK); - - if (i == -1 && (sock->NeededReq() & wxSocketBase::REQ_ACCEPT)) - { - sock->OnRequest(wxSocketBase::EVT_ACCEPT); - return; - } + if ((!m_connected && !m_connecting) || m_fd < 0) + return FALSE; - if (i != 0) - { - if (!(sock->NeededReq() & wxSocketBase::REQ_READ)) - { -#ifdef __WXGTK__ - // We can't exit from the GDK main loop because it doesn't accept - // destroying input event while we are in a event dispatch. - // So we will preread socket and we put the data in the pushback. - wxPrereadSocket(sock); - // Then we set the socket as BLOCKING - int flag = 0; - ioctl(fd, FIONBIO, &flag); -#endif - return; - } + req = new SockRequest; - sock->OnRequest(wxSocketBase::EVT_READ); - } - else - { - if (!(sock->NeededReq() & wxSocketBase::REQ_LOST)) - { - sock->Close(); - return; - } + req->type = REQ_WAIT | type; + req->timeout = seconds * 1000 + milliseconds; + req->done = FALSE; + req->buffer = NULL; + req->size = 0; + req->error = 0; + req->wait = TRUE; + m_internal->QueueRequest(req, TRUE); - sock->OnRequest(wxSocketBase::EVT_LOST); - } + return (req->io_nbytes != 0); } -#undef fd -#if defined(__WXMOTIF__) || defined(__WXXT__) -static void wx_socket_write(XtPointer client, int *WXUNUSED(fid), - XtInputId *WXUNUSED(id)) -#else -static void wx_socket_write(gpointer client, gint WXUNUSED(fd), - GdkInputCondition WXUNUSED(cond)) -#endif +bool wxSocketBase::Wait(long seconds, long milliseconds) { - wxSocketBase *sock = (wxSocketBase *)client; - - if (!sock->IsConnected()) - sock->OnRequest(wxSocketBase::EVT_CONNECT); - else - sock->OnRequest(wxSocketBase::EVT_WRITE); + return _Wait(seconds, milliseconds, REQ_ACCEPT | REQ_CONNECT | + REQ_READ | REQ_WRITE | REQ_LOST); } -#endif -#ifdef wx_xview -Notify_value wx_sock_read_xview (Notify_client client, int fd) +bool wxSocketBase::WaitForRead(long seconds, long milliseconds) { - wxSocketBase *sock = (wxSocketBase *)client; - char c; - int i; - - i = recv(fd, &c, 1, MSG_PEEK); - - if (i == -1 && (sock->NeededReq() & wxSocketBase::REQ_ACCEPT)) - { - sock->OnRequest(wxSocketBase::EVT_ACCEPT); - return; - } - - /* Bytes arrived */ - if (i != 0) - { - if (!(sock->NeededReq() & wxSocketBase::REQ_READ)) - return (Notify_value) FALSE; - - sock->OnRequest(wxSocketBase::EVT_READ); - } - else - { - if (!(sock->NeededReq() & wxSocketBase::REQ_LOST)) - return; - - sock->OnRequest(wxSocketBase::EVT_LOST); - } - - return (Notify_value) FALSE; + return _Wait(seconds, milliseconds, REQ_READ | REQ_LOST); } -Notify_value wx_sock_write_xview (Notify_client client, int fd) +bool wxSocketBase::WaitForWrite(long seconds, long milliseconds) { - wxSocketBase *sock = (wxSocketBase *)client; - - if (!sock->IsConnected()) - sock->OnRequest(wxSocketBase::EVT_CONNECT); - else - sock->OnRequest(wxSocketBase::EVT_WRITE); + return _Wait(seconds, milliseconds, REQ_WRITE); +} - return (Notify_value) TRUE; +bool wxSocketBase::WaitForLost(long seconds, long milliseconds) +{ + return _Wait(seconds, milliseconds, REQ_LOST); } -#endif + +// -------------------------------------------------------------- +// --------- wxSocketBase callback management ------------------- +// -------------------------------------------------------------- wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt) { @@ -833,256 +528,54 @@ wxSocketBase::wxRequestNotify wxSocketBase::EventToNotify(wxRequestEvent evt) void wxSocketBase::SetFlags(wxSockFlags _flags) { m_flags = _flags; - if (_flags & SPEED) - { - unsigned long flag = 0; - ioctl(m_fd, FIONBIO, &flag); - + if (_flags & SPEED) { // SPEED and WAITALL are antagonists. m_flags = (wxSockFlags)(m_flags & ~WAITALL); - - Notify(FALSE); - } - else - { - unsigned long flag = 1; - ioctl(m_fd, FIONBIO, &flag); } } -void wxSocketBase::SetNotify(wxRequestNotify flags) +wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const { - wxRequestNotify old_needed_req = m_neededreq; - if (flags & REQ_ACCEPT) - { - /* Check if server */ - if (!(GetClassInfo()->IsKindOf(CLASSINFO(wxSocketServer)))) - flags &= ~REQ_ACCEPT; - } - m_neededreq = flags; - -/* - if (m_cbkon && old_needed_req != flags) seems to be wrong, Robert Roebling - SetupCallbacks(); -*/ - - if (old_needed_req != flags) - SetupCallbacks(); + return m_flags; } -void wxSocketBase::SetupCallbacks() +void wxSocketBase::SetNotify(wxRequestNotify flags) { - if (m_fd == INVALID_SOCKET || !m_handler || (m_flags & SPEED)) - return; + /* Check if server */ + if (m_type != SOCK_SERVER) + flags &= ~REQ_ACCEPT; -#if defined(__WXMOTIF__) || defined(__WXXT__) - if (m_neededreq & (REQ_ACCEPT | REQ_READ | REQ_LOST)) - { - if (m_internal->sock_inputid <= 0) - { - m_internal->sock_inputid = XtAppAddInput (wxAPP_CONTEXT, m_fd, - (XtPointer *) XtInputReadMask, - (XtInputCallbackProc) wx_socket_read, - (XtPointer) this); - } - } - else - { - if (m_internal->sock_inputid > 0) - { - XtRemoveInput(m_internal->sock_inputid); - m_internal->sock_inputid = 0; - } - } - - if (m_neededreq & (REQ_CONNECT | REQ_WRITE)) - { - if (m_internal->sock_outputid <= 0) - { - m_internal->sock_outputid = XtAppAddInput (wxAPP_CONTEXT, m_fd, - (XtPointer *) XtInputWriteMask, - (XtInputCallbackProc) wx_socket_write, - (XtPointer) this); - } - } - else - { - if (m_internal->sock_outputid > 0) - { - XtRemoveInput(m_internal->sock_outputid); - m_internal->sock_outputid = 0; - } - } -#endif - - -#ifdef __WXGTK__ - if (m_neededreq & (REQ_ACCEPT | REQ_READ | REQ_LOST)) - { - if (m_internal->sock_inputid <= 0) - { - m_internal->sock_inputid = gdk_input_add(m_fd, GDK_INPUT_READ, - wx_socket_read, (gpointer)this); - } - } - else - { - if (m_internal->sock_inputid > 0) - { -/* - gdk_input_remove(m_internal->sock_inputid); - m_internal->sock_inputid = 0; -*/ - } - } - - if (m_neededreq & (REQ_CONNECT | REQ_WRITE)) - { - if (m_internal->sock_outputid <= 0) - { - m_internal->sock_outputid = gdk_input_add(m_fd, GDK_INPUT_WRITE, - wx_socket_write, (gpointer)this); - } - } + m_neededreq = flags; + if (m_neededreq == 0) + m_internal->DisableWaiter(); else - { - if (m_internal->sock_outputid > 0) - { -/* - gdk_input_remove(m_internal->sock_outputid); - m_internal->sock_outputid = 0; -*/ - } - } -#endif - - -#ifdef __WXMSW__ - WORD mask = 0; - - if (m_neededreq & REQ_READ) - mask |= FD_READ; - if (m_neededreq & REQ_WRITE) - mask |= FD_WRITE; - if (m_neededreq & REQ_LOST) - mask |= FD_CLOSE; - if (m_neededreq & REQ_ACCEPT) - mask |= FD_ACCEPT; - if (m_neededreq & REQ_CONNECT) - mask |= FD_CONNECT; - - if (!m_internal->my_msg) - m_internal->my_msg = m_handler->NewMessage(this); - WSAAsyncSelect(m_fd, m_handler->GetHWND(), m_internal->my_msg, mask); -#endif -#ifdef __WXMAC__ - short mask = 0; - - if (m_neededreq & REQ_READ) - mask |= FD_READ; - if (m_neededreq & REQ_WRITE) - mask |= FD_WRITE; - if (m_neededreq & REQ_LOST) - mask |= FD_CLOSE; - if (m_neededreq & REQ_ACCEPT) - mask |= FD_ACCEPT; - if (m_neededreq & REQ_CONNECT) - mask |= FD_CONNECT; - - GUSISetReference( m_fd ,mask, this ) ; - unsigned long flag = 1; - ioctl(m_fd, FIONBIO, &flag); -#endif - m_cbkon = TRUE; - m_processing = FALSE; -} - -void wxSocketBase::DestroyCallbacks() -{ - if (!m_cbkon || !m_handler) - return; - - m_cbkon = FALSE; - m_processing = FALSE; -#if defined(__WXMOTIF__) || defined(__WXXT__) - if (m_internal->sock_inputid > 0) - XtRemoveInput(m_internal->sock_inputid); - m_internal->sock_inputid = 0; - if (m_internal->sock_outputid > 0) - XtRemoveInput(m_internal->sock_outputid); - m_internal->sock_outputid = 0; -#endif -#ifdef __WXGTK__ - if (m_internal->sock_inputid > 0) - gdk_input_remove(m_internal->sock_inputid); - m_internal->sock_inputid = 0; - if (m_internal->sock_outputid > 0) - gdk_input_remove(m_internal->sock_outputid); - m_internal->sock_outputid = 0; -#endif -#ifdef __WINDOWS__ - WSAAsyncSelect(m_fd, m_handler->GetHWND(), 0, 0); -#endif -#ifdef __WXMAC__ - GUSISetReference( m_fd , 0 , 0 ) ; - int bottom = wxMacNetEventsBottom ; - while ( wxMacNetEventsTop != bottom ) - { - // set all events that reference this socket to nil - if ( wxMacNetEventsReferences[bottom] == (void*) this ) - wxMacNetEventsReferences[bottom] = NULL ; - bottom++ ; - if ( bottom == kwxMacNetEventsMax ) - bottom = 0 ; - } - SetFlags( m_flags ) ; -#endif + Notify(m_notify_state); } void wxSocketBase::Notify(bool notify) { - if (m_notifyme == notify) - return; if (notify) - SetupCallbacks(); + m_internal->EnableWaiter(); else - DestroyCallbacks(); - m_notifyme = notify; + m_internal->DisableWaiter(); + m_notify_state = notify; } void wxSocketBase::OnRequest(wxRequestEvent req_evt) { - wxRequestNotify req_notif = EventToNotify(req_evt); - - // Mask the current event - SetNotify(m_neededreq & ~req_notif); - - if (req_evt <= EVT_WRITE && DoRequests(req_evt)) - return; + wxSocketEvent event(m_id); + wxRequestNotify notify = EventToNotify(req_evt); - if (m_waitflags & 0xF0) - { - // Wake up - if ((m_waitflags & 0x0F) == req_evt) - { - m_waitflags = 0x80; -#ifndef __WXGTK__ - DestroyCallbacks(); -#endif - } - return; - } + if ((m_neededreq & notify) == notify) { + event.m_socket = this; + event.m_skevt = req_evt; + ProcessEvent(event); + // TODOTODO + // OldOnNotify(req_evt); - if (req_evt == EVT_LOST) - { - m_connected = FALSE; - Close(); + // We disable the event reporting. + SetNotify(m_neededreq & ~notify); } - if (m_notifyme) - OldOnNotify(req_evt); - - // Unmask - SetNotify(m_neededreq | req_notif); } wxSocketEvent::wxSocketEvent(int id) @@ -1093,37 +586,23 @@ wxSocketEvent::wxSocketEvent(int id) SetEventType(type); } -void wxSocketBase::OldOnNotify(wxRequestEvent evt) +wxObject *wxSocketEvent::Clone() const { - wxSocketEvent event(m_id); + wxSocketEvent *event = (wxSocketEvent *)wxEvent::Clone(); - event.SetEventObject(this); - event.m_skevt = evt; - ProcessEvent(event); + event->m_skevt = m_skevt; + event->m_socket = m_socket; - if (m_cbk) - m_cbk(*this, evt, m_cdata); + return event; } -// -------------------------------------------------------------- -// --------- wxSocketBase functions [Callback, CallbackData] ---- -// -------------------------------------------------------------- - -wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSocketBase::wxSockCbk _cbk) +void wxSocketBase::OldOnNotify(wxRequestEvent evt) { - wxSockCbk old_cbk = m_cbk; - - m_cbk = _cbk; - return old_cbk; } -char *wxSocketBase::CallbackData(char *cdata_) -{ - char *old_cdata = m_cdata; - - m_cdata = cdata_; - return old_cdata; -} +// -------------------------------------------------------------- +// --------- wxSocketBase functions [Callback, CallbackData] ---- +// -------------------------------------------------------------- void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id) { @@ -1186,108 +665,9 @@ size_t wxSocketBase::GetPushback(char *buffer, size_t size, bool peek) } // -------------------------------------------------------------- -// --------- wxSocketBase "multi-thread" core ------------------- +// --------- wxSocketBase buffer core requester ----------------- // -------------------------------------------------------------- -bool wxSocketBase::DoRequests(wxRequestEvent req_flag) -{ - wxNode *node = req_list[req_flag].First(); - size_t len; - int ret; - - if (!node) - return FALSE; - - SockRequest *req = (SockRequest *)node->Data(); - - delete node; - - switch (req->type) - { - case EVT_READ: - case EVT_PEEK: - ret = recv(m_fd, req->buffer, req->size, - (req->type == EVT_PEEK) ? MSG_PEEK : 0); - if (ret < 0) - { - req->error = errno; - req->done = TRUE; - break; - } - len = ret; - if ((len < req->size) && (m_flags & WAITALL)) - { - req->size -= len; - req->nbytes += len; - req->buffer += len; - req->auto_wakeup->Start(m_timeout*1000, TRUE); - req_list[req_flag].Insert(req); - break; - } - req->done = TRUE; - req->nbytes += len; -#ifndef __WXGTK__ - DestroyCallbacks(); -#endif - break; - case EVT_WRITE: - ret = send(m_fd, req->buffer, req->size, 0); - if (ret < 0) - { - req->error = errno; - req->done = TRUE; - break; - } - len = ret; - if ((len < req->size) && (m_flags & WAITALL)) - { - req->size -= len; - req->nbytes += len; - req->buffer += len; - req->auto_wakeup->Start(m_timeout*1000, TRUE); - req_list[req_flag].Insert(req); - break; - } - req->done = TRUE; - req->nbytes += len; -#ifndef __WXGTK__ - DestroyCallbacks(); -#endif - break; - default: - return FALSE; - } - return TRUE; -} - -void wxSocketBase::WantSpeedBuffer(char *buffer, size_t nbytes, - wxRequestEvent evt) -{ - int ret = 0; - - switch (evt) - { - case EVT_PEEK: - case EVT_READ: - ret = recv(m_fd, buffer, nbytes, - (evt == EVT_PEEK) ? MSG_PEEK : 0); - break; - case EVT_WRITE: - ret = send(m_fd, buffer, nbytes, 0); - break; - } - if (ret < 0) - { - m_lcount = 0; - m_error = errno; - } - else - { - m_lcount = ret; - m_error = 0; - } -} - void wxSocketBase::WantBuffer(char *buffer, size_t nbytes, wxRequestEvent evt) { @@ -1296,42 +676,28 @@ void wxSocketBase::WantBuffer(char *buffer, size_t nbytes, if (m_fd == INVALID_SOCKET || !m_handler || !m_connected) return; - if (m_flags & SPEED) - { - WantSpeedBuffer(buffer, nbytes, evt); - return; - } - SockRequest *buf = new SockRequest; - wxSockWakeUp s_wake(NULL, (int *)&buf_timed_out, (int)TRUE); - - m_wantbuf++; - req_list[evt].Append(buf); SaveState(); - SetNotify(REQ_LOST | EventToNotify(evt)); - SetupCallbacks(); + m_internal->DisableWaiter(); buf->buffer = buffer; buf->size = nbytes; buf->done = FALSE; - buf->type = evt; - buf->nbytes = 0; - buf->auto_wakeup = &s_wake; + buf->type = EventToNotify(evt); + buf->io_nbytes = 0; buf->error = 0; + buf->wait = TRUE; + buf->timeout = 1000; buf_timed_out = FALSE; - s_wake.Start(m_timeout*1000, TRUE); - if (m_flags & NOWAIT) - { - DoRequests(evt); - } - else - { - while (!buf->done && !buf_timed_out) - PROCESS_EVENTS(); - } - m_wantbuf--; - m_lcount = buf->nbytes; + if (m_flags & SPEED) + m_internal->QueueRequest(buf, FALSE); + else + if (m_flags & NOWAIT) + m_internal->QueueRequest(buf, TRUE); + else + m_internal->QueueRequest(buf, TRUE); + m_lcount += buf->io_nbytes; if (buf_timed_out) m_error = ETIMEDOUT; else @@ -1368,6 +734,8 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man, m_fd = INVALID_SOCKET; return; } + + m_internal->InitializeSocket(); } // -------------------------------------------------------------- @@ -1390,16 +758,12 @@ bool wxSocketServer::AcceptWith(wxSocketBase& sock) int flag = 0; setsockopt(fd2, SOL_SOCKET, SO_KEEPALIVE, (char*)&flag, sizeof(int)); - if (!(sock.m_flags & SPEED)) - { - unsigned long flag2 = 1; - ioctl(fd2, FIONBIO, &flag2); - } - sock.m_type = SOCK_INTERNAL; sock.m_fd = fd2; sock.m_connected = TRUE; + sock.m_internal->InitializeSocket(); + return TRUE; } @@ -1418,18 +782,6 @@ wxSocketBase *wxSocketServer::Accept() return sock; } -// -------------------------------------------------------------- -// wxSocketServer callbacks -// -------------------------------------------------------------- - -void wxSocketServer::OnRequest(wxRequestEvent evt) -{ - if (evt == EVT_ACCEPT) - { - OldOnNotify(EVT_ACCEPT); - } -} - // -------------------------------------------------------------- // wxSocketClient // -------------------------------------------------------------- @@ -1458,6 +810,8 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) ) if (IsConnected()) Close(); + // Initializes all socket stuff ... + // -------------------------------- m_fd = socket(addr_man.GetFamily(), SOCK_STREAM, 0); if (m_fd < 0) @@ -1490,12 +844,12 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool WXUNUSED(wait) ) if (connect(m_fd, remote, len) != 0) return FALSE; - if (!(m_flags & SPEED)) - { - flag = 1; - ioctl(m_fd, FIONBIO, &flag); - } + // Initializes the background threads ... + // -------------------------------------- + m_internal->InitializeSocket(); + // Enables bg events. + // ------------------ Notify(TRUE); m_connected = TRUE; @@ -1518,17 +872,11 @@ void wxSocketClient::OnRequest(wxRequestEvent evt) { if (m_connected) { -#ifndef __WXGTK__ SetNotify(m_neededreq & ~REQ_CONNECT); -#endif return; } - m_waitflags = 0x40; m_connected = TRUE; OldOnNotify(EVT_CONNECT); -#ifndef __WXGTK__ - DestroyCallbacks(); -#endif return; } wxSocketBase::OnRequest(evt); @@ -1546,118 +894,6 @@ static int win_initialized = 0; // -------------------------------------------------------------- // --------- wxSocketHandler CONSTRUCTOR ------------------------ // -------------------------------------------------------------- -#ifdef __WXMAC__ - -extern "C" int updatestatus(int s) ; - -void wxMacSocketOnRequestProc( void *refcon , short event ) -{ - if ( refcon ) - { - wxSocketBase *sock = (wxSocketBase *) refcon ; - - wxSocketBase::wxRequestEvent sk_req; - - int canRead ; - int canWrite ; - int exception ; - - switch (event) { - case FD_READ: - sk_req = wxSocketBase::EVT_READ; - sock->OnRequest(sk_req); - break; - case FD_WRITE: - sk_req = wxSocketBase::EVT_WRITE; - sock->OnRequest(sk_req); - break; - case FD_CLOSE: - sk_req = wxSocketBase::EVT_LOST; - sock->OnRequest(sk_req); - break; - case FD_ACCEPT: - sk_req = wxSocketBase::EVT_ACCEPT; - sock->OnRequest(sk_req); - break; - case FD_CONNECT: - sk_req = wxSocketBase::EVT_CONNECT; - sock->OnRequest(sk_req); - break; - case FD_READY : - break ; - } - updatestatus ( sock->m_fd ) ; - } -} - -void wxMacSocketHandlerProc( void *refcon , short event ) -{ - wxMacNetEventsReferences[wxMacNetEventsTop] = refcon ; - wxMacNetEventsEvents[wxMacNetEventsTop] = event ; - - // clumsy construct in order to never have a incorrect wxMacNetEventsTop (above limits) - - if ( wxMacNetEventsTop + 1 == kwxMacNetEventsMax ) - wxMacNetEventsTop = 0 ; - else - wxMacNetEventsTop++ ; -} - -#endif -#ifdef __WINDOWS__ - -extern wxChar wxPanelClassName[]; - -LRESULT APIENTRY _EXPORT wxSocketHandlerWndProc(HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam) -{ - if(message==WM_DESTROY) - { - ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG) DefWindowProc); - return DefWindowProc(hWnd, message, wParam, lParam); - } - wxSocketHandler *h_sock = (wxSocketHandler *)GetWindowLong(hWnd, GWL_USERDATA); - wxNode *node = h_sock->smsg_list->Find(message); - wxSocketBase *sock; - wxSocketBase::wxRequestEvent sk_req; - UINT event = WSAGETSELECTEVENT(lParam); - - if (!node) - return DefWindowProc(hWnd, message, wParam, lParam); - - sock = (wxSocketBase *)node->Data(); - - switch (event) { - case FD_READ: - sk_req = wxSocketBase::EVT_READ; - break; - case FD_WRITE: - sk_req = wxSocketBase::EVT_WRITE; - break; - case FD_CLOSE: - sk_req = wxSocketBase::EVT_LOST; - break; - case FD_ACCEPT: - sk_req = wxSocketBase::EVT_ACCEPT; - break; - case FD_CONNECT: - sk_req = wxSocketBase::EVT_CONNECT; - break; - - default: - wxFAIL_MSG(_T("invalid socket event")); - return (LRESULT)0; - } - - sock->OnRequest(sk_req); - - return (LRESULT)0; -} - -FARPROC wxSocketSubClassProc = NULL; - -#endif - wxSocketHandler::wxSocketHandler() { #if defined(__WINDOWS__) @@ -1668,19 +904,6 @@ wxSocketHandler::wxSocketHandler() WSAStartup((1 << 8) | 1, &wsaData); win_initialized = 1; } - internal = new wxSockHandlerInternal; - internal->sockWin = ::CreateWindow(wxPanelClassName, NULL, 0, - 0, 0, 0, 0, NULL, (HMENU) NULL, - wxhInstance, 0); - - // Subclass the window - if (!wxSocketSubClassProc) - wxSocketSubClassProc = MakeProcInstance((FARPROC) wxSocketHandlerWndProc, wxhInstance); - ::SetWindowLong(internal->sockWin, GWL_WNDPROC, (LONG) wxSocketSubClassProc); - ::SetWindowLong(internal->sockWin, GWL_USERDATA, (LONG) this); - - internal->firstAvailableMsg = 5000; - smsg_list = new wxList(wxKEY_INTEGER); #endif socks = new wxList; @@ -1710,13 +933,8 @@ wxSocketHandler::~wxSocketHandler() delete socks; #ifdef __WINDOWS__ - delete smsg_list; - - ::DestroyWindow(internal->sockWin); WSACleanup(); win_initialized = 0; - - delete internal; #endif } @@ -1740,7 +958,6 @@ void wxSocketHandler::Register(wxSocketBase* sock) { socks->Append(sock); sock->SetHandler(this); - sock->SetupCallbacks(); } } @@ -1755,7 +972,6 @@ void wxSocketHandler::UnRegister(wxSocketBase* sock) if (s == sock) { delete node; - sock->DestroyCallbacks(); sock->SetHandler(NULL); return; } @@ -1770,23 +986,15 @@ unsigned long wxSocketHandler::Count() const // -------------------------------------------------------------- // --------- wxSocketHandler "big" wait functions --------------- // -------------------------------------------------------------- -void handler_cbk(wxSocketBase& sock, - wxSocketBase::wxRequestEvent WXUNUSED(flags), - char *cdata) -{ - int *a_wait = (int *)cdata; - - (*a_wait)++; - sock.Notify(FALSE); -} int wxSocketHandler::Wait(long seconds, long microseconds) { + // TODO Needs the completely asynchronous notifier. + + /* int i; int on_wait; - wxSockWakeUp s_wake(NULL, &on_wait, -2); wxNode *node; - for (node = socks->First(), i=0; node; node = node->Next(), i++) { wxSocketBase *sock = (wxSocketBase *)node->Data(); @@ -1816,24 +1024,19 @@ int wxSocketHandler::Wait(long seconds, long microseconds) return 0; return on_wait; + */ + return 0; } void wxSocketHandler::YieldSock() { wxNode *node; - for (node = socks->First(); node; node = node->Next() ) - { + // Nothing to do anymore here except waiting for the queue emptying. + for (node = socks->First(); node; node=node->Next()) { wxSocketBase *sock = (wxSocketBase *)node->Data(); - sock->SaveState(); - - sock->SetFlags(wxSocketBase::SPEED); - if (sock->IsData()) - sock->DoRequests(wxSocketBase::EVT_READ); - sock->DoRequests(wxSocketBase::EVT_WRITE); - - sock->RestoreState(); + sock->m_internal->WaitForEnd(NULL); } } @@ -1894,27 +1097,6 @@ void wxSocketModule::OnExit() wxSocketHandler::master = NULL; } -#ifdef __WXMAC__ -void wxMacProcessSocketEvents() ; -void wxMacProcessEvents() -{ - wxMacProcessSocketEvents() ; - (*GUSISpin)(SP_MISC, 0) ; -} - -void wxMacProcessSocketEvents() -{ - while ( wxMacNetEventsTop != wxMacNetEventsBottom ) - { - // consume event at wxMacNetEventsBottom - wxMacSocketOnRequestProc(wxMacNetEventsReferences[wxMacNetEventsBottom] , wxMacNetEventsEvents[wxMacNetEventsBottom] ) ; - wxMacNetEventsBottom++ ; - if ( wxMacNetEventsBottom == kwxMacNetEventsMax ) - wxMacNetEventsBottom = 0 ; - } -} -#endif - #endif // __WXSTUBS__ diff --git a/src/gtk.inc b/src/gtk.inc index 7ea985ba23..070e9c59fb 100644 --- a/src/gtk.inc +++ b/src/gtk.inc @@ -63,6 +63,7 @@ LIB_CPP_SRC=\ common/valtext.cpp \ common/variant.cpp \ common/socket.cpp \ + common/sckint.cpp \ common/sckaddr.cpp \ common/sckipc.cpp \ common/protocol.cpp \ diff --git a/src/mac/app.cpp b/src/mac/app.cpp index b0f8b07a30..3061f99aea 100644 --- a/src/mac/app.cpp +++ b/src/mac/app.cpp @@ -1402,4 +1402,4 @@ wxApp::macAdjustCursor() } } } -*/ \ No newline at end of file +*/ diff --git a/src/mac/carbon/app.cpp b/src/mac/carbon/app.cpp index b0f8b07a30..3061f99aea 100644 --- a/src/mac/carbon/app.cpp +++ b/src/mac/carbon/app.cpp @@ -1402,4 +1402,4 @@ wxApp::macAdjustCursor() } } } -*/ \ No newline at end of file +*/ diff --git a/src/mac/carbon/makefile.unx b/src/mac/carbon/makefile.unx index 5bd62163fd..d5d55d86d4 100644 --- a/src/mac/carbon/makefile.unx +++ b/src/mac/carbon/makefile.unx @@ -62,6 +62,7 @@ LIB_CPP_SRC=\ ../common/variant.cpp \ ../common/wxexpr.cpp \ ../common/socket.cpp \ + ../common/sckint.cpp \ ../common/sckaddr.cpp \ ../common/sckipc.cpp \ ../common/protocol.cpp \ diff --git a/src/mac/makefile.unx b/src/mac/makefile.unx index 5bd62163fd..d5d55d86d4 100644 --- a/src/mac/makefile.unx +++ b/src/mac/makefile.unx @@ -62,6 +62,7 @@ LIB_CPP_SRC=\ ../common/variant.cpp \ ../common/wxexpr.cpp \ ../common/socket.cpp \ + ../common/sckint.cpp \ ../common/sckaddr.cpp \ ../common/sckipc.cpp \ ../common/protocol.cpp \ diff --git a/src/msw/makefile.b32 b/src/msw/makefile.b32 index 780261308d..4173b443af 100644 --- a/src/msw/makefile.b32 +++ b/src/msw/makefile.b32 @@ -151,6 +151,7 @@ COMMONOBJS = \ $(MSWDIR)\dynlib.obj \ $(MSWDIR)\tokenzr.obj \ $(MSWDIR)\socket.obj \ + $(MSWDIR)\sckint.obj \ $(MSWDIR)\sckaddr.obj \ $(MSWDIR)\protocol.obj \ $(MSWDIR)\url.obj \ diff --git a/src/msw/makefile.sl b/src/msw/makefile.sl index bf981e4c43..a5179c1045 100644 --- a/src/msw/makefile.sl +++ b/src/msw/makefile.sl @@ -77,6 +77,7 @@ COMMONOBJS = cmndata.obj \ paper.obj \ string.obj \ socket.obj \ + sckint.obj \ sckaddr.obj \ sckfile.obj \ sckipc.obj \ @@ -628,6 +629,9 @@ string.obj: $(COMMDIR)\string.cpp socket.obj: $(COMMDIR)\socket.cpp $(CCC) $(CPPFLAGS) $(IFLAGS) $(COMMDIR)\socket.cpp /BINARY socket.obj +sckint.obj: $(COMMDIR)\sckint.cpp + $(CCC) $(CPPFLAGS) $(IFLAGS) $(COMMDIR)\sckint.cpp /BINARY sckint.obj + sckaddr.obj: $(COMMDIR)\sckaddr.cpp $(CCC) $(CPPFLAGS) $(IFLAGS) $(COMMDIR)\sckaddr.cpp /BINARY sckaddr.obj diff --git a/src/msw/makefile.vc b/src/msw/makefile.vc index 12bd65834d..e80cec04b3 100644 --- a/src/msw/makefile.vc +++ b/src/msw/makefile.vc @@ -141,6 +141,7 @@ COMMONOBJS = \ ..\common\$D\paper.obj \ ..\common\$D\string.obj \ ..\common\$D\socket.obj \ + ..\common\$D\socket.obj \ ..\common\$D\sckaddr.obj \ ..\common\$D\sckfile.obj \ ..\common\$D\sckipc.obj \ diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index c3703a0456..58d44efaf7 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -664,6 +664,13 @@ bool wxThread::IsAlive() const (p_internal->GetState() == STATE_PAUSED); } +bool wxThread::IsPaused() const +{ + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return (p_internal->GetState() == STATE_PAUSED); +} + bool wxThread::TestDestroy() { wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index 2c8fb6851d..ddb603d172 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -325,7 +325,8 @@ wxThreadInternal::wxThreadInternal() wxThreadInternal::~wxThreadInternal() { - m_mutexSuspend.Unlock(); + // GL: moved to SignalExit + // m_mutexSuspend.Unlock(); // note that m_mutex will be unlocked by the thread which waits for our // termination @@ -375,6 +376,9 @@ void wxThreadInternal::Wait() void wxThreadInternal::SignalExit() { + // GL: Unlock mutexSuspend here. + m_mutexSuspend.Unlock(); + // as mutex is currently locked, this will block until some other thread // (normally the same which created this one) unlocks it by entering Wait() m_mutex.Lock(); @@ -453,9 +457,7 @@ wxThread::wxThread() wxThreadError wxThread::Create() { - // Maybe we could think about recreate the thread once it has exited. - if (p_internal->GetState() != STATE_NEW && - p_internal->GetState() != STATE_EXITED) + if (p_internal->GetState() != STATE_NEW) return wxTHREAD_RUNNING; // set up the thread attribute: right now, we only set thread priority @@ -590,7 +592,9 @@ wxThreadError wxThread::Resume() if ( p_internal->GetState() == STATE_PAUSED ) { + m_critsect.Leave(); p_internal->Resume(); + m_critsect.Enter(); return wxTHREAD_NO_ERROR; } @@ -727,6 +731,13 @@ bool wxThread::IsAlive() const } } +bool wxThread::IsPaused() const +{ + wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect); + + return (p_internal->GetState() == STATE_PAUSED); +} + //-------------------------------------------------------------------- // wxThreadModule //-------------------------------------------------------------------- -- 2.45.2