X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9bbd7ba3ea5befa691bcbab81c25cfaceac079cd..37b8e6798782278fdfe4f3c1291aaff55cdbb8c9:/src/msw/gsocket.c?ds=sidebyside diff --git a/src/msw/gsocket.c b/src/msw/gsocket.c index a4f45084d8..10c1b2ab4f 100644 --- a/src/msw/gsocket.c +++ b/src/msw/gsocket.c @@ -6,14 +6,19 @@ * ------------------------------------------------------------------------- */ +#ifndef __GSOCKET_STANDALONE__ +#include "wx/setup.h" +#endif -#ifdef __WXMSW__ +#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) + + +#ifndef __GSOCKET_STANDALONE__ -#include "wx/setup.h" #include "wx/msw/gsockmsw.h" #include "wx/gsocket.h" -#define INSTANCE wxhInstance +#define INSTANCE wxGetInstance() #else @@ -24,12 +29,10 @@ * be available and it must containt the app's instance * handle. */ -#define INSTANCE hInst - -#endif /* __WXMSW__ */ +#define INSTANCE hInst +#endif /* __GSOCKET_STANDALONE__ */ -#if !defined(__WXMSW__) || (defined(__WXMSW__) && wxUSE_SOCKETS) #include #include @@ -99,7 +102,6 @@ bool GSocket_Init() } firstAvailable = 0; - /* Initialize WinSocket */ return (WSAStartup((1 << 8) | 1, &wsaData) == 0); } @@ -107,7 +109,7 @@ bool GSocket_Init() void GSocket_Cleanup() { /* Destroy internal window */ - DestroyWindow(WINDOWNAME); + DestroyWindow(hWin); UnregisterClass(CLASSNAME, INSTANCE); /* Delete critical section */ @@ -139,7 +141,8 @@ GSocket *GSocket_new() socket->m_stream = TRUE; socket->m_non_blocking = FALSE; socket->m_timeout.tv_sec = 10 * 60; /* 10 minutes */ - socket->m_timeout.tv_usec = 0; + socket->m_timeout.tv_usec = 0; + socket->m_detected = 0; /* Allocate a new message number for this socket */ EnterCriticalSection(&critical); @@ -169,26 +172,23 @@ void GSocket_destroy(GSocket *socket) { assert(socket != NULL); - /* We don't want more event notifications; so first of all we - * remove the socket from the list (NOTE: we won't get a CLOSE - * event for this socket if it wasn't closed before). - */ + /* Remove the socket from the list */ EnterCriticalSection(&critical); socketList[(socket->m_msgnumber - WM_USER)] = NULL; LeaveCriticalSection(&critical); - /* We check that the socket is really shutdowned */ + /* Check that the socket is really shutdowned */ if (socket->m_fd != INVALID_SOCKET) GSocket_Shutdown(socket); - /* We destroy private addresses */ + /* Destroy private addresses */ if (socket->m_local) GAddress_destroy(socket->m_local); if (socket->m_peer) GAddress_destroy(socket->m_peer); - /* We destroy socket itself */ + /* Destroy socket itself */ free(socket); } @@ -198,22 +198,20 @@ void GSocket_Shutdown(GSocket *socket) assert(socket != NULL); - /* If socket has been created, we shutdown it */ + /* If socket has been created, shutdown it */ if (socket->m_fd != INVALID_SOCKET) { - /* TODO: Guilhem only does this for connection oriented sockets (?) */ shutdown(socket->m_fd, 2); closesocket(socket->m_fd); socket->m_fd = INVALID_SOCKET; } - /* We disable GUI callbacks */ + /* Disable GUI callbacks */ for (evt = 0; evt < GSOCK_MAX_EVENT; evt++) - { socket->m_cbacks[evt] = NULL; - } - _GSocket_Configure_Callbacks(socket); + socket->m_detected = 0; + _GSocket_Disable_Events(socket); } /* Address handling */ @@ -264,7 +262,8 @@ GAddress *GSocket_GetLocal(GSocket *socket) { GAddress *address; struct sockaddr addr; - SOCKLEN_T size; + SOCKLEN_T size = sizeof(addr); + GSocketError err; assert(socket != NULL); @@ -291,10 +290,11 @@ GAddress *GSocket_GetLocal(GSocket *socket) socket->m_error = GSOCK_MEMERR; return NULL; } - if (_GAddress_translate_from(address, &addr, size) != GSOCK_NOERROR) + err = _GAddress_translate_from(address, &addr, size); + if (err != GSOCK_NOERROR) { - socket->m_error = GSOCK_MEMERR; GAddress_destroy(address); + socket->m_error = err; return NULL; } @@ -345,7 +345,6 @@ GSocketError GSocket_SetServer(GSocket *sck) /* Create the socket */ sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0); - ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg); if (sck->m_fd == INVALID_SOCKET) { @@ -353,6 +352,9 @@ GSocketError GSocket_SetServer(GSocket *sck) return GSOCK_IOERR; } + ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg); + _GSocket_Enable_Events(sck); + /* Bind the socket to the LOCAL address */ if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) != 0) { @@ -372,7 +374,7 @@ GSocketError GSocket_SetServer(GSocket *sck) } return GSOCK_NOERROR; -} +} /* GSocket_WaitConnection: * Waits for an incoming client connection. @@ -380,11 +382,15 @@ GSocketError GSocket_SetServer(GSocket *sck) GSocket *GSocket_WaitConnection(GSocket *sck) { GSocket *connection; + struct sockaddr from; + SOCKLEN_T fromlen = sizeof(from); + GSocketError err; u_long arg = 1; assert(sck != NULL); - /* If the socket has already been created, we exit immediately */ + sck->m_detected &= ~GSOCK_CONNECTION_FLAG; + if (sck->m_fd == INVALID_SOCKET || !sck->m_server) { sck->m_error = GSOCK_INVSOCK; @@ -408,13 +414,16 @@ GSocket *GSocket_WaitConnection(GSocket *sck) return NULL; } - connection->m_fd = accept(sck->m_fd, NULL, NULL); - ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg); + connection->m_fd = accept(sck->m_fd, &from, &fromlen); if (connection->m_fd == INVALID_SOCKET) { + if (WSAGetLastError() == WSAEWOULDBLOCK) + sck->m_error = GSOCK_WOULDBLOCK; + else + sck->m_error = GSOCK_IOERR; + GSocket_destroy(connection); - sck->m_error = GSOCK_IOERR; return NULL; } @@ -423,6 +432,26 @@ GSocket *GSocket_WaitConnection(GSocket *sck) connection->m_stream = TRUE; connection->m_oriented = TRUE; + /* Setup the peer address field */ + connection->m_peer = GAddress_new(); + if (!connection->m_peer) + { + GSocket_destroy(connection); + sck->m_error = GSOCK_MEMERR; + return NULL; + } + err = _GAddress_translate_from(connection->m_peer, &from, fromlen); + if (err != GSOCK_NOERROR) + { + GAddress_destroy(connection->m_peer); + GSocket_destroy(connection); + sck->m_error = err; + return NULL; + } + + ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg); + _GSocket_Enable_Events(connection); + return connection; } @@ -453,7 +482,6 @@ GSocketError GSocket_SetNonOriented(GSocket *sck) /* Create the socket */ sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0); - ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg); if (sck->m_fd == INVALID_SOCKET) { @@ -461,6 +489,9 @@ GSocketError GSocket_SetNonOriented(GSocket *sck) return GSOCK_IOERR; } + ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg); + _GSocket_Enable_Events(sck); + /* Bind it to the LOCAL address */ if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) != 0) { @@ -475,15 +506,15 @@ GSocketError GSocket_SetNonOriented(GSocket *sck) GSocketError GSocket_SetBroadcast(GSocket *sck) { - BOOL b; + BOOL b = TRUE; assert(sck != NULL); if (GSocket_SetNonOriented(sck) != GSOCK_NOERROR) return sck->m_error; - b = TRUE; - setsockopt(sck->m_fd, SOL_SOCKET, SO_BROADCAST, (const char FAR *) &b, sizeof(b)); + setsockopt(sck->m_fd, SOL_SOCKET, SO_BROADCAST, + (const char FAR *) &b, sizeof(b)); return GSOCK_NOERROR; } @@ -493,17 +524,21 @@ GSocketError GSocket_SetBroadcast(GSocket *sck) /* GSocket_Connect: * Establishes a client connection to a server using the "Peer" * field of GSocket. "Peer" must be set by GSocket_SetPeer() before - * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK - * if the socket is alredy in use, GSOCK_INVADDR if the peer address - * has not been set, or GSOCK_IOERR for other internal errors. + * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK, + * GSOCK_INVADDR, GSOCK_TIMEDOUT, GSOCK_WOULDBLOCK and GSOCK_IOERR. + * If a socket is nonblocking and Connect() returns GSOCK_WOULDBLOCK, + * the connection request can be completed later. Use GSocket_Select() + * to check or wait for a GSOCK_CONNECTION event. */ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) { u_long arg = 1; - int type, ret; + int type, ret, err; assert(sck != NULL); + sck->m_detected &= ~GSOCK_CONNECTION_FLAG; + if (sck->m_fd != INVALID_SOCKET) { sck->m_error = GSOCK_INVSOCK; @@ -528,7 +563,6 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) /* Create the socket */ sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0); - ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg); if (sck->m_fd == INVALID_SOCKET) { @@ -536,35 +570,53 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) return GSOCK_IOERR; } - /* Connect it to the PEER address, with a timeout */ + ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg); + _GSocket_Enable_Events(sck); + + /* Connect it to the PEER address, with a timeout (see below) */ ret = connect(sck->m_fd, sck->m_peer->m_addr, sck->m_peer->m_len); if (ret == SOCKET_ERROR) { - /* For blocking GSockets, if connect fails with an EWOULDBLOCK - * error, then we can select() the socket for the specified - * timeout and check for writability to see if the connection - * request completes. If the error is different than EWOULDBLOCK, - * or if the socket is nonblocking, the call to GSocket_Connect() - * has failed. + err = WSAGetLastError(); + + /* If connect failed with EWOULDBLOCK and the GSocket object + * is in blocking mode, we select() for the specified timeout + * checking for writability to see if the connection request + * completes. */ - if ((!sck->m_non_blocking) && (WSAGetLastError() == WSAEWOULDBLOCK)) + if ((err == WSAEWOULDBLOCK) && (!sck->m_non_blocking)) { if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT) { closesocket(sck->m_fd); sck->m_fd = INVALID_SOCKET; - /* sck->m_error is set in _GSocket_Input_Timeout */ + /* sck->m_error is set in _GSocket_Output_Timeout */ return GSOCK_TIMEDOUT; } + else + return GSOCK_NOERROR; } - else /* error */ + + /* If connect failed with EWOULDBLOCK and the GSocket object + * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK + * (and return GSOCK_WOULDBLOCK) but we don't close the socket; + * this way if the connection completes, a GSOCK_CONNECTION + * event will be generated, if enabled. + */ + if ((err == WSAEWOULDBLOCK) && (sck->m_non_blocking)) { - closesocket(sck->m_fd); - sck->m_fd = INVALID_SOCKET; - sck->m_error = GSOCK_IOERR; - return GSOCK_IOERR; + sck->m_error = GSOCK_WOULDBLOCK; + return GSOCK_WOULDBLOCK; } + + /* If connect failed with an error other than EWOULDBLOCK, + * then the call to GSocket_Connect has failed. + */ + closesocket(sck->m_fd); + sck->m_fd = INVALID_SOCKET; + sck->m_error = GSOCK_IOERR; + return GSOCK_IOERR; } return GSOCK_NOERROR; @@ -575,25 +627,64 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) /* Like recv(), send(), ... */ int GSocket_Read(GSocket *socket, char *buffer, int size) { + int ret; + assert(socket != NULL); + socket->m_detected &= ~GSOCK_INPUT_FLAG; + if (socket->m_fd == INVALID_SOCKET || socket->m_server) { socket->m_error = GSOCK_INVSOCK; return -1; } + /* If the socket is blocking, wait for data (with a timeout) */ if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT) return -1; + /* Read the data */ if (socket->m_stream) - return _GSocket_Recv_Stream(socket, buffer, size); + ret = _GSocket_Recv_Stream(socket, buffer, size); else - return _GSocket_Recv_Dgram(socket, buffer, size); + ret = _GSocket_Recv_Dgram(socket, buffer, size); + + if (ret == SOCKET_ERROR) + { + /* NOTE: Window sockets exhibit a very strange property; + * if the socket is in non-blocking mode (which is always + * the case here, no matter the setting of GSocket itself) + * a call to send() can fail with EWOULDBLOCK even when + * select() says that the socket is writable. + * + * This can break several things because, usually, if + * select() says that the socket is writable, it is + * assumed that send() won't fail. To avoid this, we + * return 0 instead of -1 for this special case. + * + * XXX - this comment seems not to belong here, and also + * the code is not consistent with the unix version of + * gsocket... what to do? (GRG) + */ + if (WSAGetLastError() != WSAEWOULDBLOCK) + { + socket->m_error = GSOCK_IOERR; + return -1; + } + else + { + socket->m_error = GSOCK_WOULDBLOCK; + return 0; + } + } + + return ret; } int GSocket_Write(GSocket *socket, const char *buffer, int size) { + int ret; + assert(socket != NULL); if (socket->m_fd == INVALID_SOCKET || socket->m_server) @@ -602,43 +693,48 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size) return -1; } + /* If the socket is blocking, wait for writability (with a timeout) */ if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT) return -1; + /* Read the data */ if (socket->m_stream) - return _GSocket_Send_Stream(socket, buffer, size); + ret = _GSocket_Send_Stream(socket, buffer, size); else - return _GSocket_Send_Dgram(socket, buffer, size); -} - -bool GSocket_DataAvailable(GSocket *socket) -{ - fd_set read_set; - struct timeval tv; + ret = _GSocket_Send_Dgram(socket, buffer, size); - assert(socket != NULL); - - if (socket->m_fd == INVALID_SOCKET || socket->m_server) + if (ret == SOCKET_ERROR) { - socket->m_error = GSOCK_INVSOCK; - return FALSE; - } + if (WSAGetLastError() != WSAEWOULDBLOCK) + socket->m_error = GSOCK_IOERR; + else + socket->m_error = GSOCK_WOULDBLOCK; - FD_ZERO(&read_set); - FD_SET(socket->m_fd, &read_set); + socket->m_detected &= ~GSOCK_OUTPUT_FLAG; + return -1; + } - tv.tv_sec = 0; - tv.tv_usec = 0; + return ret; +} - select(socket->m_fd + 1, &read_set, NULL, NULL, &tv); +/* GSocket_Select: + * Polls the socket to determine its status. This function will + * check for the events specified in the 'flags' parameter, and + * it will return a mask indicating which operations can be + * performed. This function won't block, regardless of the + * mode (blocking|nonblocking) of the socket. + */ +GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags) +{ + assert(socket != NULL); - return FD_ISSET(socket->m_fd, &read_set); + return (flags & socket->m_detected); } /* Flags */ /* GSocket_SetNonBlocking: - * Sets the socket in non-blocking mode. This is useful if + * Sets the socket to non-blocking mode. This is useful if * we don't want to wait. */ void GSocket_SetNonBlocking(GSocket *socket, bool non_block) @@ -649,13 +745,15 @@ void GSocket_SetNonBlocking(GSocket *socket, bool non_block) } /* GSocket_SetTimeout: + * Sets the timeout for blocking calls. Time is + * expressed in milliseconds. */ -void GSocket_SetTimeout(GSocket *socket, unsigned long millisecs) +void GSocket_SetTimeout(GSocket *socket, unsigned long millis) { assert(socket != NULL); - socket->m_timeout.tv_sec = (millisecs / 1000); - socket->m_timeout.tv_usec = (millisecs % 1000) * 1000; + socket->m_timeout.tv_sec = (millis / 1000); + socket->m_timeout.tv_usec = (millis % 1000) * 1000; } /* GSocket_GetError: @@ -687,14 +785,14 @@ GSocketError GSocket_GetError(GSocket *socket) */ /* GSocket_SetCallback: - * Enables the callbacks specified by 'event'. Note that 'event' + * Enables the callbacks specified by 'flags'. Note that 'flags' * may be a combination of flags OR'ed toghether, so the same * callback function can be made to accept different events. * The callback function must have the following prototype: * * void function(GSocket *socket, GSocketEvent event, char *cdata) */ -void GSocket_SetCallback(GSocket *socket, GSocketEventFlags event, +void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags, GSocketCallback callback, char *cdata) { int count; @@ -703,22 +801,19 @@ void GSocket_SetCallback(GSocket *socket, GSocketEventFlags event, for (count = 0; count < GSOCK_MAX_EVENT; count++) { - /* We test each flag and enable the corresponding events */ - if ((event & (1 << count)) != 0) + if ((flags & (1 << count)) != 0) { socket->m_cbacks[count] = callback; socket->m_data[count] = cdata; } } - - _GSocket_Configure_Callbacks(socket); } /* GSocket_UnsetCallback: - * Disables all callbacks specified by 'event', which may be a + * Disables all callbacks specified by 'flags', which may be a * combination of flags OR'ed toghether. */ -void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags event) +void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags) { int count = 0; @@ -726,41 +821,47 @@ void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags event) for (count = 0; count < GSOCK_MAX_EVENT; count++) { - /* We test each flag and disable the corresponding events */ - if ((event & (1 << count)) != 0) + if ((flags & (1 << count)) != 0) { socket->m_cbacks[count] = NULL; + socket->m_data[count] = NULL; } } - - _GSocket_Configure_Callbacks(socket); } /* Internals */ -void _GSocket_Configure_Callbacks(GSocket *socket) +/* _GSocket_Enable_Events: + * We enable all event notifications here (we need to be notified + * of all events for internal processing) but we will only notify + * users when an appropiate callback function has been installed. + */ +void _GSocket_Enable_Events(GSocket *socket) { - long mask = 0; - int count; + assert (socket != NULL); - for (count = 0; count < GSOCK_MAX_EVENT; count++) + if (socket->m_fd != INVALID_SOCKET) { - if (socket->m_cbacks[count] != NULL) - { - switch (count) - { - case GSOCK_INPUT: mask |= FD_READ; break; - case GSOCK_OUTPUT: mask |= FD_WRITE; break; - case GSOCK_CONNECTION: mask |= (FD_ACCEPT | FD_CONNECT); break; - case GSOCK_LOST: mask |= FD_CLOSE; break; - } - } + WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, + FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE); } +} + +/* _GSocket_Disable_Events: + * Disable event notifications (when shutdowning the socket) + */ +void _GSocket_Disable_Events(GSocket *socket) +{ + assert (socket != NULL); - WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, mask); + if (socket->m_fd != INVALID_SOCKET) + { + WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0); + } } + LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, @@ -769,6 +870,7 @@ LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, GSocket *socket; GSocketEvent event; GSocketCallback cback; + char *data; if (uMsg >= WM_USER && uMsg <= (WM_USER + MAXSOCKETS - 1)) { @@ -776,6 +878,7 @@ LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, socket = socketList[(uMsg - WM_USER)]; event = -1; cback = NULL; + data = NULL; /* Check that the socket still exists (it has not been * destroyed) and for safety, check that the m_fd field @@ -788,12 +891,27 @@ LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, case FD_READ: event = GSOCK_INPUT; break; case FD_WRITE: event = GSOCK_OUTPUT; break; case FD_ACCEPT: event = GSOCK_CONNECTION; break; - case FD_CONNECT: event = GSOCK_CONNECTION; break; + case FD_CONNECT: + { + if (WSAGETSELECTERROR(lParam) != 0) + event = GSOCK_LOST; + else + event = GSOCK_CONNECTION; + break; + } case FD_CLOSE: event = GSOCK_LOST; break; } if (event != -1) + { cback = socket->m_cbacks[event]; + data = socket->m_data[event]; + + if (event == GSOCK_LOST) + socket->m_detected = GSOCK_LOST_FLAG; + else + socket->m_detected |= (1 << event); + } } /* OK, we can now leave the critical section because we have @@ -803,7 +921,7 @@ LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, LeaveCriticalSection(&critical); if (cback != NULL) - (cback)(socket, event, socket->m_data[event]); + (cback)(socket, event, data); return (LRESULT) 0; } @@ -820,7 +938,7 @@ GSocketError _GSocket_Input_Timeout(GSocket *socket) { fd_set readfds; - if (socket->m_non_blocking == FALSE) + if (!socket->m_non_blocking) { FD_ZERO(&readfds); FD_SET(socket->m_fd, &readfds); @@ -841,7 +959,7 @@ GSocketError _GSocket_Output_Timeout(GSocket *socket) { fd_set writefds; - if (socket->m_non_blocking == FALSE) + if (!socket->m_non_blocking) { FD_ZERO(&writefds); FD_SET(socket->m_fd, &writefds); @@ -856,42 +974,20 @@ GSocketError _GSocket_Output_Timeout(GSocket *socket) int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size) { - int ret; - - ret = recv(socket->m_fd, buffer, size, 0); - - if (ret == SOCKET_ERROR) - { - if (WSAGetLastError() != WSAEWOULDBLOCK) - socket->m_error = GSOCK_IOERR; - else - socket->m_error = GSOCK_WOULDBLOCK; - - return -1; - } - - return ret; + return recv(socket->m_fd, buffer, size, 0); } int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size) { struct sockaddr from; - SOCKLEN_T fromlen; + SOCKLEN_T fromlen = sizeof(from); int ret; - - fromlen = sizeof(from); + GSocketError err; ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen); if (ret == SOCKET_ERROR) - { - if (WSAGetLastError() != WSAEWOULDBLOCK) - socket->m_error = GSOCK_IOERR; - else - socket->m_error = GSOCK_WOULDBLOCK; - - return -1; - } + return SOCKET_ERROR; /* Translate a system address into a GSocket address */ if (!socket->m_peer) @@ -903,10 +999,12 @@ int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size) return -1; } } - if (_GAddress_translate_from(socket->m_peer, &from, fromlen) != GSOCK_NOERROR) + err = _GAddress_translate_from(socket->m_peer, &from, fromlen); + if (err != GSOCK_NOERROR) { - socket->m_error = GSOCK_MEMERR; /* TODO: bug in Unix GSocket! */ - GAddress_destroy(socket->m_peer); /* TODO: bug in Unix GSocket! */ + GAddress_destroy(socket->m_peer); + socket->m_peer = NULL; + socket->m_error = err; return -1; } @@ -915,26 +1013,14 @@ int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size) int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size) { - int ret; - - ret = send(socket->m_fd, buffer, size, 0); - - if (ret == SOCKET_ERROR) - { - if (WSAGetLastError() != WSAEWOULDBLOCK) - socket->m_error = GSOCK_IOERR; - else - socket->m_error = GSOCK_WOULDBLOCK; - - return -1; - } - return ret; + return send(socket->m_fd, buffer, size, 0); } int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size) { struct sockaddr *addr; int len, ret; + GSocketError err; if (!socket->m_peer) { @@ -942,9 +1028,10 @@ int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size) return -1; } - if (!_GAddress_translate_to(socket->m_peer, &addr, &len)) + err = _GAddress_translate_to(socket->m_peer, &addr, &len); + if (err != GSOCK_NOERROR) { - socket->m_error = GSOCK_MEMERR; + socket->m_error = err; return -1; } @@ -953,15 +1040,6 @@ int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size) /* Frees memory allocated by _GAddress_translate_to */ free(addr); - if (ret == SOCKET_ERROR) - { - if (WSAGetLastError() != WSAEWOULDBLOCK) - socket->m_error = GSOCK_IOERR; - else - socket->m_error = GSOCK_WOULDBLOCK; - - return -1; - } return ret; } @@ -1117,6 +1195,7 @@ GSocketError _GAddress_translate_to(GAddress *address, GSocketError _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) { @@ -1124,11 +1203,10 @@ GSocketError _GAddress_Init_INET(GAddress *address) return GSOCK_MEMERR; } - address->m_len = sizeof(struct sockaddr_in); address->m_family = GSOCK_INET; address->m_realfamily = PF_INET; ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET; - ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY; + ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_NONE; return GSOCK_NOERROR; } @@ -1145,7 +1223,7 @@ GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname) 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) { @@ -1192,7 +1270,7 @@ GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port, address->m_error = GSOCK_INVPORT; return GSOCK_INVOP; } - + se = getservbyname(port, protocol); if (!se) { @@ -1202,7 +1280,7 @@ GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port, port_int = atoi(port); addr = (struct sockaddr_in *)address->m_addr; - addr->sin_port = htons(port_int); + addr->sin_port = htons((u_short) port_int); return GSOCK_NOERROR; } @@ -1222,7 +1300,7 @@ GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port) assert(address != NULL); CHECK_ADDRESS(address, INET, GSOCK_INVADDR); - + addr = (struct sockaddr_in *)address->m_addr; addr->sin_port = htons(port); @@ -1235,7 +1313,7 @@ GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t char *addr_buf; struct sockaddr_in *addr; - assert(address != NULL); + assert(address != NULL); CHECK_ADDRESS(address, INET, GSOCK_INVADDR); addr = (struct sockaddr_in *)address->m_addr; @@ -1257,8 +1335,8 @@ unsigned long GAddress_INET_GetHostAddress(GAddress *address) { struct sockaddr_in *addr; - assert(address != NULL); - CHECK_ADDRESS(address, INET, 0); + assert(address != NULL); + CHECK_ADDRESS(address, INET, 0); addr = (struct sockaddr_in *)address->m_addr; @@ -1269,8 +1347,8 @@ unsigned short GAddress_INET_GetPort(GAddress *address) { struct sockaddr_in *addr; - assert(address != NULL); - CHECK_ADDRESS(address, INET, 0); + assert(address != NULL); + CHECK_ADDRESS(address, INET, 0); addr = (struct sockaddr_in *)address->m_addr; return ntohs(addr->sin_port); @@ -1303,10 +1381,15 @@ GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf) return GSOCK_INVADDR; } +#else /* !wxUSE_SOCKETS */ -#endif /* !defined(__WXMSW__) || (defined(__WXMSW__) && wxUSE_SOCKETS) */ - +/* + * translation unit shouldn't be empty, so include this typedef to make the + * compiler (VC++ 6.0, for example) happy + */ +typedef (*wxDummy)(); +#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */ /* Diferencias con la version Unix: * - El descriptor es SOCKET y no int @@ -1316,9 +1399,7 @@ GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf) * - inet_addr en lugar de inet_aton * - Codigo de inicializacion y terminacion para inicializar y * terminar WinSocket y para la ventana interna. - * - SetTimeout en la version MSW simplemente guarda el valor en - * socket.m_timeout, por tanto no hay necesidad de llamar a - * SetTimeout cada vez que se crea realmente un socket (no - * un gsocket). - * - Lo mismo para SetNonBlocking. + * - SetTimeout, SetNonBlocking y la implementacion de los + * timeouts eran bastante diferentes, pero ahora se han + * hecho en la version Unix igual que en esta. */