- }
-
- /* If connect failed with an error other than EWOULDBLOCK,
- * then the call to Connect() has failed.
- */
- Close();
- m_error = wxSOCKET_IOERR;
- return wxSOCKET_IOERR;
- }
-
- return wxSOCKET_NOERROR;
-}
-
-/* Generic IO */
-
-/* Like recv(), send(), ... */
-int wxSocketImplMSW::Read(void *buffer, int size)
-{
- int ret;
-
- /* Reenable INPUT events */
- m_detected &= ~wxSOCKET_INPUT_FLAG;
-
- if (m_fd == INVALID_SOCKET || m_server)
- {
- m_error = wxSOCKET_INVSOCK;
- return -1;
- }
-
- /* If the socket is blocking, wait for data (with a timeout) */
- if (Input_Timeout() == wxSOCKET_TIMEDOUT)
- {
- m_error = wxSOCKET_TIMEDOUT;
- return -1;
- }
-
- /* Read the data */
- if (m_stream)
- ret = Recv_Stream(buffer, size);
- else
- ret = Recv_Dgram(buffer, size);
-
- if (ret == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- m_error = wxSOCKET_IOERR;
- else
- m_error = wxSOCKET_WOULDBLOCK;
- return -1;
- }
-
- return ret;
-}
-
-int wxSocketImplMSW::Write(const void *buffer, int size)
-{
- int ret;
-
- if (m_fd == INVALID_SOCKET || m_server)
- {
- m_error = wxSOCKET_INVSOCK;
- return -1;
- }
-
- /* If the socket is blocking, wait for writability (with a timeout) */
- if (Output_Timeout() == wxSOCKET_TIMEDOUT)
- return -1;
-
- /* Write the data */
- if (m_stream)
- ret = Send_Stream(buffer, size);
- else
- ret = Send_Dgram(buffer, size);
-
- if (ret == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- m_error = wxSOCKET_IOERR;
- else
- m_error = wxSOCKET_WOULDBLOCK;
-
- /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
- * does). Once the first OUTPUT event is received, users can assume
- * that the socket is writable until a read operation fails. Only then
- * will further OUTPUT events be posted.
- */
- m_detected &= ~wxSOCKET_OUTPUT_FLAG;
- return -1;
- }
-
- return ret;
-}
-
-/* Internals (IO) */
-
-/*
- * For blocking sockets, wait until data is available or
- * until timeout ellapses.
- */
-wxSocketError wxSocketImplMSW::Input_Timeout()
-{
- fd_set readfds;
-
- if (!m_non_blocking)
- {
- FD_ZERO(&readfds);
- FD_SET(m_fd, &readfds);
- if (select(0, &readfds, NULL, NULL, &m_timeout) == 0)
- {
- m_error = wxSOCKET_TIMEDOUT;
- return wxSOCKET_TIMEDOUT;
- }
- }
- return wxSOCKET_NOERROR;
-}
-
-/*
- * For blocking sockets, wait until data can be sent without
- * blocking or until timeout ellapses.
- */
-wxSocketError wxSocketImplMSW::Output_Timeout()
-{
- fd_set writefds;
-
- if (!m_non_blocking)
- {
- FD_ZERO(&writefds);
- FD_SET(m_fd, &writefds);
- if (select(0, NULL, &writefds, NULL, &m_timeout) == 0)
- {
- m_error = wxSOCKET_TIMEDOUT;
- return wxSOCKET_TIMEDOUT;
- }
- }
- return wxSOCKET_NOERROR;
-}
-
-/*
- * For blocking sockets, wait until the connection is
- * established or fails, or until timeout ellapses.
- */
-wxSocketError wxSocketImplMSW::Connect_Timeout()
-{
- fd_set writefds;
- fd_set exceptfds;
-
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
- FD_SET(m_fd, &writefds);
- FD_SET(m_fd, &exceptfds);
- if (select(0, NULL, &writefds, &exceptfds, &m_timeout) == 0)
- {
- m_error = wxSOCKET_TIMEDOUT;
- return wxSOCKET_TIMEDOUT;
- }
- if (!FD_ISSET(m_fd, &writefds))
- {
- m_error = wxSOCKET_IOERR;
- return wxSOCKET_IOERR;
- }
-
- return wxSOCKET_NOERROR;
-}
-
-int wxSocketImplMSW::Recv_Stream(void *buffer, int size)
-{
- return recv(m_fd, static_cast<char *>(buffer), size, 0);
-}
-
-int wxSocketImplMSW::Recv_Dgram(void *buffer, int size)
-{
- wxSockAddr from;
- WX_SOCKLEN_T fromlen = sizeof(from);
- int ret;
- wxSocketError err;
-
- ret = recvfrom(m_fd, static_cast<char *>(buffer),
- size, 0, &from, &fromlen);
-
- if (ret == SOCKET_ERROR)
- return SOCKET_ERROR;
-
- /* Translate a system address into a wxSocketImpl address */
- if (!m_peer)
- {
- m_peer = GAddress_new();
- if (!m_peer)
- {
- m_error = wxSOCKET_MEMERR;
- return -1;
- }
- }
- err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
- if (err != wxSOCKET_NOERROR)
- {
- GAddress_destroy(m_peer);
- m_peer = NULL;
- m_error = err;
- return -1;
- }
-
- return ret;
-}
-
-int wxSocketImplMSW::Send_Stream(const void *buffer, int size)
-{
- return send(m_fd, static_cast<const char *>(buffer), size, 0);
-}
-
-int wxSocketImplMSW::Send_Dgram(const void *buffer, int size)
-{
- struct sockaddr *addr;
- int len, ret;
- wxSocketError err;
-
- if (!m_peer)
- {
- m_error = wxSOCKET_INVADDR;
- return -1;
- }
-
- err = _GAddress_translate_to(m_peer, &addr, &len);
- if (err != wxSOCKET_NOERROR)
- {
- m_error = err;
- return -1;
- }
-
- ret = sendto(m_fd, static_cast<const char *>(buffer), size, 0, addr, len);
-
- /* Frees memory allocated by _GAddress_translate_to */
- free(addr);
-
- return ret;
-}
-
-/*
- * -------------------------------------------------------------------------
- * GAddress
- * -------------------------------------------------------------------------
- */
-
-/* CHECK_ADDRESS verifies that the current address family is either
- * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
- * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
- * an appropiate error code.
- *
- * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
- */
-#define CHECK_ADDRESS(address, family) \
-{ \
- if (address->m_family == wxSOCKET_NOFAMILY) \
- if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
- return address->m_error; \
- if (address->m_family != wxSOCKET_##family) \
- { \
- address->m_error = wxSOCKET_INVADDR; \
- return wxSOCKET_INVADDR; \
- } \
-}
-
-#define CHECK_ADDRESS_RETVAL(address, family, retval) \
-{ \
- if (address->m_family == wxSOCKET_NOFAMILY) \
- if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
- return retval; \
- if (address->m_family != wxSOCKET_##family) \
- { \
- address->m_error = wxSOCKET_INVADDR; \
- return retval; \
- } \
-}
-
-
-GAddress *GAddress_new()
-{
- GAddress *address;
-
- if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
- return NULL;
-
- address->m_family = wxSOCKET_NOFAMILY;
- address->m_addr = NULL;
- address->m_len = 0;
-
- return address;
-}
-
-GAddress *GAddress_copy(GAddress *address)
-{
- GAddress *addr2;
-
- if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
- return NULL;
-
- memcpy(addr2, address, sizeof(GAddress));
-
- if (address->m_addr)
- {
- addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
- if (addr2->m_addr == NULL)
- {
- free(addr2);
- return NULL;
- }
- memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
- }
-
- return addr2;
-}
-
-void GAddress_destroy(GAddress *address)
-{
- if (address->m_addr)
- free(address->m_addr);
-
- free(address);
-}
-
-void GAddress_SetFamily(GAddress *address, GAddressType type)
-{
- address->m_family = type;
-}
-
-GAddressType GAddress_GetFamily(GAddress *address)
-{
- return address->m_family;
-}
-
-wxSocketError _GAddress_translate_from(GAddress *address,
- struct sockaddr *addr, int len)
-{
- address->m_realfamily = addr->sa_family;
- switch (addr->sa_family)
- {
- case AF_INET:
- address->m_family = wxSOCKET_INET;
- break;
- case AF_UNIX:
- address->m_family = wxSOCKET_UNIX;
- break;
-#if wxUSE_IPV6
- case AF_INET6:
- address->m_family = wxSOCKET_INET6;
- break;
-#endif
- default:
- {
- address->m_error = wxSOCKET_INVOP;
- return wxSOCKET_INVOP;
- }
- }
-
- if (address->m_addr)
- free(address->m_addr);
-
- address->m_len = len;
- address->m_addr = (struct sockaddr *) malloc(len);
-
- if (address->m_addr == NULL)
- {
- address->m_error = wxSOCKET_MEMERR;
- return wxSOCKET_MEMERR;
- }
- memcpy(address->m_addr, addr, len);
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError _GAddress_translate_to(GAddress *address,
- struct sockaddr **addr, int *len)
-{
- if (!address->m_addr)
- {
- address->m_error = wxSOCKET_INVADDR;
- return wxSOCKET_INVADDR;
- }
-
- *len = address->m_len;
- *addr = (struct sockaddr *) malloc(address->m_len);
- if (*addr == NULL)
- {
- address->m_error = wxSOCKET_MEMERR;
- return wxSOCKET_MEMERR;
- }
-
- memcpy(*addr, address->m_addr, address->m_len);
- return wxSOCKET_NOERROR;
-}
-
-/*
- * -------------------------------------------------------------------------
- * Internet address family
- * -------------------------------------------------------------------------
- */
-
-wxSocketError _GAddress_Init_INET(GAddress *address)
-{
- address->m_len = sizeof(struct sockaddr_in);
- address->m_addr = (struct sockaddr *) malloc(address->m_len);
- if (address->m_addr == NULL)
- {
- address->m_error = wxSOCKET_MEMERR;
- return wxSOCKET_MEMERR;
- }
-
- address->m_family = wxSOCKET_INET;
- address->m_realfamily = AF_INET;
- ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
- ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
-{
- struct hostent *he;
- struct in_addr *addr;
-
- CHECK_ADDRESS(address, INET);
-
- addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
-
- addr->s_addr = inet_addr(hostname);
-
- /* If it is a numeric host name, convert it now */
- if (addr->s_addr == INADDR_NONE)
- {
- struct in_addr *array_addr;
-
- /* It is a real name, we solve it */
- if ((he = gethostbyname(hostname)) == NULL)
- {
- /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
- address->m_error = wxSOCKET_NOHOST;
- return wxSOCKET_NOHOST;
- }
- array_addr = (struct in_addr *) *(he->h_addr_list);
- addr->s_addr = array_addr[0].s_addr;
- }
- return wxSOCKET_NOERROR;
-}