[PATCH 5/7] dpwsockx: Implementation of Reply and Send callbacks
Ismael Barros
razielmine at gmail.com
Mon Aug 31 18:50:50 CDT 2009
Implemented auxiliar functions to send TCP and UDP messages
---
dlls/dpwsockx/dpwsockx_dll.h | 6 ++
dlls/dpwsockx/dpwsockx_main.c | 196 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 198 insertions(+), 4 deletions(-)
diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h
index 2ad5844..15cd188 100644
--- a/dlls/dpwsockx/dpwsockx_dll.h
+++ b/dlls/dpwsockx/dpwsockx_dll.h
@@ -59,6 +59,12 @@ typedef struct tagDPWS_DATA
LPDIRECTPLAYSP lpISP;
} DPWS_DATA, *LPDPWS_DATA;
+typedef struct tagDPWS_PLAYER_DATA
+{
+ SOCKADDR_IN tcpAddr;
+ SOCKADDR_IN udpAddr;
+} DPWS_PLAYER_DATA, *LPDPWS_PLAYER_DATA;
+
typedef struct tagDPSP_MSG_HEADER
{
DWORD size; /* size & 0x000FFFFF, token & 0xFFF00000 */
diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c
index dc0171b..30d71d2 100644
--- a/dlls/dpwsockx/dpwsockx_main.c
+++ b/dlls/dpwsockx/dpwsockx_main.c
@@ -298,6 +298,120 @@ static HRESULT start_listener( LPDPWS_DATA dpwsData, BOOL is_tcp )
}
+static HRESULT send_udp_message( LPVOID message,
+ DWORD messageSize,
+ LPSOCKADDR destAddr )
+{
+ SOCKET sock;
+ int ret;
+
+ TRACE( "Sending message to %s:%d\n",
+ inet_ntoa(((LPSOCKADDR_IN) destAddr)->sin_addr),
+ ntohs(((LPSOCKADDR_IN) destAddr)->sin_port) );
+
+ if ( messageSize > DPWS_MAXBUFFERSIZE )
+ {
+ return DPERR_SENDTOOBIG;
+ }
+
+ sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+ if ( sock == INVALID_SOCKET )
+ {
+ ERR( "socket() failed: %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+
+ if ( ((LPSOCKADDR_IN)destAddr)->sin_addr.s_addr == htonl(INADDR_BROADCAST) )
+ {
+ /* Allow the socket to send broadcast messages */
+ BOOL allowBroadcast = TRUE;
+ ret = setsockopt( sock, SOL_SOCKET, SO_BROADCAST,
+ (char*) &allowBroadcast, sizeof(BOOL) );
+ if ( ret == SOCKET_ERROR )
+ {
+ ERR( "setsockopt() failed: %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+ }
+
+ /* Send message */
+ ret = sendto( sock, message, messageSize, 0, destAddr, sizeof(SOCKADDR) );
+ if ( ret == SOCKET_ERROR )
+ {
+ ERR( "sendto() failed: %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+ else if ( ret != messageSize )
+ {
+ ERR( "%d/%d bytes sent", ret, messageSize );
+ return DPERR_GENERIC;
+ }
+
+ return DP_OK;
+}
+
+static HRESULT send_tcp_message( LPVOID message,
+ DWORD messageSize,
+ LPSOCKADDR destAddr )
+{
+ SOCKET sock;
+ int ret;
+
+ /* TODO:
+ * For each message sent, we open a TCP socket, send the message and
+ * close the socket. The desired behaviour would be to open a socket
+ * only if there's no socket for the requesting address, and keep
+ * sending messages with that socket, without closing it. */
+
+ TRACE( "Sending message to %s:%d\n",
+ inet_ntoa(((LPSOCKADDR_IN) destAddr)->sin_addr),
+ ntohs(((LPSOCKADDR_IN) destAddr)->sin_port) );
+
+ if ( messageSize > DPWS_GUARANTEED_MAXBUFFERSIZE )
+ {
+ return DPERR_SENDTOOBIG;
+ }
+
+ sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
+ if ( sock == INVALID_SOCKET )
+ {
+ ERR( "socket() failed: %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+
+ ret = connect( sock, destAddr, sizeof(SOCKADDR) );
+ if ( ret == SOCKET_ERROR )
+ {
+ if ( WSAGetLastError() != WSAEISCONN )
+ {
+ ERR( "connect() failed: %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+ }
+
+ ret = send( sock, message, messageSize, 0 );
+ if ( ret == SOCKET_ERROR )
+ {
+ ERR( "send() failed: %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+ else if ( ret != messageSize )
+ {
+ ERR( "%d/%d bytes sent", ret, messageSize );
+ return DPERR_GENERIC;
+ }
+
+ ret = closesocket( sock );
+ if ( ret == SOCKET_ERROR)
+ {
+ ERR( "closesocket() failed %d\n", WSAGetLastError() );
+ return DPERR_GENERIC;
+ }
+
+ return DP_OK;
+}
+
+
static HRESULT WINAPI DPWSCB_EnumSessions( LPDPSP_ENUMSESSIONSDATA data )
{
FIXME( "(%p,%d,%p,%u) stub\n",
@@ -308,19 +422,93 @@ static HRESULT WINAPI DPWSCB_EnumSessions( LPDPSP_ENUMSESSIONSDATA data )
static HRESULT WINAPI DPWSCB_Reply( LPDPSP_REPLYDATA data )
{
- FIXME( "(%p,%p,%d,%d,%p) stub\n",
+ LPDPWS_DATA dpwsData;
+ DWORD dwDataSize;
+ SOCKADDR_IN destAddr;
+
+ TRACE( "(%p,%p,%d,%d,%p)\n",
data->lpSPMessageHeader, data->lpMessage, data->dwMessageSize,
data->idNameServer, data->lpISP );
- return DPERR_UNSUPPORTED;
+
+ IDirectPlaySP_GetSPData( data->lpISP, (LPVOID*) &dpwsData, &dwDataSize,
+ DPGET_LOCAL );
+
+ /* Extract destination address from request header */
+ destAddr = ((LPDPSP_MSG_HEADER) data->lpSPMessageHeader)->SockAddr;
+
+ /* Add header to message body */
+ ((LPDPSP_MSG_HEADER) data->lpMessage)->size
+ = data->dwMessageSize | DPSP_MSG_TOKEN_REMOTE;
+ ((LPDPSP_MSG_HEADER) data->lpMessage)->SockAddr
+ = dpwsData->tcp_listener.addr;
+
+ return send_tcp_message( data->lpMessage, data->dwMessageSize,
+ (LPSOCKADDR) &destAddr );
}
static HRESULT WINAPI DPWSCB_Send( LPDPSP_SENDDATA data )
{
- FIXME( "(0x%08x,%d,%d,%p,%d,%u,%p) stub\n",
+ LPDPWS_DATA dpwsData;
+ LPDPWS_PLAYER_DATA dpwsPlayerData;
+ DWORD dwDataSize, dwPlayerDataSize;
+ SOCKADDR_IN destAddr;
+
+ TRACE( "(0x%08x,0x%08x,0x%08x,%p,%d,%u,%p)\n",
data->dwFlags, data->idPlayerTo, data->idPlayerFrom,
data->lpMessage, data->dwMessageSize,
data->bSystemMessage, data->lpISP );
- return DPERR_UNSUPPORTED;
+
+ IDirectPlaySP_GetSPData( data->lpISP, (LPVOID*) &dpwsData, &dwDataSize,
+ DPGET_LOCAL );
+
+ /* Get destination address from the player id */
+ if ( data->idPlayerTo == 0 ) /* Message to nameserver */
+ {
+ destAddr = dpwsData->nameserverAddr;
+ }
+ else
+ {
+ HRESULT hr;
+ hr = IDirectPlaySP_GetSPPlayerData( data->lpISP, data->idPlayerTo,
+ (LPVOID*) &dpwsPlayerData,
+ &dwPlayerDataSize, DPGET_REMOTE );
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+
+ if ( ( data->bSystemMessage ) ||
+ ( data->dwFlags & DPSEND_GUARANTEED ) )
+ {
+ destAddr = dpwsPlayerData->tcpAddr;
+ }
+ else
+ {
+ destAddr = dpwsPlayerData->udpAddr;
+ }
+ }
+
+ /* Add header to message body */
+ ((LPDPSP_MSG_HEADER) data->lpMessage)->size
+ = data->dwMessageSize | DPSP_MSG_TOKEN_REMOTE;
+ ((LPDPSP_MSG_HEADER) data->lpMessage)->SockAddr
+ = dpwsData->tcp_listener.addr;
+
+ /* If the flag DPSESSION_DIRECTPLAYPROTOCOL is set we are
+ * supposed to send UDP messages and implement all the TCP
+ * functionality ourselves in dplayx, but for now let's not
+ * reinvent the wheel. */
+ if ( ( data->bSystemMessage ) ||
+ ( data->dwFlags & DPSEND_GUARANTEED ) )
+ {
+ return send_tcp_message( data->lpMessage, data->dwMessageSize,
+ (LPSOCKADDR) &destAddr );
+ }
+ else
+ {
+ return send_udp_message( data->lpMessage, data->dwMessageSize,
+ (LPSOCKADDR) &destAddr );
+ }
}
static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data )
--
1.6.4.1
More information about the wine-patches
mailing list