+// ============================================================================
+// wxSocketManager
+// ============================================================================
+
+wxSocketManager *wxSocketManager::ms_manager = NULL;
+
+/* static */
+void wxSocketManager::Set(wxSocketManager *manager)
+{
+    wxASSERT_MSG( !ms_manager, "too late to set manager now" );
+
+    ms_manager = manager;
+}
+
+/* static */
+void wxSocketManager::Init()
+{
+    wxASSERT_MSG( !ms_manager, "shouldn't be initialized twice" );
+
+    /*
+        Details: Initialize() creates a hidden window as a sink for socket
+        events, such as 'read completed'. wxMSW has only one message loop
+        for the main thread. If Initialize is called in a secondary thread,
+        the socket window will be created for the secondary thread, but
+        since there is no message loop on this thread, it will never
+        receive events and all socket operations will time out.
+        BTW, the main thread must not be stopped using sleep or block
+        on a semaphore (a bad idea in any case) or socket operations
+        will time out.
+
+        On the Mac side, Initialize() stores a pointer to the CFRunLoop for
+        the main thread. Because secondary threads do not have run loops,
+        adding event notifications to the "Current" loop would have no
+        effect at all, events would never fire.
+    */
+    wxASSERT_MSG( wxIsMainThread(),
+                    "sockets must be initialized from the main thread" );
+
+    wxAppConsole * const app = wxAppConsole::GetInstance();
+    wxCHECK_RET( app, "sockets can't be initialized without wxApp" );
+
+    ms_manager = app->GetTraits()->GetSocketManager();
+}
+
+// ==========================================================================
+// wxSocketImpl
+// ==========================================================================
+
+wxSocketImpl::wxSocketImpl(wxSocketBase& wxsocket)
+    : m_wxsocket(&wxsocket)
+{
+    m_fd              = INVALID_SOCKET;
+    m_error           = wxSOCKET_NOERROR;
+    m_server          = false;
+    m_stream          = true;
+
+    SetTimeout(wxsocket.GetTimeout() * 1000);
+
+    m_establishing    = false;
+    m_reusable        = false;
+    m_broadcast       = false;
+    m_dobind          = true;
+    m_initialRecvBufferSize = -1;
+    m_initialSendBufferSize = -1;
+}
+
+wxSocketImpl::~wxSocketImpl()
+{
+    if ( m_fd != INVALID_SOCKET )
+        Shutdown();
+}
+
+bool wxSocketImpl::PreCreateCheck(const wxSockAddressImpl& addr)
+{
+    if ( m_fd != INVALID_SOCKET )
+    {
+        m_error = wxSOCKET_INVSOCK;
+        return false;
+    }
+
+    if ( !addr.IsOk() )
+    {
+        m_error = wxSOCKET_INVADDR;
+        return false;
+    }
+
+    return true;
+}
+
+void wxSocketImpl::PostCreation()
+{
+    // FreeBSD variants can't use MSG_NOSIGNAL, and instead use a socket option
+#ifdef SO_NOSIGPIPE
+    EnableSocketOption(SO_NOSIGPIPE);
+#endif
+
+    if ( m_reusable )
+        EnableSocketOption(SO_REUSEADDR);
+
+    if ( m_broadcast )
+    {
+        wxASSERT_MSG( !m_stream, "broadcasting is for datagram sockets only" );
+
+        EnableSocketOption(SO_BROADCAST);
+    }
+
+    if ( m_initialRecvBufferSize >= 0 )
+        SetSocketOption(SO_RCVBUF, m_initialRecvBufferSize);
+    if ( m_initialSendBufferSize >= 0 )
+        SetSocketOption(SO_SNDBUF, m_initialSendBufferSize);
+
+    // we always put our sockets in unblocked mode and handle blocking
+    // ourselves in DoRead/Write() if wxSOCKET_WAITALL is specified
+    UnblockAndRegisterWithEventLoop();
+}
+
+wxSocketError wxSocketImpl::UpdateLocalAddress()
+{
+    WX_SOCKLEN_T lenAddr = m_local.GetLen();
+    if ( getsockname(m_fd, m_local.GetWritableAddr(), &lenAddr) != 0 )
+    {
+        Close();
+        m_error = wxSOCKET_IOERR;
+        return m_error;
+    }
+
+    return wxSOCKET_NOERROR;
+}
+
+wxSocketError wxSocketImpl::CreateServer()
+{
+    if ( !PreCreateCheck(m_local) )
+        return m_error;
+
+    m_server = true;
+    m_stream = true;
+
+    // do create the socket
+    m_fd = socket(m_local.GetFamily(), SOCK_STREAM, 0);
+
+    if ( m_fd == INVALID_SOCKET )
+    {
+        m_error = wxSOCKET_IOERR;
+        return wxSOCKET_IOERR;
+    }
+
+    PostCreation();
+
+    // and then bind to and listen on it
+    //
+    // FIXME: should we test for m_dobind here?
+    if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 )
+        m_error = wxSOCKET_IOERR;
+
+    if ( IsOk() )
+    {
+        if ( listen(m_fd, 5) != 0 )
+            m_error = wxSOCKET_IOERR;
+    }
+
+    if ( !IsOk() )
+    {
+        Close();
+        return m_error;
+    }
+
+    // finally retrieve the address we effectively bound to
+    return UpdateLocalAddress();
+}
+
+wxSocketError wxSocketImpl::CreateClient(bool wait)
+{
+    if ( !PreCreateCheck(m_peer) )
+        return m_error;
+
+    m_fd = socket(m_peer.GetFamily(), SOCK_STREAM, 0);
+
+    if ( m_fd == INVALID_SOCKET )
+    {
+        m_error = wxSOCKET_IOERR;
+        return wxSOCKET_IOERR;
+    }
+
+    PostCreation();
+
+    // If a local address has been set, then bind to it before calling connect
+    if ( m_local.IsOk() )
+    {
+        if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 )
+        {
+            Close();
+            m_error = wxSOCKET_IOERR;
+            return m_error;
+        }
+    }
+
+    // Do connect now
+    int rc = connect(m_fd, m_peer.GetAddr(), m_peer.GetLen());
+    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;
+}
+
+
+wxSocketError wxSocketImpl::CreateUDP()
+{
+    if ( !PreCreateCheck(m_local) )
+        return m_error;
+
+    m_stream = false;
+    m_server = false;
+
+    m_fd = socket(m_local.GetFamily(), SOCK_DGRAM, 0);
+
+    if ( m_fd == INVALID_SOCKET )
+    {
+        m_error = wxSOCKET_IOERR;
+        return wxSOCKET_IOERR;
+    }
+
+    PostCreation();
+
+    if ( m_dobind )
+    {
+        if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 )
+        {
+            Close();
+            m_error = wxSOCKET_IOERR;
+            return m_error;
+        }
+
+        return UpdateLocalAddress();
+    }
+
+    return wxSOCKET_NOERROR;
+}
+
+wxSocketImpl *wxSocketImpl::Accept(wxSocketBase& wxsocket)
+{
+    wxSockAddressStorage from;
+    WX_SOCKLEN_T fromlen = sizeof(from);
+    const SOCKET fd = accept(m_fd, &from.addr, &fromlen);
+
+    // accepting is similar to reading in the sense that it resets "ready for
+    // read" flag on the socket
+    ReenableEvents(wxSOCKET_INPUT_FLAG);
+
+    if ( fd == INVALID_SOCKET )
+        return NULL;
+
+    wxSocketImpl * const sock = Create(wxsocket);
+    sock->m_fd = fd;
+    sock->m_peer = wxSockAddressImpl(from.addr, fromlen);
+
+    sock->UnblockAndRegisterWithEventLoop();
+
+    return sock;
+}
+
+
+void wxSocketImpl::Close()
+{
+    if ( m_fd != INVALID_SOCKET )
+    {
+        DoClose();
+        m_fd = INVALID_SOCKET;
+    }
+}
+
+void wxSocketImpl::Shutdown()
+{
+    if ( m_fd != INVALID_SOCKET )
+    {
+        shutdown(m_fd, 1 /* SD_SEND */);
+        Close();
+    }
+}
+
+/*
+ *  Sets the timeout for blocking calls. Time is expressed in
+ *  milliseconds.
+ */
+void wxSocketImpl::SetTimeout(unsigned long millis)
+{
+    SetTimeValFromMS(m_timeout, millis);
+}
+
+void wxSocketImpl::NotifyOnStateChange(wxSocketNotify event)
+{
+    m_wxsocket->OnRequest(event);
+}
+
+/* Address handling */
+wxSocketError wxSocketImpl::SetLocal(const wxSockAddressImpl& local)
+{
+    /* the socket must be initialized, or it must be a server */
+    if (m_fd != INVALID_SOCKET && !m_server)
+    {
+        m_error = wxSOCKET_INVSOCK;
+        return wxSOCKET_INVSOCK;
+    }
+
+    if ( !local.IsOk() )
+    {
+        m_error = wxSOCKET_INVADDR;
+        return wxSOCKET_INVADDR;
+    }
+
+    m_local = local;
+
+    return wxSOCKET_NOERROR;
+}
+
+wxSocketError wxSocketImpl::SetPeer(const wxSockAddressImpl& peer)
+{
+    if ( !peer.IsOk() )
+    {
+        m_error = wxSOCKET_INVADDR;
+        return wxSOCKET_INVADDR;
+    }
+
+    m_peer = peer;
+
+    return wxSOCKET_NOERROR;
+}
+
+const wxSockAddressImpl& wxSocketImpl::GetLocal()
+{
+    if ( !m_local.IsOk() )
+        UpdateLocalAddress();
+
+    return m_local;
+}
+
+// ----------------------------------------------------------------------------
+// wxSocketImpl IO
+// ----------------------------------------------------------------------------
+
+// this macro wraps the given expression (normally a syscall) in a loop which
+// ignores any interruptions, i.e. reevaluates it again if it failed and errno
+// is EINTR
+#ifdef __UNIX__
+    #define DO_WHILE_EINTR( rc, syscall ) \
+        do { \
+            rc = (syscall); \
+        } \
+        while ( rc == -1 && errno == EINTR )
+#else
+    #define DO_WHILE_EINTR( rc, syscall ) rc = (syscall)
+#endif
+
+int wxSocketImpl::RecvStream(void *buffer, int size)
+{
+    int ret;
+    DO_WHILE_EINTR( ret, recv(m_fd, static_cast<char *>(buffer), size, 0) );
+
+    if ( !ret )
+    {
+        // receiving 0 bytes for a TCP socket indicates that the connection was
+        // closed by peer so shut down our end as well (for UDP sockets empty
+        // datagrams are also possible)
+        m_establishing = false;
+        NotifyOnStateChange(wxSOCKET_LOST);
+
+        Shutdown();
+
+        // do not return an error in this case however
+    }
+
+    return ret;
+}
+
+int wxSocketImpl::SendStream(const void *buffer, int size)
+{
+#ifdef wxNEEDS_IGNORE_SIGPIPE
+    IgnoreSignal ignore(SIGPIPE);
+#endif
+
+    int ret;
+    DO_WHILE_EINTR( ret, send(m_fd, static_cast<const char *>(buffer), size,
+                              wxSOCKET_MSG_NOSIGNAL) );
+
+    return ret;
+}
+
+int wxSocketImpl::RecvDgram(void *buffer, int size)
+{
+    wxSockAddressStorage from;
+    WX_SOCKLEN_T fromlen = sizeof(from);
+
+    int ret;
+    DO_WHILE_EINTR( ret, recvfrom(m_fd, static_cast<char *>(buffer), size,
+                                  0, &from.addr, &fromlen) );
+
+    if ( ret == SOCKET_ERROR )
+        return SOCKET_ERROR;
+
+    m_peer = wxSockAddressImpl(from.addr, fromlen);
+    if ( !m_peer.IsOk() )
+        return -1;
+
+    return ret;
+}
+
+int wxSocketImpl::SendDgram(const void *buffer, int size)
+{
+    if ( !m_peer.IsOk() )
+    {
+        m_error = wxSOCKET_INVADDR;
+        return -1;
+    }
+
+    int ret;
+    DO_WHILE_EINTR( ret, sendto(m_fd, static_cast<const char *>(buffer), size,
+                                0, m_peer.GetAddr(), m_peer.GetLen()) );
+
+    return ret;
+}
+
+int wxSocketImpl::Read(void *buffer, int size)
+{
+    // server sockets can't be used for IO, only to accept new connections
+    if ( m_fd == INVALID_SOCKET || m_server )
+    {
+        m_error = wxSOCKET_INVSOCK;
+        return -1;
+    }
+
+    int ret = m_stream ? RecvStream(buffer, size)
+                       : RecvDgram(buffer, size);
+
+    m_error = ret == SOCKET_ERROR ? GetLastError() : wxSOCKET_NOERROR;
+
+    return ret;
+}
+
+int wxSocketImpl::Write(const void *buffer, int size)
+{
+    if ( m_fd == INVALID_SOCKET || m_server )
+    {
+        m_error = wxSOCKET_INVSOCK;
+        return -1;
+    }
+
+    int ret = m_stream ? SendStream(buffer, size)
+                       : SendDgram(buffer, size);
+
+    m_error = ret == SOCKET_ERROR ? GetLastError() : wxSOCKET_NOERROR;
+
+    return ret;
+}
+