our sockets are always non-blocking anyhow so throw away all the code dealing with checking if they're blocking; also merge Unix/Win32 versions of connect() and accept() handling as they were almost identical except for the different checking of the return value which was factored out into a platform-specific GetLastError() function
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57600 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -37,14 +37,12 @@ public:
|
|||||||
|
|
||||||
virtual ~wxSocketImplMSW();
|
virtual ~wxSocketImplMSW();
|
||||||
|
|
||||||
virtual wxSocketImpl *WaitConnection(wxSocketBase& wxsocket);
|
virtual wxSocketError GetLastError() const;
|
||||||
|
|
||||||
|
virtual int Read(void *buffer, int size);
|
||||||
int Read(void *buffer, int size);
|
virtual int Write(const void *buffer, int size);
|
||||||
int Write(const void *buffer, int size);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual wxSocketError DoHandleConnect(int ret);
|
|
||||||
virtual void DoClose();
|
virtual void DoClose();
|
||||||
|
|
||||||
virtual void UnblockAndRegisterWithEventLoop()
|
virtual void UnblockAndRegisterWithEventLoop()
|
||||||
|
@@ -191,7 +191,6 @@ public:
|
|||||||
// set various socket properties: all of those can only be called before
|
// set various socket properties: all of those can only be called before
|
||||||
// creating the socket
|
// creating the socket
|
||||||
void SetTimeout(unsigned long millisec);
|
void SetTimeout(unsigned long millisec);
|
||||||
void SetNonBlocking(bool non_blocking) { m_non_blocking = non_blocking; }
|
|
||||||
void SetReusable() { m_reusable = true; }
|
void SetReusable() { m_reusable = true; }
|
||||||
void SetBroadcast() { m_broadcast = true; }
|
void SetBroadcast() { m_broadcast = true; }
|
||||||
void DontDoBind() { m_dobind = false; }
|
void DontDoBind() { m_dobind = false; }
|
||||||
@@ -207,12 +206,17 @@ public:
|
|||||||
// accessors
|
// accessors
|
||||||
// ---------
|
// ---------
|
||||||
|
|
||||||
|
bool IsServer() const { return m_server; }
|
||||||
|
|
||||||
GAddress *GetLocal();
|
GAddress *GetLocal();
|
||||||
GAddress *GetPeer();
|
GAddress *GetPeer();
|
||||||
|
|
||||||
wxSocketError GetError() const { return m_error; }
|
wxSocketError GetError() const { return m_error; }
|
||||||
bool IsOk() const { return m_error == wxSOCKET_NOERROR; }
|
bool IsOk() const { return m_error == wxSOCKET_NOERROR; }
|
||||||
|
|
||||||
|
// get the error code corresponding to the last operation
|
||||||
|
virtual wxSocketError GetLastError() const = 0;
|
||||||
|
|
||||||
|
|
||||||
// creating/closing the socket
|
// creating/closing the socket
|
||||||
// --------------------------
|
// --------------------------
|
||||||
@@ -235,8 +239,8 @@ public:
|
|||||||
// (notice that DontDoBind() is ignored by this function)
|
// (notice that DontDoBind() is ignored by this function)
|
||||||
//
|
//
|
||||||
// this function may return wxSOCKET_WOULDBLOCK in addition to the return
|
// this function may return wxSOCKET_WOULDBLOCK in addition to the return
|
||||||
// values listed above
|
// values listed above if wait is false
|
||||||
wxSocketError CreateClient();
|
wxSocketError CreateClient(bool wait);
|
||||||
|
|
||||||
// create (and bind unless DontDoBind() had been called) an UDP socket
|
// create (and bind unless DontDoBind() had been called) an UDP socket
|
||||||
// associated with the given local address
|
// associated with the given local address
|
||||||
@@ -256,15 +260,25 @@ public:
|
|||||||
virtual int Write(const void *buffer, int size) = 0;
|
virtual int Write(const void *buffer, int size) = 0;
|
||||||
|
|
||||||
// basically a wrapper for select(): returns the condition of the socket,
|
// basically a wrapper for select(): returns the condition of the socket,
|
||||||
// blocking for not longer than timeout ms for something to become
|
// blocking for not longer than timeout if it is specified (otherwise just
|
||||||
// available
|
// poll without blocking at all)
|
||||||
//
|
//
|
||||||
// flags defines what kind of conditions we're interested in, the return
|
// flags defines what kind of conditions we're interested in, the return
|
||||||
// value is composed of a (possibly empty) subset of the bits set in flags
|
// value is composed of a (possibly empty) subset of the bits set in flags
|
||||||
wxSocketEventFlags Select(wxSocketEventFlags flags,
|
wxSocketEventFlags Select(wxSocketEventFlags flags,
|
||||||
unsigned long timeout = 0);
|
const timeval *timeout = NULL);
|
||||||
|
|
||||||
virtual wxSocketImpl *WaitConnection(wxSocketBase& wxsocket) = 0;
|
// convenient wrapper calling Select() with our default timeout
|
||||||
|
wxSocketEventFlags SelectWithTimeout(wxSocketEventFlags flags)
|
||||||
|
{
|
||||||
|
return Select(flags, &m_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// just a wrapper for accept(): it is called to create a new wxSocketImpl
|
||||||
|
// corresponding to a new server connection represented by the given
|
||||||
|
// wxSocketBase, returns NULL on error (including immediately if there are
|
||||||
|
// no pending connections as our sockets are non-blocking)
|
||||||
|
wxSocketImpl *Accept(wxSocketBase& wxsocket);
|
||||||
|
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
@@ -286,8 +300,6 @@ public:
|
|||||||
GAddress *m_peer;
|
GAddress *m_peer;
|
||||||
wxSocketError m_error;
|
wxSocketError m_error;
|
||||||
|
|
||||||
bool m_non_blocking;
|
|
||||||
bool m_server;
|
|
||||||
bool m_stream;
|
bool m_stream;
|
||||||
bool m_establishing;
|
bool m_establishing;
|
||||||
bool m_reusable;
|
bool m_reusable;
|
||||||
@@ -301,20 +313,10 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
wxSocketImpl(wxSocketBase& wxsocket);
|
wxSocketImpl(wxSocketBase& wxsocket);
|
||||||
|
|
||||||
// wait until input/output becomes available or m_timeout expires
|
// true if we're a listening stream socket
|
||||||
//
|
bool m_server;
|
||||||
// returns true if we do have input/output or false on timeout or error
|
|
||||||
// (also sets m_error accordingly)
|
|
||||||
bool BlockForInputWithTimeout()
|
|
||||||
{ return DoBlockWithTimeout(wxSOCKET_INPUT_FLAG); }
|
|
||||||
bool BlockForOutputWithTimeout()
|
|
||||||
{ return DoBlockWithTimeout(wxSOCKET_OUTPUT_FLAG); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// handle the given connect() return value (which may be 0 or EWOULDBLOCK
|
|
||||||
// or something else)
|
|
||||||
virtual wxSocketError DoHandleConnect(int ret) = 0;
|
|
||||||
|
|
||||||
// called by Close() if we have a valid m_fd
|
// called by Close() if we have a valid m_fd
|
||||||
virtual void DoClose() = 0;
|
virtual void DoClose() = 0;
|
||||||
|
|
||||||
@@ -351,12 +353,6 @@ private:
|
|||||||
// update local address after binding/connecting
|
// update local address after binding/connecting
|
||||||
wxSocketError UpdateLocalAddress();
|
wxSocketError UpdateLocalAddress();
|
||||||
|
|
||||||
// wait for IO on the socket or until timeout expires
|
|
||||||
//
|
|
||||||
// the parameter can be one of wxSOCKET_INPUT/OUTPUT_FLAG (but could be
|
|
||||||
// their combination in the future, hence we take wxSocketEventFlags)
|
|
||||||
bool DoBlockWithTimeout(wxSocketEventFlags flags);
|
|
||||||
|
|
||||||
|
|
||||||
// set in ctor and never changed except that it's reset to NULL when the
|
// set in ctor and never changed except that it's reset to NULL when the
|
||||||
// socket is shut down
|
// socket is shut down
|
||||||
|
@@ -29,11 +29,12 @@ public:
|
|||||||
m_enabledCallbacks = 0;
|
m_enabledCallbacks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Shutdown();
|
virtual wxSocketError GetLastError() const;
|
||||||
virtual wxSocketImpl *WaitConnection(wxSocketBase& wxsocket);
|
|
||||||
|
|
||||||
int Read(void *buffer, int size);
|
virtual void Shutdown();
|
||||||
int Write(const void *buffer, int size);
|
|
||||||
|
virtual int Read(void *buffer, int size);
|
||||||
|
virtual int Write(const void *buffer, int size);
|
||||||
|
|
||||||
// wxFDIOHandler methods
|
// wxFDIOHandler methods
|
||||||
virtual void OnReadWaiting();
|
virtual void OnReadWaiting();
|
||||||
@@ -49,7 +50,6 @@ public:
|
|||||||
int GetEnabledCallbacks() const { return m_enabledCallbacks; }
|
int GetEnabledCallbacks() const { return m_enabledCallbacks; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual wxSocketError DoHandleConnect(int ret);
|
|
||||||
virtual void DoClose()
|
virtual void DoClose()
|
||||||
{
|
{
|
||||||
wxSocketManager * const manager = wxSocketManager::Get();
|
wxSocketManager * const manager = wxSocketManager::Get();
|
||||||
@@ -151,7 +151,7 @@ protected:
|
|||||||
|
|
||||||
case wxSOCKET_CONNECTION:
|
case wxSOCKET_CONNECTION:
|
||||||
// FIXME: explain this?
|
// FIXME: explain this?
|
||||||
return socket->m_server ? FD_INPUT : FD_OUTPUT;
|
return socket->IsServer() ? FD_INPUT : FD_OUTPUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -102,31 +102,6 @@ public:
|
|||||||
DECLARE_NO_COPY_CLASS(wxSocketState)
|
DECLARE_NO_COPY_CLASS(wxSocketState)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Conditionally make the socket non-blocking for the lifetime of this object.
|
|
||||||
class wxSocketUnblocker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
wxSocketUnblocker(wxSocketImpl *socket, bool unblock = true)
|
|
||||||
: m_impl(socket),
|
|
||||||
m_unblock(unblock)
|
|
||||||
{
|
|
||||||
if ( m_unblock )
|
|
||||||
m_impl->SetNonBlocking(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
~wxSocketUnblocker()
|
|
||||||
{
|
|
||||||
if ( m_unblock )
|
|
||||||
m_impl->SetNonBlocking(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
wxSocketImpl * const m_impl;
|
|
||||||
bool m_unblock;
|
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(wxSocketUnblocker)
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxSocketManager
|
// wxSocketManager
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -185,7 +160,6 @@ wxSocketImpl::wxSocketImpl(wxSocketBase& wxsocket)
|
|||||||
m_error = wxSOCKET_NOERROR;
|
m_error = wxSOCKET_NOERROR;
|
||||||
m_server = false;
|
m_server = false;
|
||||||
m_stream = true;
|
m_stream = true;
|
||||||
m_non_blocking = false;
|
|
||||||
|
|
||||||
SetTimeout(wxsocket.GetTimeout() * 1000);
|
SetTimeout(wxsocket.GetTimeout() * 1000);
|
||||||
|
|
||||||
@@ -248,8 +222,8 @@ void wxSocketImpl::PostCreation()
|
|||||||
if ( m_initialSendBufferSize >= 0 )
|
if ( m_initialSendBufferSize >= 0 )
|
||||||
SetSocketOption(SO_SNDBUF, m_initialSendBufferSize);
|
SetSocketOption(SO_SNDBUF, m_initialSendBufferSize);
|
||||||
|
|
||||||
// FIXME: shouldn't we check for m_non_blocking here? as it is now, all our
|
// we always put our sockets in unblocked mode and handle blocking
|
||||||
// sockets are non-blocking
|
// ourselves in DoRead/Write() if wxSOCKET_WAITALL is specified
|
||||||
UnblockAndRegisterWithEventLoop();
|
UnblockAndRegisterWithEventLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +283,7 @@ wxSocketError wxSocketImpl::CreateServer()
|
|||||||
return UpdateLocalAddress();
|
return UpdateLocalAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSocketError wxSocketImpl::CreateClient()
|
wxSocketError wxSocketImpl::CreateClient(bool wait)
|
||||||
{
|
{
|
||||||
if ( !PreCreateCheck(m_peer) )
|
if ( !PreCreateCheck(m_peer) )
|
||||||
return m_error;
|
return m_error;
|
||||||
@@ -318,8 +292,8 @@ wxSocketError wxSocketImpl::CreateClient()
|
|||||||
|
|
||||||
if ( m_fd == INVALID_SOCKET )
|
if ( m_fd == INVALID_SOCKET )
|
||||||
{
|
{
|
||||||
m_error = wxSOCKET_IOERR;
|
m_error = wxSOCKET_IOERR;
|
||||||
return wxSOCKET_IOERR;
|
return wxSOCKET_IOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
PostCreation();
|
PostCreation();
|
||||||
@@ -335,9 +309,34 @@ wxSocketError wxSocketImpl::CreateClient()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the peer and handle the EWOULDBLOCK return value in
|
// Do connect now
|
||||||
// platform-specific code
|
int rc = connect(m_fd, m_peer->m_addr, m_peer->m_len);
|
||||||
return DoHandleConnect(connect(m_fd, m_peer->m_addr, m_peer->m_len));
|
if ( rc == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
wxSocketError err = GetLastError();
|
||||||
|
if ( err == wxSOCKET_WOULDBLOCK )
|
||||||
|
{
|
||||||
|
m_establishing = true;
|
||||||
|
|
||||||
|
// block waiting for connection if we should (otherwise just return
|
||||||
|
// wxSOCKET_WOULDBLOCK to the caller)
|
||||||
|
if ( wait )
|
||||||
|
{
|
||||||
|
err = SelectWithTimeout(wxSOCKET_CONNECTION_FLAG)
|
||||||
|
? wxSOCKET_NOERROR
|
||||||
|
: wxSOCKET_TIMEDOUT;
|
||||||
|
m_establishing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_error = err;
|
||||||
|
}
|
||||||
|
else // connected
|
||||||
|
{
|
||||||
|
m_error = wxSOCKET_NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -374,6 +373,26 @@ wxSocketError wxSocketImpl::CreateUDP()
|
|||||||
return wxSOCKET_NOERROR;
|
return wxSOCKET_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxSocketImpl *wxSocketImpl::Accept(wxSocketBase& wxsocket)
|
||||||
|
{
|
||||||
|
wxSockAddr from;
|
||||||
|
WX_SOCKLEN_T fromlen = sizeof(from);
|
||||||
|
const int fd = accept(m_fd, &from, &fromlen);
|
||||||
|
|
||||||
|
if ( fd == INVALID_SOCKET )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wxSocketImpl * const sock = Create(wxsocket);
|
||||||
|
sock->m_fd = fd;
|
||||||
|
|
||||||
|
sock->m_peer = GAddress_new();
|
||||||
|
_GAddress_translate_from(sock->m_peer, &from, fromlen);
|
||||||
|
|
||||||
|
sock->UnblockAndRegisterWithEventLoop();
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void wxSocketImpl::Close()
|
void wxSocketImpl::Close()
|
||||||
{
|
{
|
||||||
@@ -517,38 +536,6 @@ GAddress *wxSocketImpl::GetPeer()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSocketImpl::DoBlockWithTimeout(wxSocketEventFlags flags)
|
|
||||||
{
|
|
||||||
if ( !m_non_blocking )
|
|
||||||
{
|
|
||||||
fd_set fds;
|
|
||||||
wxFD_ZERO(&fds);
|
|
||||||
wxFD_SET(m_fd, &fds);
|
|
||||||
|
|
||||||
fd_set
|
|
||||||
*readfds = flags & wxSOCKET_INPUT_FLAG ? &fds : NULL,
|
|
||||||
*writefds = flags & wxSOCKET_OUTPUT_FLAG ? &fds : NULL;
|
|
||||||
|
|
||||||
// make a copy as it can be modified by select()
|
|
||||||
struct timeval tv = m_timeout;
|
|
||||||
int ret = select(m_fd + 1, readfds, writefds, NULL, &tv);
|
|
||||||
|
|
||||||
switch ( ret )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
m_error = wxSOCKET_TIMEDOUT;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
m_error = wxSOCKET_IOERR;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else: we're non-blocking, never block
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// wxSocketBase
|
// wxSocketBase
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@@ -715,9 +702,6 @@ wxSocketError wxSocketBase::LastError() const
|
|||||||
|
|
||||||
// The following IO operations update m_error and m_lcount:
|
// The following IO operations update m_error and m_lcount:
|
||||||
// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
|
// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
|
||||||
//
|
|
||||||
// TODO: Should Connect, Accept and AcceptWith update m_error?
|
|
||||||
|
|
||||||
bool wxSocketBase::Close()
|
bool wxSocketBase::Close()
|
||||||
{
|
{
|
||||||
// Interrupt pending waits
|
// Interrupt pending waits
|
||||||
@@ -773,7 +757,6 @@ wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
|
|||||||
// polling the socket and don't block at all.
|
// polling the socket and don't block at all.
|
||||||
if ( m_flags & wxSOCKET_NOWAIT )
|
if ( m_flags & wxSOCKET_NOWAIT )
|
||||||
{
|
{
|
||||||
wxSocketUnblocker unblock(m_impl);
|
|
||||||
int ret = m_impl->Read(buffer, nbytes);
|
int ret = m_impl->Read(buffer, nbytes);
|
||||||
if ( ret < 0 )
|
if ( ret < 0 )
|
||||||
return 0;
|
return 0;
|
||||||
@@ -784,10 +767,8 @@ wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
|
|||||||
{
|
{
|
||||||
for ( ;; )
|
for ( ;; )
|
||||||
{
|
{
|
||||||
// Wait until socket becomes ready for reading dispatching the GUI
|
// Wait until socket becomes ready for reading
|
||||||
// events in the meanwhile unless wxSOCKET_BLOCK was explicitly
|
if ( !WaitForRead() )
|
||||||
// specified to disable this.
|
|
||||||
if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const int ret = m_impl->Read(buffer, nbytes);
|
const int ret = m_impl->Read(buffer, nbytes);
|
||||||
@@ -981,7 +962,6 @@ wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
|
|||||||
wxUint32 total = 0;
|
wxUint32 total = 0;
|
||||||
if ( m_flags & wxSOCKET_NOWAIT )
|
if ( m_flags & wxSOCKET_NOWAIT )
|
||||||
{
|
{
|
||||||
wxSocketUnblocker unblock(m_impl);
|
|
||||||
const int ret = m_impl->Write(buffer, nbytes);
|
const int ret = m_impl->Write(buffer, nbytes);
|
||||||
if ( ret > 0 )
|
if ( ret > 0 )
|
||||||
total += ret;
|
total += ret;
|
||||||
@@ -990,7 +970,7 @@ wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
|
|||||||
{
|
{
|
||||||
for ( ;; )
|
for ( ;; )
|
||||||
{
|
{
|
||||||
if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
|
if ( !WaitForWrite() )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const int ret = m_impl->Write(buffer, nbytes);
|
const int ret = m_impl->Write(buffer, nbytes);
|
||||||
@@ -1124,7 +1104,7 @@ wxSocketBase& wxSocketBase::Discard()
|
|||||||
and it will return a mask indicating which operations can be performed.
|
and it will return a mask indicating which operations can be performed.
|
||||||
*/
|
*/
|
||||||
wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
|
wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
|
||||||
unsigned long timeout)
|
const timeval *timeout)
|
||||||
{
|
{
|
||||||
wxSocketEventFlags result = 0;
|
wxSocketEventFlags result = 0;
|
||||||
|
|
||||||
@@ -1132,7 +1112,10 @@ wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
|
|||||||
return (wxSOCKET_LOST_FLAG & flags);
|
return (wxSOCKET_LOST_FLAG & flags);
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
SetTimeValFromMS(tv, timeout);
|
if ( timeout )
|
||||||
|
tv = *timeout;
|
||||||
|
else
|
||||||
|
tv.tv_sec = tv.tv_usec = 0;
|
||||||
|
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
fd_set writefds;
|
fd_set writefds;
|
||||||
@@ -1237,9 +1220,10 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
|
|||||||
const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
|
const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
|
||||||
|
|
||||||
// Get the active event loop which we'll use for the message dispatching
|
// Get the active event loop which we'll use for the message dispatching
|
||||||
// when running in the main thread
|
// when running in the main thread unless this was explicitly disabled by
|
||||||
|
// setting wxSOCKET_BLOCK flag
|
||||||
wxEventLoopBase *eventLoop;
|
wxEventLoopBase *eventLoop;
|
||||||
if ( wxIsMainThread() )
|
if ( !(m_flags & wxSOCKET_BLOCK) && wxIsMainThread() )
|
||||||
{
|
{
|
||||||
eventLoop = wxEventLoop::GetActive();
|
eventLoop = wxEventLoop::GetActive();
|
||||||
}
|
}
|
||||||
@@ -1280,7 +1264,9 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
|
|||||||
else // no event loop or waiting in another thread
|
else // no event loop or waiting in another thread
|
||||||
{
|
{
|
||||||
// as explained below, we should always check for wxSOCKET_LOST_FLAG
|
// as explained below, we should always check for wxSOCKET_LOST_FLAG
|
||||||
events = m_impl->Select(flags | wxSOCKET_LOST_FLAG, timeLeft);
|
timeval tv;
|
||||||
|
SetTimeValFromMS(tv, timeLeft);
|
||||||
|
events = m_impl->Select(flags | wxSOCKET_LOST_FLAG, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
|
// always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
|
||||||
@@ -1642,17 +1628,34 @@ wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
|
|||||||
|
|
||||||
bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
|
bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
|
||||||
{
|
{
|
||||||
if (!m_impl)
|
if ( !m_impl || (m_impl->m_fd == INVALID_SOCKET) || !m_impl->IsServer() )
|
||||||
return false;
|
{
|
||||||
|
wxFAIL_MSG( "can only be called for a valid server socket" );
|
||||||
|
|
||||||
// If wait == false, then the call should be nonblocking.
|
m_error = wxSOCKET_INVSOCK;
|
||||||
// When we are finished, we put the socket to blocking mode
|
|
||||||
// again.
|
return false;
|
||||||
wxSocketUnblocker unblock(m_impl, !wait);
|
}
|
||||||
sock.m_impl = m_impl->WaitConnection(sock);
|
|
||||||
|
if ( wait )
|
||||||
|
{
|
||||||
|
// wait until we get a connection
|
||||||
|
if ( !m_impl->SelectWithTimeout(wxSOCKET_INPUT_FLAG) )
|
||||||
|
{
|
||||||
|
m_error = wxSOCKET_TIMEDOUT;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock.m_impl = m_impl->Accept(sock);
|
||||||
|
|
||||||
if ( !sock.m_impl )
|
if ( !sock.m_impl )
|
||||||
|
{
|
||||||
|
m_error = m_impl->GetLastError();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
sock.m_type = wxSOCKET_BASE;
|
sock.m_type = wxSOCKET_BASE;
|
||||||
sock.m_connected = true;
|
sock.m_connected = true;
|
||||||
@@ -1741,66 +1744,56 @@ wxSocketClient::~wxSocketClient()
|
|||||||
// Connect
|
// Connect
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxSocketClient::DoConnect(const wxSockAddress& addr_man,
|
bool wxSocketClient::DoConnect(const wxSockAddress& remote,
|
||||||
const wxSockAddress* local,
|
const wxSockAddress* local,
|
||||||
bool wait)
|
bool wait)
|
||||||
{
|
{
|
||||||
if (m_impl)
|
if ( m_impl )
|
||||||
{
|
{
|
||||||
// Shutdown and destroy the socket
|
// Shutdown and destroy the old socket
|
||||||
Close();
|
Close();
|
||||||
delete m_impl;
|
delete m_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_impl = wxSocketImpl::Create(*this);
|
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
m_establishing = false;
|
m_establishing = false;
|
||||||
|
|
||||||
if (!m_impl)
|
// Create and set up the new one
|
||||||
|
m_impl = wxSocketImpl::Create(*this);
|
||||||
|
if ( !m_impl )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If wait == false, then the call should be nonblocking. When we are
|
|
||||||
// finished, we put the socket to blocking mode again.
|
|
||||||
wxSocketUnblocker unblock(m_impl, !wait);
|
|
||||||
|
|
||||||
// Reuse makes sense for clients too, if we are trying to rebind to the same port
|
// Reuse makes sense for clients too, if we are trying to rebind to the same port
|
||||||
if (GetFlags() & wxSOCKET_REUSEADDR)
|
if (GetFlags() & wxSOCKET_REUSEADDR)
|
||||||
{
|
|
||||||
m_impl->SetReusable();
|
m_impl->SetReusable();
|
||||||
}
|
|
||||||
if (GetFlags() & wxSOCKET_BROADCAST)
|
if (GetFlags() & wxSOCKET_BROADCAST)
|
||||||
{
|
|
||||||
m_impl->SetBroadcast();
|
m_impl->SetBroadcast();
|
||||||
}
|
|
||||||
if (GetFlags() & wxSOCKET_NOBIND)
|
if (GetFlags() & wxSOCKET_NOBIND)
|
||||||
{
|
|
||||||
m_impl->DontDoBind();
|
m_impl->DontDoBind();
|
||||||
}
|
|
||||||
|
|
||||||
// If no local address was passed and one has been set, use the one that was Set
|
// Bind to the local IP address and port, when provided or if one had been
|
||||||
if (!local && m_localAddress.GetAddress())
|
// set before
|
||||||
{
|
if ( !local && m_localAddress.GetAddress() )
|
||||||
local = &m_localAddress;
|
local = &m_localAddress;
|
||||||
}
|
|
||||||
|
|
||||||
// Bind to the local IP address and port, when provided
|
if ( local )
|
||||||
if (local)
|
m_impl->SetLocal(local->GetAddress());
|
||||||
{
|
|
||||||
GAddress* la = local->GetAddress();
|
|
||||||
|
|
||||||
if (la && la->m_addr)
|
|
||||||
m_impl->SetLocal(la);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_impl->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
|
m_impl->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
|
||||||
|
|
||||||
m_impl->SetPeer(addr_man.GetAddress());
|
m_impl->SetPeer(remote.GetAddress());
|
||||||
const wxSocketError err = m_impl->CreateClient();
|
|
||||||
|
|
||||||
if (err != wxSOCKET_NOERROR)
|
// Finally do create the socket and connect to the peer
|
||||||
|
const wxSocketError err = m_impl->CreateClient(wait);
|
||||||
|
|
||||||
|
if ( err != wxSOCKET_NOERROR )
|
||||||
{
|
{
|
||||||
if (err == wxSOCKET_WOULDBLOCK)
|
if ( err == wxSOCKET_WOULDBLOCK )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( !wait, "shouldn't get this for blocking connect" );
|
||||||
|
|
||||||
m_establishing = true;
|
m_establishing = true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1809,16 +1802,16 @@ bool wxSocketClient::DoConnect(const wxSockAddress& addr_man,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSocketClient::Connect(const wxSockAddress& addr_man, bool wait)
|
bool wxSocketClient::Connect(const wxSockAddress& remote, bool wait)
|
||||||
{
|
{
|
||||||
return DoConnect(addr_man, NULL, wait);
|
return DoConnect(remote, NULL, wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSocketClient::Connect(const wxSockAddress& addr_man,
|
bool wxSocketClient::Connect(const wxSockAddress& remote,
|
||||||
const wxSockAddress& local,
|
const wxSockAddress& local,
|
||||||
bool wait)
|
bool wait)
|
||||||
{
|
{
|
||||||
return DoConnect(addr_man, &local, wait);
|
return DoConnect(remote, &local, wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
|
bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
|
||||||
|
@@ -448,139 +448,22 @@ void wxSocketImplMSW::DoClose()
|
|||||||
closesocket(m_fd);
|
closesocket(m_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
wxSocketError wxSocketImplUnix::GetLastError() const
|
||||||
* Waits for an incoming client connection. Returns a pointer to
|
|
||||||
* a wxSocketImpl object, or NULL if there was an error, in which case
|
|
||||||
* the last error field will be updated for the calling wxSocketImpl.
|
|
||||||
*
|
|
||||||
* Error codes (set in the calling wxSocketImpl)
|
|
||||||
* wxSOCKET_INVSOCK - the socket is not valid or not a server.
|
|
||||||
* wxSOCKET_TIMEDOUT - timeout, no incoming connections.
|
|
||||||
* wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
|
|
||||||
* wxSOCKET_MEMERR - couldn't allocate memory.
|
|
||||||
* wxSOCKET_IOERR - low-level error.
|
|
||||||
*/
|
|
||||||
wxSocketImpl *wxSocketImplMSW::WaitConnection(wxSocketBase& wxsocket)
|
|
||||||
{
|
{
|
||||||
wxSocketImpl *connection;
|
switch ( WSAGetLastError() )
|
||||||
wxSockAddr from;
|
|
||||||
WX_SOCKLEN_T fromlen = sizeof(from);
|
|
||||||
wxSocketError err;
|
|
||||||
u_long arg = 1;
|
|
||||||
|
|
||||||
/* Reenable CONNECTION events */
|
|
||||||
m_detected &= ~wxSOCKET_CONNECTION_FLAG;
|
|
||||||
|
|
||||||
/* If the socket has already been created, we exit immediately */
|
|
||||||
if (m_fd == INVALID_SOCKET || !m_server)
|
|
||||||
{
|
|
||||||
m_error = wxSOCKET_INVSOCK;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a wxSocketImpl object for the new connection */
|
|
||||||
connection = wxSocketImplMSW::Create(wxsocket);
|
|
||||||
|
|
||||||
if (!connection)
|
|
||||||
{
|
|
||||||
m_error = wxSOCKET_MEMERR;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for a connection (with timeout) */
|
|
||||||
if ( !BlockForInputWithTimeout() )
|
|
||||||
{
|
|
||||||
delete connection;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
connection->m_fd = accept(m_fd, (sockaddr*)&from, &fromlen);
|
|
||||||
|
|
||||||
if (connection->m_fd == INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
if (WSAGetLastError() == WSAEWOULDBLOCK)
|
|
||||||
m_error = wxSOCKET_WOULDBLOCK;
|
|
||||||
else
|
|
||||||
m_error = wxSOCKET_IOERR;
|
|
||||||
|
|
||||||
delete connection;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize all fields */
|
|
||||||
connection->m_server = false;
|
|
||||||
connection->m_stream = true;
|
|
||||||
|
|
||||||
/* Setup the peer address field */
|
|
||||||
connection->m_peer = GAddress_new();
|
|
||||||
if (!connection->m_peer)
|
|
||||||
{
|
|
||||||
delete connection;
|
|
||||||
m_error = wxSOCKET_MEMERR;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
err = _GAddress_translate_from(connection->m_peer, (sockaddr*)&from, fromlen);
|
|
||||||
if (err != wxSOCKET_NOERROR)
|
|
||||||
{
|
|
||||||
GAddress_destroy(connection->m_peer);
|
|
||||||
delete connection;
|
|
||||||
m_error = err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
|
|
||||||
wxSocketManager::Get()->Install_Callback(connection);
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxSocketError wxSocketImplMSW::DoHandleConnect(int ret)
|
|
||||||
{
|
|
||||||
// TODO: review this
|
|
||||||
if (ret == SOCKET_ERROR)
|
|
||||||
{
|
{
|
||||||
int err = WSAGetLastError();
|
case 0:
|
||||||
|
return wxSOCKET_NOERROR;
|
||||||
|
|
||||||
/* If connect failed with EWOULDBLOCK and the wxSocketImpl object
|
case WSAENOTSOCK:
|
||||||
* is in blocking mode, we select() for the specified timeout
|
return wxSOCKET_INVSOCK;
|
||||||
* checking for writability to see if the connection request
|
|
||||||
* completes.
|
|
||||||
*/
|
|
||||||
if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
|
|
||||||
{
|
|
||||||
err = Connect_Timeout();
|
|
||||||
|
|
||||||
if (err != wxSOCKET_NOERROR)
|
case WSAEWOULDBLOCK:
|
||||||
{
|
|
||||||
Close();
|
|
||||||
/* m_error is set in Connect_Timeout */
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wxSocketError) err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If connect failed with EWOULDBLOCK and the wxSocketImpl object
|
|
||||||
* is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
|
|
||||||
* (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
|
|
||||||
* this way if the connection completes, a wxSOCKET_CONNECTION
|
|
||||||
* event will be generated, if enabled.
|
|
||||||
*/
|
|
||||||
if ((err == WSAEWOULDBLOCK) && (m_non_blocking))
|
|
||||||
{
|
|
||||||
m_establishing = true;
|
|
||||||
m_error = wxSOCKET_WOULDBLOCK;
|
|
||||||
return wxSOCKET_WOULDBLOCK;
|
return wxSOCKET_WOULDBLOCK;
|
||||||
}
|
|
||||||
|
|
||||||
/* If connect failed with an error other than EWOULDBLOCK,
|
default:
|
||||||
* then the call to Connect() has failed.
|
return wxSOCKET_IOERR;
|
||||||
*/
|
|
||||||
Close();
|
|
||||||
m_error = wxSOCKET_IOERR;
|
|
||||||
return wxSOCKET_IOERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxSOCKET_NOERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generic IO */
|
/* Generic IO */
|
||||||
@@ -599,12 +482,6 @@ int wxSocketImplMSW::Read(void *buffer, int size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the socket is blocking, wait for data (with a timeout) */
|
|
||||||
if ( !BlockForInputWithTimeout() )
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the data */
|
/* Read the data */
|
||||||
if (m_stream)
|
if (m_stream)
|
||||||
ret = Recv_Stream(buffer, size);
|
ret = Recv_Stream(buffer, size);
|
||||||
@@ -633,10 +510,6 @@ int wxSocketImplMSW::Write(const void *buffer, int size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the socket is blocking, wait for writability (with a timeout) */
|
|
||||||
if ( !BlockForOutputWithTimeout() )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Write the data */
|
/* Write the data */
|
||||||
if (m_stream)
|
if (m_stream)
|
||||||
ret = Send_Stream(buffer, size);
|
ret = Send_Stream(buffer, size);
|
||||||
|
@@ -424,13 +424,6 @@ struct servent *wxGetservbyname_r(const char *port, const char *protocol,
|
|||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* debugging helpers */
|
|
||||||
#ifdef __GSOCKET_DEBUG__
|
|
||||||
# define SOCKET_DEBUG(args) printf args
|
|
||||||
#else
|
|
||||||
# define SOCKET_DEBUG(args)
|
|
||||||
#endif /* __GSOCKET_DEBUG__ */
|
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
|
wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
|
||||||
{
|
{
|
||||||
@@ -450,93 +443,22 @@ void wxSocketImplUnix::Shutdown()
|
|||||||
wxSocketImpl::Shutdown();
|
wxSocketImpl::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
wxSocketError wxSocketImplUnix::GetLastError() const
|
||||||
* Waits for an incoming client connection. Returns a pointer to
|
|
||||||
* a wxSocketImplUnix object, or NULL if there was an error, in which case
|
|
||||||
* the last error field will be updated for the calling wxSocketImplUnix.
|
|
||||||
*
|
|
||||||
* Error codes (set in the calling wxSocketImplUnix)
|
|
||||||
* wxSOCKET_INVSOCK - the socket is not valid or not a server.
|
|
||||||
* wxSOCKET_TIMEDOUT - timeout, no incoming connections.
|
|
||||||
* wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
|
|
||||||
* wxSOCKET_MEMERR - couldn't allocate memory.
|
|
||||||
* wxSOCKET_IOERR - low-level error.
|
|
||||||
*/
|
|
||||||
wxSocketImpl *wxSocketImplUnix::WaitConnection(wxSocketBase& wxsocket)
|
|
||||||
{
|
{
|
||||||
wxSockAddr from;
|
switch ( errno )
|
||||||
WX_SOCKLEN_T fromlen = sizeof(from);
|
{
|
||||||
wxSocketImpl *connection;
|
case 0:
|
||||||
wxSocketError err;
|
return wxSOCKET_NOERROR;
|
||||||
int arg = 1;
|
|
||||||
|
|
||||||
/* If the socket has already been created, we exit immediately */
|
case ENOTSOCK:
|
||||||
if (m_fd == INVALID_SOCKET || !m_server)
|
return wxSOCKET_INVSOCK;
|
||||||
{
|
|
||||||
m_error = wxSOCKET_INVSOCK;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a wxSocketImplUnix object for the new connection */
|
case EINPROGRESS:
|
||||||
connection = wxSocketImplUnix::Create(wxsocket);
|
return wxSOCKET_WOULDBLOCK;
|
||||||
|
|
||||||
if (!connection)
|
default:
|
||||||
{
|
return wxSOCKET_IOERR;
|
||||||
m_error = wxSOCKET_MEMERR;
|
}
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for a connection (with timeout) */
|
|
||||||
if ( !BlockForInputWithTimeout() )
|
|
||||||
{
|
|
||||||
delete connection;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
connection->m_fd = accept(m_fd, (sockaddr*)&from, (WX_SOCKLEN_T *) &fromlen);
|
|
||||||
|
|
||||||
/* Reenable CONNECTION events */
|
|
||||||
EnableEvent(wxSOCKET_CONNECTION);
|
|
||||||
|
|
||||||
if (connection->m_fd == INVALID_SOCKET)
|
|
||||||
{
|
|
||||||
if (errno == EWOULDBLOCK)
|
|
||||||
m_error = wxSOCKET_WOULDBLOCK;
|
|
||||||
else
|
|
||||||
m_error = wxSOCKET_IOERR;
|
|
||||||
|
|
||||||
delete connection;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize all fields */
|
|
||||||
connection->m_server = false;
|
|
||||||
connection->m_stream = true;
|
|
||||||
|
|
||||||
/* Setup the peer address field */
|
|
||||||
connection->m_peer = GAddress_new();
|
|
||||||
if (!connection->m_peer)
|
|
||||||
{
|
|
||||||
delete connection;
|
|
||||||
m_error = wxSOCKET_MEMERR;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _GAddress_translate_from(connection->m_peer, (sockaddr*)&from, fromlen);
|
|
||||||
if (err != wxSOCKET_NOERROR)
|
|
||||||
{
|
|
||||||
delete connection;
|
|
||||||
m_error = err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__EMX__) || defined(__VISAGECPP__)
|
|
||||||
ioctl(connection->m_fd, FIONBIO, (char*)&arg, sizeof(arg));
|
|
||||||
#else
|
|
||||||
ioctl(connection->m_fd, FIONBIO, &arg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSocketImplUnix::DoEnableEvents(bool flag)
|
void wxSocketImplUnix::DoEnableEvents(bool flag)
|
||||||
@@ -554,70 +476,6 @@ void wxSocketImplUnix::DoEnableEvents(bool flag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSocketError wxSocketImplUnix::DoHandleConnect(int ret)
|
|
||||||
{
|
|
||||||
/* We only call EnableEvents() if we know we aren't shutting down the socket.
|
|
||||||
* NB: EnableEvents() needs to be called whether the socket is blocking or
|
|
||||||
* non-blocking, it just shouldn't be called prior to knowing there is a
|
|
||||||
* connection _if_ blocking sockets are being used.
|
|
||||||
* If connect above returns 0, we are already connected and need to make the
|
|
||||||
* call to EnableEvents() now.
|
|
||||||
*/
|
|
||||||
if ( m_non_blocking || (ret == 0) )
|
|
||||||
EnableEvents();
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
const int err = errno;
|
|
||||||
|
|
||||||
/* If connect failed with EINPROGRESS and the wxSocketImplUnix object
|
|
||||||
* is in blocking mode, we select() for the specified timeout
|
|
||||||
* checking for writability to see if the connection request
|
|
||||||
* completes.
|
|
||||||
*/
|
|
||||||
if ((err == EINPROGRESS) && (!m_non_blocking))
|
|
||||||
{
|
|
||||||
if ( !BlockForOutputWithTimeout() )
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
return wxSOCKET_TIMEDOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error;
|
|
||||||
SOCKOPTLEN_T len = sizeof(error);
|
|
||||||
|
|
||||||
getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*) &error, &len);
|
|
||||||
EnableEvents();
|
|
||||||
|
|
||||||
if (!error)
|
|
||||||
return wxSOCKET_NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If connect failed with EINPROGRESS and the wxSocketImplUnix object
|
|
||||||
* is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
|
|
||||||
* (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
|
|
||||||
* this way if the connection completes, a wxSOCKET_CONNECTION
|
|
||||||
* event will be generated, if enabled.
|
|
||||||
*/
|
|
||||||
if ((err == EINPROGRESS) && (m_non_blocking))
|
|
||||||
{
|
|
||||||
m_establishing = true;
|
|
||||||
m_error = wxSOCKET_WOULDBLOCK;
|
|
||||||
return wxSOCKET_WOULDBLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If connect failed with an error other than EINPROGRESS,
|
|
||||||
* then the call to Connect has failed.
|
|
||||||
*/
|
|
||||||
Close();
|
|
||||||
m_error = wxSOCKET_IOERR;
|
|
||||||
|
|
||||||
return wxSOCKET_IOERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxSOCKET_NOERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generic IO */
|
/* Generic IO */
|
||||||
|
|
||||||
/* Like recv(), send(), ... */
|
/* Like recv(), send(), ... */
|
||||||
@@ -634,45 +492,34 @@ int wxSocketImplUnix::Read(void *buffer, int size)
|
|||||||
/* Disable events during query of socket status */
|
/* Disable events during query of socket status */
|
||||||
DisableEvent(wxSOCKET_INPUT);
|
DisableEvent(wxSOCKET_INPUT);
|
||||||
|
|
||||||
/* If the socket is blocking, wait for data (with a timeout) */
|
/* Read the data */
|
||||||
if ( !BlockForInputWithTimeout() )
|
if (m_stream)
|
||||||
{
|
|
||||||
m_error = wxSOCKET_TIMEDOUT;
|
|
||||||
/* Don't return here immediately, otherwise socket events would not be
|
|
||||||
* re-enabled! */
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Read the data */
|
|
||||||
if (m_stream)
|
|
||||||
ret = Recv_Stream(buffer, size);
|
ret = Recv_Stream(buffer, size);
|
||||||
else
|
else
|
||||||
ret = Recv_Dgram(buffer, size);
|
ret = Recv_Dgram(buffer, size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If recv returned zero for a TCP socket (if m_stream == NULL, it's an UDP
|
* If recv returned zero for a TCP socket (if m_stream == NULL, it's an UDP
|
||||||
* socket and empty datagrams are possible), then the connection has been
|
* socket and empty datagrams are possible), then the connection has been
|
||||||
* gracefully closed.
|
* gracefully closed.
|
||||||
*
|
*
|
||||||
* Otherwise, recv has returned an error (-1), in which case we have lost
|
* Otherwise, recv has returned an error (-1), in which case we have lost
|
||||||
* the socket only if errno does _not_ indicate that there may be more data
|
* the socket only if errno does _not_ indicate that there may be more data
|
||||||
* to read.
|
* to read.
|
||||||
*/
|
*/
|
||||||
if ((ret == 0) && m_stream)
|
if ((ret == 0) && m_stream)
|
||||||
{
|
{
|
||||||
/* Make sure wxSOCKET_LOST event gets sent and shut down the socket */
|
/* Make sure wxSOCKET_LOST event gets sent and shut down the socket */
|
||||||
m_detected = wxSOCKET_LOST_FLAG;
|
m_detected = wxSOCKET_LOST_FLAG;
|
||||||
OnReadWaiting();
|
OnReadWaiting();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (ret == -1)
|
else if (ret == -1)
|
||||||
{
|
{
|
||||||
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
|
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
|
||||||
m_error = wxSOCKET_WOULDBLOCK;
|
m_error = wxSOCKET_WOULDBLOCK;
|
||||||
else
|
else
|
||||||
m_error = wxSOCKET_IOERR;
|
m_error = wxSOCKET_IOERR;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable events again now that we are done processing */
|
/* Enable events again now that we are done processing */
|
||||||
@@ -685,41 +532,27 @@ int wxSocketImplUnix::Write(const void *buffer, int size)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
SOCKET_DEBUG(( "Write #1, size %d\n", size ));
|
|
||||||
|
|
||||||
if (m_fd == INVALID_SOCKET || m_server)
|
if (m_fd == INVALID_SOCKET || m_server)
|
||||||
{
|
{
|
||||||
m_error = wxSOCKET_INVSOCK;
|
m_error = wxSOCKET_INVSOCK;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET_DEBUG(( "Write #2, size %d\n", size ));
|
|
||||||
|
|
||||||
/* If the socket is blocking, wait for writability (with a timeout) */
|
|
||||||
if ( !BlockForOutputWithTimeout() )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
SOCKET_DEBUG(( "Write #3, size %d\n", size ));
|
|
||||||
|
|
||||||
/* Write the data */
|
/* Write the data */
|
||||||
if (m_stream)
|
if (m_stream)
|
||||||
ret = Send_Stream(buffer, size);
|
ret = Send_Stream(buffer, size);
|
||||||
else
|
else
|
||||||
ret = Send_Dgram(buffer, size);
|
ret = Send_Dgram(buffer, size);
|
||||||
|
|
||||||
SOCKET_DEBUG(( "Write #4, size %d\n", size ));
|
|
||||||
|
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
|
if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
|
||||||
{
|
{
|
||||||
m_error = wxSOCKET_WOULDBLOCK;
|
m_error = wxSOCKET_WOULDBLOCK;
|
||||||
SOCKET_DEBUG(( "Write error WOULDBLOCK\n" ));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_error = wxSOCKET_IOERR;
|
m_error = wxSOCKET_IOERR;
|
||||||
SOCKET_DEBUG(( "Write error IOERR\n" ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
|
/* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
|
||||||
@@ -732,8 +565,6 @@ int wxSocketImplUnix::Write(const void *buffer, int size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKET_DEBUG(( "Write #5, size %d ret %d\n", size, ret ));
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user