+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;