// (C) 1999-2000, Guillermo Rodriguez Garcia
// (C) 2008 Vadim Zeitlin
// RCS_ID: $Id$
-// License: wxWindows licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#endif
#include "wx/private/socket.h"
+#include "wx/msw/private.h" // for wxGetInstance()
+#include "wx/private/fd.h"
#include "wx/apptrait.h"
-
-extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance();
-#define INSTANCE wxGetInstance()
-
-#include <winsock.h>
-
-#if defined(__CYGWIN__)
- //CYGWIN gives annoying warning about runtime stuff if we don't do this
-# define USE_SYS_TYPES_FD_SET
-# include <sys/types.h>
-#endif
+#include "wx/thread.h"
+#include "wx/dynlib.h"
+#include "wx/link.h"
#ifdef __WXWINCE__
/*
# pragma warning(default:4115) /* named type definition in parentheses */
#endif
-#define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
+#include "wx/msw/private/hiddenwin.h"
-/* implemented in utils.cpp */
-extern "C" WXDLLIMPEXP_BASE HWND
-wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
+#define CLASSNAME TEXT("_wxSocket_Internal_Window_Class")
/* Maximum number of different wxSocket objects at a given time.
* This value can be modified at will, but it CANNOT be greater
#endif
#ifndef __WXWINCE__
-typedef int (PASCAL *WSAAsyncSelectFunc)(SOCKET,HWND,u_int,long);
+typedef int (PASCAL *WSAAsyncSelect_t)(SOCKET,HWND,u_int,long);
#else
/* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
*/
long lNetworkEvents;
int iErrorCode[10];
} WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;
-typedef HANDLE (PASCAL *WSACreateEventFunc)();
-typedef int (PASCAL *WSAEventSelectFunc)(SOCKET,HANDLE,long);
-typedef int (PASCAL *WSAWaitForMultipleEventsFunc)(long,HANDLE,BOOL,long,BOOL);
-typedef int (PASCAL *WSAEnumNetworkEventsFunc)(SOCKET,HANDLE,LPWSANETWORKEVENTS);
+typedef HANDLE (PASCAL *WSACreateEvent_t)();
+typedef int (PASCAL *WSAEventSelect_t)(SOCKET,HANDLE,long);
+typedef int (PASCAL *WSAWaitForMultipleEvents_t)(long,HANDLE,BOOL,long,BOOL);
+typedef int (PASCAL *WSAEnumNetworkEvents_t)(SOCKET,HANDLE,LPWSANETWORKEVENTS);
#endif //__WXWINCE__
LRESULT CALLBACK wxSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM);
/* Global variables */
static HWND hWin;
-static CRITICAL_SECTION critical;
+wxCRIT_SECT_DECLARE_MEMBER(gs_critical);
static wxSocketImplMSW *socketList[MAXSOCKETS];
static int firstAvailable;
#ifndef __WXWINCE__
-static WSAAsyncSelectFunc gs_WSAAsyncSelect = NULL;
+static WSAAsyncSelect_t gs_WSAAsyncSelect = NULL;
#else
static SocketHash socketHash;
static unsigned int currSocket;
HANDLE hThread[MAXSOCKETS];
-static WSACreateEventFunc gs_WSACreateEvent = NULL;
-static WSAEventSelectFunc gs_WSAEventSelect = NULL;
-static WSAWaitForMultipleEventsFunc gs_WSAWaitForMultipleEvents = NULL;
-static WSAEnumNetworkEventsFunc gs_WSAEnumNetworkEvents = NULL;
+static WSACreateEvent_t gs_WSACreateEvent = NULL;
+static WSAEventSelect_t gs_WSAEventSelect = NULL;
+static WSAWaitForMultipleEvents_t gs_WSAWaitForMultipleEvents = NULL;
+static WSAEnumNetworkEvents_t gs_WSAEnumNetworkEvents = NULL;
/* This structure will be used to pass data on to the thread that handles socket events.
*/
typedef struct thread_data{
}thread_data;
#endif
-static HMODULE gs_wsock32dll = 0;
-
-
#ifdef __WXWINCE__
-/* This thread handles socket events on WinCE using WSAEventSelect() as WSAAsyncSelect is not supported.
-* When an event occures for the socket, it is checked what kind of event happend and the correct message gets posted
-* so that the hidden window can handle it as it would in other MSW builds.
+/* This thread handles socket events on WinCE using WSAEventSelect() as
+ * WSAAsyncSelect is not supported. When an event occurs for the socket, it is
+ * checked what kind of event happened and the correct message gets posted so
+ * that the hidden window can handle it as it would in other MSW builds.
*/
DWORD WINAPI SocketThread(LPVOID data)
{
{
return new wxSocketImplMSW(wxsocket);
}
- virtual void Install_Callback(wxSocketImpl *socket, wxSocketNotify event);
- virtual void Uninstall_Callback(wxSocketImpl *socket, wxSocketNotify event);
+ virtual void Install_Callback(wxSocketImpl *socket,
+ wxSocketNotify event = wxSOCKET_LOST);
+ virtual void Uninstall_Callback(wxSocketImpl *socket,
+ wxSocketNotify event = wxSOCKET_LOST);
+
+private:
+ static wxDynamicLibrary gs_wsock32dll;
};
-/* Global initializers */
+wxDynamicLibrary wxSocketMSWManager::gs_wsock32dll;
bool wxSocketMSWManager::OnInit()
{
return false;
/* Initialize socket list */
- InitializeCriticalSection(&critical);
-
for (i = 0; i < MAXSOCKETS; i++)
{
socketList[i] = NULL;
}
firstAvailable = 0;
- /* Load WSAAsyncSelect from wsock32.dll (we don't link against it
- statically to avoid dependency on wsock32.dll for apps that don't use
- sockets): */
+ // we don't link with wsock32.dll (or ws2 in CE case) statically to avoid
+ // dependencies on it for all the application using wx even if they don't use
+ // sockets
+#ifdef __WXWINCE__
+ #define WINSOCK_DLL_NAME wxT("ws2.dll")
+#else
+ #define WINSOCK_DLL_NAME wxT("wsock32.dll")
+#endif
+
+ gs_wsock32dll.Load(WINSOCK_DLL_NAME, wxDL_VERBATIM | wxDL_QUIET);
+ if ( !gs_wsock32dll.IsLoaded() )
+ return false;
+
#ifndef __WXWINCE__
- gs_wsock32dll = LoadLibrary(wxT("wsock32.dll"));
- if (!gs_wsock32dll)
- return false;
- gs_WSAAsyncSelect =(WSAAsyncSelectFunc)GetProcAddress(gs_wsock32dll,
- "WSAAsyncSelect");
- if (!gs_WSAAsyncSelect)
- return false;
+ wxDL_INIT_FUNC(gs_, WSAAsyncSelect, gs_wsock32dll);
+ if ( !gs_WSAAsyncSelect )
+ return false;
#else
-/* On WinCE we load ws2.dll which will provide the needed functions.
-*/
- gs_wsock32dll = LoadLibrary(wxT("ws2.dll"));
- if (!gs_wsock32dll)
- return false;
- gs_WSAEventSelect =(WSAEventSelectFunc)GetProcAddress(gs_wsock32dll,
- wxT("WSAEventSelect"));
- if (!gs_WSAEventSelect)
- return false;
+ wxDL_INIT_FUNC(gs_, WSAEventSelect, gs_wsock32dll);
+ if ( !gs_WSAEventSelect )
+ return false;
- gs_WSACreateEvent =(WSACreateEventFunc)GetProcAddress(gs_wsock32dll,
- wxT("WSACreateEvent"));
- if (!gs_WSACreateEvent)
- return false;
+ wxDL_INIT_FUNC(gs_, WSACreateEvent, gs_wsock32dll);
+ if ( !gs_WSACreateEvent )
+ return false;
- gs_WSAWaitForMultipleEvents =(WSAWaitForMultipleEventsFunc)GetProcAddress(gs_wsock32dll,
- wxT("WSAWaitForMultipleEvents"));
- if (!gs_WSAWaitForMultipleEvents)
- return false;
+ wxDL_INIT_FUNC(gs_, WSAWaitForMultipleEvents, gs_wsock32dll);
+ if ( !gs_WSAWaitForMultipleEvents )
+ return false;
- gs_WSAEnumNetworkEvents =(WSAEnumNetworkEventsFunc)GetProcAddress(gs_wsock32dll,
- wxT("WSAEnumNetworkEvents"));
- if (!gs_WSAEnumNetworkEvents)
- return false;
+ wxDL_INIT_FUNC(gs_, WSAEnumNetworkEvents, gs_wsock32dll);
+ if ( !gs_WSAEnumNetworkEvents )
+ return false;
- currSocket = 0;
-#endif
+ currSocket = 0;
+#endif // !__WXWINCE__/__WXWINCE__
// finally initialize WinSock
WSADATA wsaData;
#endif
/* Destroy internal window */
DestroyWindow(hWin);
- UnregisterClass(CLASSNAME, INSTANCE);
-
- /* Unlock wsock32.dll */
- if (gs_wsock32dll)
- {
- FreeLibrary(gs_wsock32dll);
- gs_wsock32dll = 0;
- }
-
- /* Delete critical section */
- DeleteCriticalSection(&critical);
+ UnregisterClass(CLASSNAME, wxGetInstance());
WSACleanup();
+
+ gs_wsock32dll.Unload();
}
/* Per-socket GUI initialization / cleanup */
: wxSocketImpl(wxsocket)
{
/* Allocate a new message number for this socket */
- EnterCriticalSection(&critical);
+ wxCRIT_SECT_LOCKER(lock, gs_critical);
int i = firstAvailable;
while (socketList[i] != NULL)
if (i == firstAvailable) /* abort! */
{
- LeaveCriticalSection(&critical);
m_msgnumber = 0; // invalid
return;
}
socketList[i] = this;
firstAvailable = (i + 1) % MAXSOCKETS;
m_msgnumber = (i + WM_USER);
-
- LeaveCriticalSection(&critical);
}
wxSocketImplMSW::~wxSocketImplMSW()
{
/* Remove the socket from the list */
- EnterCriticalSection(&critical);
+ wxCRIT_SECT_LOCKER(lock, gs_critical);
if ( m_msgnumber )
{
socketList[m_msgnumber - WM_USER] = NULL;
}
//else: the socket has never been created successfully
-
- LeaveCriticalSection(&critical);
}
/* Windows proc for asynchronous event handling */
WPARAM wParam,
LPARAM lParam)
{
- wxSocketImplMSW *socket;
- wxSocketNotify event;
+ if ( uMsg < WM_USER || uMsg > (WM_USER + MAXSOCKETS - 1))
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
- if (uMsg >= WM_USER && uMsg <= (WM_USER + MAXSOCKETS - 1))
- {
- EnterCriticalSection(&critical);
- socket = socketList[(uMsg - WM_USER)];
- event = (wxSocketNotify) -1;
-
- /* Check that the socket still exists (it has not been
- * destroyed) and for safety, check that the m_fd field
- * is what we expect it to be.
- */
- if ((socket != NULL) && ((WPARAM)socket->m_fd == wParam))
+ wxSocketImplMSW *socket;
+ wxSocketNotify event = (wxSocketNotify)-1;
{
- switch WSAGETSELECTEVENT(lParam)
- {
- case FD_READ: event = wxSOCKET_INPUT; break;
- case FD_WRITE: event = wxSOCKET_OUTPUT; break;
- case FD_ACCEPT: event = wxSOCKET_CONNECTION; break;
- case FD_CONNECT:
+ wxCRIT_SECT_LOCKER(lock, gs_critical);
+
+ socket = socketList[(uMsg - WM_USER)];
+ if ( !socket )
+ return 0;
+
+ // the socket may be already closed but we could still receive
+ // notifications for it sent (asynchronously) before it got closed
+ if ( socket->m_fd == INVALID_SOCKET )
+ return 0;
+
+ wxASSERT_MSG( socket->m_fd == (SOCKET)wParam,
+ "mismatch between message and socket?" );
+
+ switch ( WSAGETSELECTEVENT(lParam) )
{
- if (WSAGETSELECTERROR(lParam) != 0)
- event = wxSOCKET_LOST;
- else
- event = wxSOCKET_CONNECTION;
- break;
+ case FD_READ:
+ // We may get a FD_READ notification even when there is no data
+ // to read on the socket, in particular this happens on socket
+ // creation when we seem to always get FD_CONNECT, FD_WRITE and
+ // FD_READ notifications all at once (but it doesn't happen
+ // only then). Ignore such dummy notifications.
+ {
+ fd_set fds;
+ timeval tv = { 0, 0 };
+
+ wxFD_ZERO(&fds);
+ wxFD_SET(socket->m_fd, &fds);
+
+ if ( select(socket->m_fd + 1, &fds, NULL, NULL, &tv) != 1 )
+ return 0;
+ }
+
+ event = wxSOCKET_INPUT;
+ break;
+
+ case FD_WRITE:
+ event = wxSOCKET_OUTPUT;
+ break;
+
+ case FD_ACCEPT:
+ event = wxSOCKET_CONNECTION;
+ break;
+
+ case FD_CONNECT:
+ event = WSAGETSELECTERROR(lParam) ? wxSOCKET_LOST
+ : wxSOCKET_CONNECTION;
+ break;
+
+ case FD_CLOSE:
+ event = wxSOCKET_LOST;
+ break;
+
+ default:
+ wxFAIL_MSG( "unexpected socket notification" );
+ return 0;
}
- case FD_CLOSE: event = wxSOCKET_LOST; break;
- }
-
- if (event != -1)
- {
- if (event == wxSOCKET_LOST)
- socket->m_detected = wxSOCKET_LOST_FLAG;
- else
- socket->m_detected |= (1 << event);
- }
- }
-
- LeaveCriticalSection(&critical);
+ } // unlock gs_critical
- if ( socket )
- socket->NotifyOnStateChange(event);
+ socket->NotifyOnStateChange(event);
- return (LRESULT) 0;
- }
- else
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ return 0;
}
/*
* Disable event notifications (used when shutting down the socket)
*/
void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl *socket_,
- wxSocketNotify WXUNUSED(event))
+ wxSocketNotify WXUNUSED(event))
{
wxSocketImplMSW * const socket = static_cast<wxSocketImplMSW *>(socket_);
}
} gs_managerSetter;
+// see the relative linker macro in socket.cpp
+wxFORCE_LINK_THIS_MODULE( mswsocket );
+
// ============================================================================
// wxSocketImpl implementation
// ============================================================================
-/* static */
-wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
-{
- return new wxSocketImplMSW(wxsocket);
-}
-
void wxSocketImplMSW::DoClose()
{
- wxSocketManager::Get()->
- Uninstall_Callback(this, wxSOCKET_MAX_EVENT /* unused anyhow */);
+ wxSocketManager::Get()->Uninstall_Callback(this);
closesocket(m_fd);
}
-/*
- * 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;
- 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 (Input_Timeout() == wxSOCKET_TIMEDOUT)
- {
- delete connection;
- /* m_error set by Input_Timeout */
- 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)
+wxSocketError wxSocketImplMSW::GetLastError() const
{
- // TODO: review this
- if (ret == SOCKET_ERROR)
+ switch ( WSAGetLastError() )
{
- int err = WSAGetLastError();
-
- /* If connect failed with EWOULDBLOCK and the wxSocketImpl object
- * is in blocking mode, we select() for the specified timeout
- * checking for writability to see if the connection request
- * completes.
- */
- if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
- {
- err = Connect_Timeout();
-
- if (err != wxSOCKET_NOERROR)
- {
- Close();
- /* m_error is set in Connect_Timeout */
- }
+ case 0:
+ return wxSOCKET_NOERROR;
- return (wxSocketError) err;
- }
+ case WSAENOTSOCK:
+ return wxSOCKET_INVSOCK;
- /* 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;
+ case WSAEWOULDBLOCK:
return wxSOCKET_WOULDBLOCK;
- }
- /* If connect failed with an error other than EWOULDBLOCK,
- * then the call to Connect() has failed.
- */
- Close();
- m_error = wxSOCKET_IOERR;
- return wxSOCKET_IOERR;
+ default:
+ 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;
-}
-
-wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
-{
- return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
-}
-
-wxSocketError GAddress_INET_SetAnyAddress(GAddress *address)
-{
- return GAddress_INET_SetHostAddress(address, INADDR_ANY);
-}
-
-wxSocketError GAddress_INET_SetHostAddress(GAddress *address,
- unsigned long hostaddr)
-{
- struct in_addr *addr;
-
- CHECK_ADDRESS(address, INET);
-
- addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
- addr->s_addr = htonl(hostaddr);
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
- const char *protocol)
-{
- struct servent *se;
- struct sockaddr_in *addr;
-
- CHECK_ADDRESS(address, INET);
-
- if (!port)
- {
- address->m_error = wxSOCKET_INVPORT;
- return wxSOCKET_INVPORT;
- }
-
- se = getservbyname(port, protocol);
- if (!se)
- {
- if (isdigit(port[0]))
- {
- int port_int;
-
- port_int = atoi(port);
- addr = (struct sockaddr_in *)address->m_addr;
- addr->sin_port = htons((u_short) port_int);
- return wxSOCKET_NOERROR;
- }
-
- address->m_error = wxSOCKET_INVPORT;
- return wxSOCKET_INVPORT;
- }
-
- addr = (struct sockaddr_in *)address->m_addr;
- addr->sin_port = se->s_port;
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
-{
- struct sockaddr_in *addr;
-
- CHECK_ADDRESS(address, INET);
-
- addr = (struct sockaddr_in *)address->m_addr;
- addr->sin_port = htons(port);
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
-{
- struct hostent *he;
- char *addr_buf;
- struct sockaddr_in *addr;
-
- CHECK_ADDRESS(address, INET);
-
- addr = (struct sockaddr_in *)address->m_addr;
- addr_buf = (char *)&(addr->sin_addr);
-
- he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
- if (he == NULL)
- {
- address->m_error = wxSOCKET_NOHOST;
- return wxSOCKET_NOHOST;
- }
-
- strncpy(hostname, he->h_name, sbuf);
-
- return wxSOCKET_NOERROR;
-}
-
-unsigned long GAddress_INET_GetHostAddress(GAddress *address)
-{
- struct sockaddr_in *addr;
-
- CHECK_ADDRESS_RETVAL(address, INET, 0);
-
- addr = (struct sockaddr_in *)address->m_addr;
-
- return ntohl(addr->sin_addr.s_addr);
-}
-
-unsigned short GAddress_INET_GetPort(GAddress *address)
-{
- struct sockaddr_in *addr;
-
- CHECK_ADDRESS_RETVAL(address, INET, 0);
-
- addr = (struct sockaddr_in *)address->m_addr;
- return ntohs(addr->sin_port);
-}
-
-
-#if wxUSE_IPV6
-/*
- * -------------------------------------------------------------------------
- * Internet IPv6 address family
- * -------------------------------------------------------------------------
- */
-#include "ws2tcpip.h"
-
-#ifdef __VISUALC__
- #pragma comment(lib,"ws2_32")
-#endif // __VISUALC__
-
-wxSocketError _GAddress_Init_INET6(GAddress *address)
-{
- struct in6_addr any_address = IN6ADDR_ANY_INIT;
- address->m_len = sizeof(struct sockaddr_in6);
- address->m_addr = (struct sockaddr *) malloc(address->m_len);
- if (address->m_addr == NULL)
- {
- address->m_error = wxSOCKET_MEMERR;
- return wxSOCKET_MEMERR;
- }
- memset(address->m_addr,0,address->m_len);
-
- address->m_family = wxSOCKET_INET6;
- address->m_realfamily = AF_INET6;
- ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6;
- ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address;
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname)
-{
- CHECK_ADDRESS(address, INET6);
-
- addrinfo hints;
- memset( & hints, 0, sizeof( hints ) );
- hints.ai_family = AF_INET6;
- addrinfo * info = 0;
- if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info )
- {
- address->m_error = wxSOCKET_NOHOST;
- return wxSOCKET_NOHOST;
- }
-
- memcpy( address->m_addr, info->ai_addr, info->ai_addrlen );
- freeaddrinfo( info );
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address)
-{
- CHECK_ADDRESS(address, INET6);
-
- struct in6_addr addr;
- memset( & addr, 0, sizeof( addr ) );
- return GAddress_INET6_SetHostAddress(address, addr);
-}
-wxSocketError GAddress_INET6_SetHostAddress(GAddress *address,
- struct in6_addr hostaddr)
-{
- CHECK_ADDRESS(address, INET6);
-
- ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr;
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port,
- const char *protocol)
-{
- struct servent *se;
- struct sockaddr_in6 *addr;
-
- CHECK_ADDRESS(address, INET6);
-
- if (!port)
- {
- address->m_error = wxSOCKET_INVPORT;
- return wxSOCKET_INVPORT;
- }
-
- se = getservbyname(port, protocol);
- if (!se)
- {
- if (isdigit((unsigned char) port[0]))
- {
- int port_int;
-
- port_int = atoi(port);
- addr = (struct sockaddr_in6 *)address->m_addr;
- addr->sin6_port = htons((u_short) port_int);
- return wxSOCKET_NOERROR;
- }
-
- address->m_error = wxSOCKET_INVPORT;
- return wxSOCKET_INVPORT;
- }
-
- addr = (struct sockaddr_in6 *)address->m_addr;
- addr->sin6_port = se->s_port;
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port)
-{
- struct sockaddr_in6 *addr;
-
- CHECK_ADDRESS(address, INET6);
-
- addr = (struct sockaddr_in6 *)address->m_addr;
- addr->sin6_port = htons(port);
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf)
-{
- struct hostent *he;
- char *addr_buf;
- struct sockaddr_in6 *addr;
-
- CHECK_ADDRESS(address, INET6);
-
- addr = (struct sockaddr_in6 *)address->m_addr;
- addr_buf = (char *)&(addr->sin6_addr);
-
- he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6);
- if (he == NULL)
- {
- address->m_error = wxSOCKET_NOHOST;
- return wxSOCKET_NOHOST;
- }
-
- strncpy(hostname, he->h_name, sbuf);
-
- return wxSOCKET_NOERROR;
-}
-
-wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr)
-{
- CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR);
- *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr;
- return wxSOCKET_NOERROR;
-}
-
-unsigned short GAddress_INET6_GetPort(GAddress *address)
-{
- CHECK_ADDRESS_RETVAL(address, INET6, 0);
-
- return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port );
-}
-
-#endif // wxUSE_IPV6
-
-/*
- * -------------------------------------------------------------------------
- * Unix address family
- * -------------------------------------------------------------------------
- */
-
-wxSocketError _GAddress_Init_UNIX(GAddress *address)
-{
- address->m_error = wxSOCKET_INVADDR;
- return wxSOCKET_INVADDR;
-}
-
-wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
-{
- address->m_error = wxSOCKET_INVADDR;
- return wxSOCKET_INVADDR;
-}
-
-wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
-{
- address->m_error = wxSOCKET_INVADDR;
- return wxSOCKET_INVADDR;
}
#endif // wxUSE_SOCKETS