From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index c9428aafead..2e4cffc3295 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1868,6 +1868,29 @@ static unsigned short receiveGuaranteedGameMessage_( int line, SOCKET sock, DPID return port; }
+#define receiveGameMessage( sock, expectedFromId, expectedToId, expectedData, expectedDataSize ) \ + receiveGameMessage_( __LINE__, sock, expectedFromId, expectedToId, expectedData, expectedDataSize ) +static void receiveGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPID expectedToId, void *expectedData, + DWORD expectedDataSize ) +{ + struct + { + GameMessage request; + BYTE data[ 256 ]; + } request; + int wsResult; + + DWORD expectedSize = sizeof( request.request ) + expectedDataSize; + + wsResult = receiveMessage_( line, sock, &request, expectedSize ); + todo_wine ok_( __FILE__, line )( wsResult == expectedSize, "recv() returned %d.\n", wsResult ); + if ( wsResult == SOCKET_ERROR ) + return; + + checkGameMessage_( line, &request.request, expectedFromId, expectedToId ); + ok_( __FILE__, line )( !memcmp( &request.data, expectedData, expectedDataSize ), "message data didn't match.\n" ); +} + #define sendGuaranteedGameMessage( sock, port, fromId, toId, data, dataSize ) \ sendGuaranteedGameMessage_( __LINE__, sock, port, fromId, toId, data, dataSize ) static void sendGuaranteedGameMessage_( int line, SOCKET sock, unsigned short port, DPID fromId, DPID toId, void *data, @@ -7693,6 +7716,7 @@ static void test_Send(void) IDirectPlay4 *dp; SOCKET sendSock; SOCKET recvSock; + SOCKET udpSock; HRESULT hr; DPID dpid;
@@ -7741,9 +7765,18 @@ static void test_Send(void) ok( dpid == 0x14, "got destination id %#lx.\n", dpid ); receiveGuaranteedGameMessage( recvSock, 0x07734, DPID_ALLPLAYERS, data, sizeof( data ) );
+ udpSock = bindUdp( 2399 ); + + hr = IDirectPlayX_Send( dp, 0x07734, 0x1337, 0, data, sizeof( data ) ); + todo_wine ok( hr == DP_OK, "got hr %#lx.\n", hr ); + + receiveGameMessage( udpSock, 0x07734, 0x1337, data, sizeof( data ) ); + checkNoMorePlayerMessages( dp ); + checkNoMoreMessages( udpSock ); checkNoMoreMessages( recvSock );
+ closesocket( udpSock ); closesocket( recvSock ); closesocket( sendSock );
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 10 +- dlls/dpwsockx/dpwsockx_dll.h | 11 +- dlls/dpwsockx/dpwsockx_main.c | 201 ++++++++++++++++++++++++---------- 3 files changed, 155 insertions(+), 67 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 2e4cffc3295..6c535c97cb8 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1148,8 +1148,8 @@ static void checkSpData_( int line, SpData *spData ) ok_( __FILE__, line )( !spData->tcpAddr.sin_addr.s_addr, "got TCP address %#lx.\n", spData->tcpAddr.sin_addr.s_addr ); ok_( __FILE__, line )( spData->udpAddr.sin_family == AF_INET, "got UDP family %d.\n", spData->udpAddr.sin_family ); - todo_wine ok_( __FILE__, line )( 2350 <= ntohs( spData->udpAddr.sin_port ) && ntohs( spData->udpAddr.sin_port ) < 2400, - "got UDP port %d.\n", ntohs( spData->udpAddr.sin_port ) ); + ok_( __FILE__, line )( 2350 <= ntohs( spData->udpAddr.sin_port ) && ntohs( spData->udpAddr.sin_port ) < 2400, + "got UDP port %d.\n", ntohs( spData->udpAddr.sin_port ) ); ok_( __FILE__, line )( !spData->udpAddr.sin_addr.s_addr, "got UDP address %#lx.\n", spData->udpAddr.sin_addr.s_addr ); } @@ -1883,9 +1883,7 @@ static void receiveGameMessage_( int line, SOCKET sock, DPID expectedFromId, DPI DWORD expectedSize = sizeof( request.request ) + expectedDataSize;
wsResult = receiveMessage_( line, sock, &request, expectedSize ); - todo_wine ok_( __FILE__, line )( wsResult == expectedSize, "recv() returned %d.\n", wsResult ); - if ( wsResult == SOCKET_ERROR ) - return; + ok_( __FILE__, line )( wsResult == expectedSize, "recv() returned %d.\n", wsResult );
checkGameMessage_( line, &request.request, expectedFromId, expectedToId ); ok_( __FILE__, line )( !memcmp( &request.data, expectedData, expectedDataSize ), "message data didn't match.\n" ); @@ -7768,7 +7766,7 @@ static void test_Send(void) udpSock = bindUdp( 2399 );
hr = IDirectPlayX_Send( dp, 0x07734, 0x1337, 0, data, sizeof( data ) ); - todo_wine ok( hr == DP_OK, "got hr %#lx.\n", hr ); + ok( hr == DP_OK, "got hr %#lx.\n", hr );
receiveGameMessage( udpSock, 0x07734, 0x1337, data, sizeof( data ) );
diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index 8e83247460d..1e1ff3bac99 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -74,10 +74,16 @@ struct tagDPWS_IN_CONNECTION IDirectPlaySP *sp; };
+typedef struct +{ + SOCKADDR_IN addr; + BOOL guaranteed; +} DPWS_CONNECTION_KEY; + typedef struct { struct rb_entry entry; - SOCKADDR_IN addr; + DPWS_CONNECTION_KEY key;
SOCKET tcpSock; WSAOVERLAPPED overlapped; @@ -106,6 +112,9 @@ typedef struct tagDPWS_DATA WSAEVENT acceptEvent; struct list inConnections;
+ SOCKET udpSock; + SOCKADDR_IN udpAddr; + CRITICAL_SECTION sendCs; DPWS_PLAYER nameserver; DPWS_CONNECTION_REF nameserverConnectionRef; diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index 678706a79cd..b4995c91ef0 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -33,22 +33,29 @@ WINE_DEFAULT_DEBUG_CHANNEL(dplay); #define DPWS_PORT 47624 #define DPWS_START_TCP_PORT 2300 #define DPWS_END_TCP_PORT 2350 +#define DPWS_START_UDP_PORT 2350 +#define DPWS_END_UDP_PORT 2400
static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection );
static int DPWS_CompareConnections( const void *key, const struct rb_entry *entry ) { DPWS_OUT_CONNECTION *connection = RB_ENTRY_VALUE( entry, DPWS_OUT_CONNECTION, entry ); - SOCKADDR_IN *addr = (SOCKADDR_IN *)key; + DPWS_CONNECTION_KEY *connection_key = (DPWS_CONNECTION_KEY *)key;
- if ( addr->sin_port < connection->addr.sin_port ) + if ( connection_key->addr.sin_port < connection->key.addr.sin_port ) return -1; - if ( addr->sin_port > connection->addr.sin_port ) + if ( connection_key->addr.sin_port > connection->key.addr.sin_port ) return 1;
- if ( addr->sin_addr.s_addr < connection->addr.sin_addr.s_addr ) + if ( connection_key->addr.sin_addr.s_addr < connection->key.addr.sin_addr.s_addr ) return -1; - if ( addr->sin_addr.s_addr > connection->addr.sin_addr.s_addr ) + if ( connection_key->addr.sin_addr.s_addr > connection->key.addr.sin_addr.s_addr ) + return 1; + + if ( connection_key->guaranteed < connection->key.guaranteed ) + return -1; + if ( connection_key->guaranteed > connection->key.guaranteed ) return 1;
return 0; @@ -344,6 +351,25 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData )
list_init( &dpwsData->inConnections );
+ dpwsData->udpSock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + if ( dpwsData->udpSock == INVALID_SOCKET ) + { + ERR( "socket() failed\n" ); + WSACloseEvent( dpwsData->acceptEvent ); + closesocket( dpwsData->tcpSock ); + return DPERR_UNAVAILABLE; + } + + hr = DPWS_BindToFreePort( dpwsData->udpSock, &dpwsData->udpAddr, DPWS_START_UDP_PORT, + DPWS_END_UDP_PORT ); + if ( FAILED( hr ) ) + { + closesocket( dpwsData->udpSock ); + WSACloseEvent( dpwsData->acceptEvent ); + closesocket( dpwsData->tcpSock ); + return hr; + } + rb_init( &dpwsData->connections, DPWS_CompareConnections );
dpwsData->stopEvent = WSACreateEvent(); @@ -510,7 +536,7 @@ static HRESULT WINAPI DPWSCB_AddPlayerToGroup( DPSP_ADDPLAYERTOGROUPDATA *data )
RB_FOR_EACH_ENTRY( playerConnectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) { - entry = rb_get( &group->connectionRefs, &playerConnectionRef->connection->addr ); + entry = rb_get( &group->connectionRefs, &playerConnectionRef->connection->key ); if ( entry ) { groupConnectionRef = RB_ENTRY_VALUE( entry, DPWS_CONNECTION_REF, entry ); @@ -522,7 +548,7 @@ static HRESULT WINAPI DPWSCB_AddPlayerToGroup( DPSP_ADDPLAYERTOGROUPDATA *data ) return DPERR_OUTOFMEMORY; groupConnectionRef->ref = 1; groupConnectionRef->connection = playerConnectionRef->connection; - rb_put( &group->connectionRefs, &groupConnectionRef->connection->addr, + rb_put( &group->connectionRefs, &groupConnectionRef->connection->key, &groupConnectionRef->entry ); }
@@ -554,12 +580,16 @@ static HRESULT WINAPI DPWSCB_CreateGroup( DPSP_CREATEGROUPDATA *data ) return DP_OK; }
-static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, +static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, BOOL guaranteed, DPWS_OUT_CONNECTION **connection ) { + DPWS_CONNECTION_KEY key; struct rb_entry *entry;
- entry = rb_get( &dpwsData->connections, addr ); + key.addr = *addr; + key.guaranteed = guaranteed; + + entry = rb_get( &dpwsData->connections, &key ); if ( entry ) { *connection = RB_ENTRY_VALUE( entry, DPWS_OUT_CONNECTION, entry ); @@ -570,10 +600,10 @@ static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, if ( !*connection ) return DPERR_OUTOFMEMORY;
- (*connection)->addr = *addr; + (*connection)->key = key; (*connection)->tcpSock = INVALID_SOCKET;
- rb_put( &dpwsData->connections, &(*connection)->addr, &(*connection)->entry ); + rb_put( &dpwsData->connections, &(*connection)->key, &(*connection)->entry );
return DP_OK; } @@ -581,6 +611,7 @@ static HRESULT DPWS_GetConnection( DPWS_DATA *dpwsData, SOCKADDR_IN *addr, static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data ) { DPWS_CONNECTION_REF *tcpConnectionRef; + DPWS_CONNECTION_REF *udpConnectionRef; DPWS_PLAYER playerPlaceholder = { 0 }; DPWS_PLAYERDATA *playerData; DWORD playerDataSize; @@ -628,6 +659,7 @@ static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data ) playerData->tcpAddr.sin_family = AF_INET; playerData->tcpAddr.sin_port = dpwsData->tcpAddr.sin_port; playerData->udpAddr.sin_family = AF_INET; + playerData->udpAddr.sin_port = dpwsData->udpAddr.sin_port; }
hr = IDirectPlaySP_SetSPPlayerData( data->lpISP, data->idPlayer, (void *) &playerPlaceholder, @@ -654,16 +686,35 @@ static HRESULT WINAPI DPWSCB_CreatePlayer( LPDPSP_CREATEPLAYERDATA data )
tcpConnectionRef->ref = 1;
- hr = DPWS_GetConnection( dpwsData, &playerData->tcpAddr, &tcpConnectionRef->connection ); + hr = DPWS_GetConnection( dpwsData, &playerData->tcpAddr, TRUE, &tcpConnectionRef->connection ); + if ( FAILED( hr ) ) + { + free( tcpConnectionRef ); + free( player ); + return hr; + } + + udpConnectionRef = calloc( 1, sizeof( DPWS_CONNECTION_REF ) ); + if ( !udpConnectionRef ) + { + free( tcpConnectionRef ); + free( player ); + return DPERR_OUTOFMEMORY; + } + + udpConnectionRef->ref = 1; + + hr = DPWS_GetConnection( dpwsData, &playerData->udpAddr, FALSE, &udpConnectionRef->connection ); if ( FAILED( hr ) ) { + free( udpConnectionRef ); free( tcpConnectionRef ); free( player ); return hr; }
- rb_put( &player->connectionRefs, &tcpConnectionRef->connection->addr, - &tcpConnectionRef->entry ); + rb_put( &player->connectionRefs, &tcpConnectionRef->connection->key, &tcpConnectionRef->entry ); + rb_put( &player->connectionRefs, &udpConnectionRef->connection->key, &udpConnectionRef->entry );
return DP_OK; } @@ -790,13 +841,13 @@ static HRESULT WINAPI DPWSCB_Open( LPDPSP_OPENDATA data )
rb_init( &dpwsData->nameserver.connectionRefs, DPWS_CompareConnectionRefs );
- hr = DPWS_GetConnection( dpwsData, &nameserverAddr, + hr = DPWS_GetConnection( dpwsData, &nameserverAddr, TRUE, &dpwsData->nameserverConnectionRef.connection ); if ( FAILED( hr ) ) return hr;
rb_put( &dpwsData->nameserver.connectionRefs, - &dpwsData->nameserverConnectionRef.connection->addr, + &dpwsData->nameserverConnectionRef.connection->key, &dpwsData->nameserverConnectionRef.entry );
return DP_OK; @@ -827,7 +878,7 @@ static HRESULT WINAPI DPWSCB_RemovePlayerFromGroup( DPSP_REMOVEPLAYERFROMGROUPDA
RB_FOR_EACH_ENTRY( playerConnectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) { - entry = rb_get( &group->connectionRefs, &playerConnectionRef->connection->addr ); + entry = rb_get( &group->connectionRefs, &playerConnectionRef->connection->key ); if ( !entry ) continue; groupConnectionRef = RB_ENTRY_VALUE( entry, DPWS_CONNECTION_REF, entry ); @@ -885,79 +936,113 @@ static HRESULT WINAPI DPWSCB_GetAddressChoices( LPDPSP_GETADDRESSCHOICESDATA dat }
static HRESULT DPWS_SendImpl( DPWS_DATA *dpwsData, DPWS_PLAYER *player, SGBUFFER *buffers, - DWORD bufferCount, DWORD messageSize ) + DWORD bufferCount, DWORD messageSize, BOOL guaranteed, BOOL system ) { DPWS_CONNECTION_REF *connectionRef; DPSP_MSG_HEADER header = { 0 }; HRESULT sendResult;
- header.mixed = DPSP_MSG_MAKE_MIXED( messageSize, DPSP_MSG_TOKEN_REMOTE ); - header.SockAddr.sin_family = AF_INET; - header.SockAddr.sin_port = dpwsData->tcpAddr.sin_port; + if ( guaranteed || system ) + { + header.mixed = DPSP_MSG_MAKE_MIXED( messageSize, DPSP_MSG_TOKEN_REMOTE ); + header.SockAddr.sin_family = AF_INET; + header.SockAddr.sin_port = dpwsData->tcpAddr.sin_port;
- buffers[ 0 ].pData = (unsigned char *) &header; + buffers[ 0 ].pData = (unsigned char *) &header; + }
EnterCriticalSection( &dpwsData->sendCs );
- RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + if ( guaranteed ) { - DPWS_OUT_CONNECTION *connection = connectionRef->connection; + RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) + { + DPWS_OUT_CONNECTION *connection = connectionRef->connection;
- if ( connection->tcpSock != INVALID_SOCKET ) - continue; + if ( !connection->key.guaranteed ) + continue; + if ( connection->tcpSock != INVALID_SOCKET ) + continue;
- connection->tcpSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if ( connection->tcpSock == INVALID_SOCKET ) - { - ERR( "socket() failed\n" ); - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_UNAVAILABLE; - } + connection->tcpSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if ( connection->tcpSock == INVALID_SOCKET ) + { + ERR( "socket() failed\n" ); + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + }
- if ( SOCKET_ERROR == connect( connection->tcpSock, (SOCKADDR *) &connection->addr, - sizeof( connection->addr ) ) ) - { - ERR( "connect() failed\n" ); - closesocket( connection->tcpSock ); - connection->tcpSock = INVALID_SOCKET; - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_UNAVAILABLE; + if ( SOCKET_ERROR == connect( connection->tcpSock, (SOCKADDR *) &connection->key.addr, + sizeof( connection->key.addr ) ) ) + { + ERR( "connect() failed\n" ); + closesocket( connection->tcpSock ); + connection->tcpSock = INVALID_SOCKET; + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + } } }
+ sendResult = DP_OK; + RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) { DPWS_OUT_CONNECTION *connection = connectionRef->connection; DWORD transferred;
- if ( SOCKET_ERROR == WSASend( connection->tcpSock, (WSABUF *) buffers, bufferCount, - &transferred, 0, &connection->overlapped, NULL ) ) + if ( connection->key.guaranteed != guaranteed ) + continue; + + if ( guaranteed ) { - if ( WSAGetLastError() != WSA_IO_PENDING ) + if ( SOCKET_ERROR == WSASend( connection->tcpSock, (WSABUF *) buffers, bufferCount, + &transferred, 0, &connection->overlapped, NULL ) ) { - ERR( "WSASend() failed\n" ); - LeaveCriticalSection( &dpwsData->sendCs ); - return DPERR_UNAVAILABLE; + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSASend() failed\n" ); + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + } + } + } + else + { + if ( SOCKET_ERROR == WSASendTo( dpwsData->udpSock, (WSABUF *) buffers, bufferCount, + &transferred, 0, (SOCKADDR *) &connection->key.addr, + sizeof( connection->key.addr ), &connection->overlapped, + NULL ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSASendTo() failed\n" ); + LeaveCriticalSection( &dpwsData->sendCs ); + return DPERR_UNAVAILABLE; + } } } }
- sendResult = DP_OK; - RB_FOR_EACH_ENTRY( connectionRef, &player->connectionRefs, DPWS_CONNECTION_REF, entry ) { DPWS_OUT_CONNECTION *connection = connectionRef->connection; DWORD transferred; + SOCKET sock; + + if ( connection->key.guaranteed != guaranteed ) + continue; + + sock = guaranteed ? connection->tcpSock : dpwsData->udpSock;
- if ( !WSAGetOverlappedResult( connection->tcpSock, &connection->overlapped, &transferred, - TRUE, NULL ) ) + if ( !WSAGetOverlappedResult( sock, &connection->overlapped, &transferred, TRUE, NULL ) ) { ERR( "WSAGetOverlappedResult() failed\n" ); sendResult = DPERR_UNAVAILABLE; continue; }
- if ( transferred < messageSize ) + if ( guaranteed && transferred < messageSize ) { ERR( "lost connection\n" ); closesocket( connection->tcpSock ); @@ -985,12 +1070,6 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) data->dwPriority, data->dwTimeout, data->lpDPContext, data->lpdwSPMsgID, data->bSystemMessage );
- if ( !( data->dwFlags & DPSEND_GUARANTEED ) ) - { - FIXME( "non-guaranteed delivery is not yet supported\n" ); - return DPERR_UNSUPPORTED; - } - if ( data->dwFlags & DPSEND_ASYNC ) { FIXME("asynchronous send is not yet supported\n"); @@ -1015,7 +1094,8 @@ static HRESULT WINAPI DPWSCB_SendEx( LPDPSP_SENDEXDATA data ) }
return DPWS_SendImpl( dpwsData, player, data->lpSendBuffers, data->cBuffers, - data->dwMessageSize ); + data->dwMessageSize, !!( data->dwFlags & DPSEND_GUARANTEED ), + data->bSystemMessage ); }
static HRESULT WINAPI DPWSCB_SendToGroupEx( LPDPSP_SENDTOGROUPEXDATA data ) @@ -1047,7 +1127,8 @@ static HRESULT WINAPI DPWSCB_SendToGroupEx( LPDPSP_SENDTOGROUPEXDATA data ) if ( FAILED( hr ) ) return hr;
- return DPWS_SendImpl( dpwsData, group, data->lpSendBuffers, data->cBuffers, data->dwMessageSize ); + return DPWS_SendImpl( dpwsData, group, data->lpSendBuffers, data->cBuffers, data->dwMessageSize, + !!( data->dwFlags & DPSEND_GUARANTEED ), FALSE ); }
static HRESULT WINAPI DPWSCB_Cancel( LPDPSP_CANCELDATA data )
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 109 +++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 17 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 6c535c97cb8..5ddb7e3a5e8 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1081,6 +1081,25 @@ static SOCKET connectTcp_( int line, unsigned short port ) return sock; }
+#define connectUdp( port ) connectUdp_( __LINE__, port) +static SOCKET connectUdp_( int line, unsigned short port ) +{ + SOCKADDR_IN addr; + int wsResult; + SOCKET sock; + + sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); + ok_( __FILE__, line)( sock != INVALID_SOCKET, "got send socket %#Ix.\n", sock ); + + addr.sin_family = AF_INET; + addr.sin_port = htons( port ); + addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); + wsResult = connect( sock, (SOCKADDR *) &addr, sizeof( addr ) ); + ok_( __FILE__, line)( !wsResult, "connect returned %d.\n", wsResult ); + + return sock; +} + #define receiveMessage( sock, buffer, size ) receiveMessage_( __LINE__, sock, buffer, size ) static int receiveMessage_( int line, SOCKET sock, void *buffer, int size ) { @@ -1139,8 +1158,8 @@ static void checkMessageHeader_( int line, MessageHeader *header, WORD expectedC ok_( __FILE__, line )( header->command == expectedCommand, "got command %d.\n", header->command ); }
-#define checkSpData( spData ) checkSpData_( __LINE__, spData ) -static void checkSpData_( int line, SpData *spData ) +#define checkSpData( spData ) checkSpData_( __LINE__, spData, udpPort ) +static void checkSpData_( int line, SpData *spData, unsigned short *udpPort ) { ok_( __FILE__, line )( spData->tcpAddr.sin_family == AF_INET, "got TCP family %d.\n", spData->tcpAddr.sin_family ); ok_( __FILE__, line )( 2300 <= ntohs( spData->tcpAddr.sin_port ) && ntohs( spData->tcpAddr.sin_port ) < 2350, @@ -1152,6 +1171,9 @@ static void checkSpData_( int line, SpData *spData ) "got UDP port %d.\n", ntohs( spData->udpAddr.sin_port ) ); ok_( __FILE__, line )( !spData->udpAddr.sin_addr.s_addr, "got UDP address %#lx.\n", spData->udpAddr.sin_addr.s_addr ); + + if ( udpPort ) + *udpPort = ntohs( spData->udpAddr.sin_port ); }
#define checkPackedPlayer( player, expectedFlags, expectedId, expectedShortNameLength, expectedLongNameLength, \ @@ -1339,10 +1361,11 @@ static void sendRequestPlayerReply_( int line, SOCKET sock, unsigned short port, ok_( __FILE__, line )( wsResult == sizeof( reply ), "send() returned %d.\n", wsResult ); }
-#define receiveAddForwardRequest( sock, expectedPlayerId, expectedPassword, expectedTickCount ) \ - receiveAddForwardRequest_( __LINE__, sock, expectedPlayerId, expectedPassword, expectedTickCount ) +#define receiveAddForwardRequest( sock, expectedPlayerId, expectedPassword, expectedTickCount, udpPort ) \ + receiveAddForwardRequest_( __LINE__, sock, expectedPlayerId, expectedPassword, expectedTickCount, udpPort ) static unsigned short receiveAddForwardRequest_( int line, SOCKET sock, DPID expectedPlayerId, - const WCHAR *expectedPassword, DWORD expectedTickCount ) + const WCHAR *expectedPassword, DWORD expectedTickCount, + unsigned short *udpPort ) { struct { @@ -1375,7 +1398,7 @@ static unsigned short receiveAddForwardRequest_( int line, SOCKET sock, DPID exp ok_( __FILE__, line )( request.request.passwordOffset == 108, "got password offset %lu.\n", request.request.passwordOffset ); checkPackedPlayer_( line, &request.request.playerInfo, 0x9, expectedPlayerId, 0, 0, 0, expectedPlayerId ); - checkSpData_( line, &request.request.spData ); + checkSpData_( line, &request.request.spData, udpPort );
wsResult = receiveMessage_( line, sock, password, expectedPasswordSize );
@@ -1716,7 +1739,7 @@ static unsigned short receiveCreatePlayer_( int line, SOCKET sock, DPID expected
wsResult = receiveMessage_( line, sock, &spData, sizeof( spData ) ); ok_( __FILE__, line )( wsResult == sizeof( spData ), "recv() returned %d.\n", wsResult ); - checkSpData_( line, &spData ); + checkSpData_( line, &spData, NULL );
if ( expectedPlayerDataSize ) { @@ -1924,6 +1947,33 @@ static void sendGuaranteedGameMessage_( int line, SOCKET sock, unsigned short po ok_( __FILE__, line )( wsResult == dataSize, "send() returned %d.\n", wsResult ); }
+#define sendGameMessage( sock, fromId, toId, data, dataSize ) \ + sendGameMessage_( __LINE__, sock, fromId, toId, data, dataSize ) +static void sendGameMessage_( int line, SOCKET sock, DPID fromId, DPID toId, void *data, DWORD dataSize ) +{ + struct + { + GameMessage request; + BYTE data[ 256 ]; + } request = + { + .request = + { + .fromId = fromId, + .toId = toId, + } + }; + int wsResult; + DWORD size; + + size = sizeof( request.request ) + dataSize; + + memcpy( request.data, data, dataSize ); + + wsResult = send( sock, (char *) &request, size, 0 ); + ok_( __FILE__, line )( wsResult == size, "send() returned %d.\n", wsResult ); +} + static void init_TCPIP_provider( IDirectPlay4 *pDP, LPCSTR strIPAddressString, WORD port ) {
@@ -2775,7 +2825,7 @@ static void check_Open_( int line, IDirectPlay4A *dp, DPSESSIONDESC2 *dpsd, cons
if ( forwardRequestExpected ) { - receiveAddForwardRequest_( line, recvSock, 0x12345678, expectedPassword, serverDpsd->dwReserved1 ); + receiveAddForwardRequest_( line, recvSock, 0x12345678, expectedPassword, serverDpsd->dwReserved1, NULL );
if ( addForwardReplyHr == DP_OK ) sendSuperEnumPlayersReply_( line, sendSock, listenPort, 2399, serverDpsd, L"normal" ); @@ -3127,10 +3177,10 @@ static void test_interactive_Open(void)
}
-#define joinSession( dp, dpsd, serverDpsd, sendSock, recvSock ) \ - joinSession_( __LINE__, dp, dpsd, serverDpsd, sendSock, recvSock ) +#define joinSession( dp, dpsd, serverDpsd, sendSock, recvSock, udpPort ) \ + joinSession_( __LINE__, dp, dpsd, serverDpsd, sendSock, recvSock, udpPort ) static void joinSession_( int line, IDirectPlay4 *dp, DPSESSIONDESC2 *dpsd, DPSESSIONDESC2 *serverDpsd, - SOCKET *sendSock, SOCKET *recvSock ) + SOCKET *sendSock, SOCKET *recvSock, unsigned short *udpPort ) { EnumSessionsParam *enumSessionsParam; OpenParam *openParam; @@ -3174,7 +3224,7 @@ static void joinSession_( int line, IDirectPlay4 *dp, DPSESSIONDESC2 *dpsd, DPSE
receiveRequestPlayerId_( line, *recvSock, 0x9 ); sendRequestPlayerReply_( line, *sendSock, 2349, 0x12345678, DP_OK ); - receiveAddForwardRequest_( line, *recvSock, 0x12345678, L"", serverDpsd->dwReserved1 ); + receiveAddForwardRequest_( line, *recvSock, 0x12345678, L"", serverDpsd->dwReserved1, udpPort ); sendSuperEnumPlayersReply_( line, *sendSock, 2349, 2399, serverDpsd, L"normal" ); checkNoMoreMessages_( line, *recvSock );
@@ -3213,7 +3263,7 @@ static void test_ADDFORWARD(void)
init_TCPIP_provider( dp, "127.0.0.1", 0 );
- joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); + joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, NULL );
sendAddForward( sendSock, 2349, 2348, 2398 ); receiveAddForwardAck( recvSock, 0x07734 ); @@ -4526,7 +4576,7 @@ static void test_CreatePlayer(void) NULL, NULL, 0 );
/* Join to normal session */ - joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); + joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, NULL );
/* Player name */ dpid = 0xdeadbeef; @@ -4789,7 +4839,7 @@ static void test_CREATEPLAYER(void)
init_TCPIP_provider( dp, "127.0.0.1", 0 );
- joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); + joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, NULL );
createPlayer( dp, 0x11223344, event, NULL, 0, 0, sendSock, recvSock );
@@ -7729,7 +7779,7 @@ static void test_Send(void) hr = IDirectPlayX_Send( dp, 0x07734, 0x1337, DPSEND_GUARANTEED, data, sizeof( data ) ); ok( hr == DPERR_INVALIDPLAYER, "got hr %#lx.\n", hr );
- joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); + joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, NULL );
createPlayer( dp, 0x07734, NULL, NULL, 0, 0, sendSock, recvSock ); createPlayer( dp, 0x14, NULL, NULL, 0, 0, sendSock, recvSock ); @@ -8134,6 +8184,7 @@ static void test_Receive(void) }; BYTE data0[] = { 1, 2, 3, 4, 5, 6, 7, 8, }; BYTE data1[] = { 4, 3, 2, 1, }; + unsigned short udpPort; BYTE msgData[ 256 ]; DWORD msgDataSize; DPID fromId, toId; @@ -8141,6 +8192,7 @@ static void test_Receive(void) IDirectPlay4 *dp; SOCKET sendSock; SOCKET recvSock; + SOCKET udpSock; HANDLE event0; HANDLE event1; HRESULT hr; @@ -8161,7 +8213,7 @@ static void test_Receive(void) hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); ok( hr == DPERR_NOMESSAGES, "got hr %#lx.\n", hr );
- joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock ); + joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, &udpPort );
createPlayer( dp, 0x07734, event0, NULL, 0, 0, sendSock, recvSock ); createPlayer( dp, 0x14, event1, NULL, 0, 0, sendSock, recvSock ); @@ -8312,6 +8364,29 @@ static void test_Receive(void) hr = IDirectPlayX_Receive( dp, &fromId, &toId, DPRECEIVE_TOPLAYER, msgData, &msgDataSize ); ok( hr == DPERR_NOMESSAGES, "got hr %#lx.\n", hr );
+ udpSock = connectUdp( udpPort ); + + sendGameMessage( udpSock, 0x1337, 0x07734, data0, sizeof( data0 ) ); + + waitResult = WaitForSingleObject( event0, 2000 ); + todo_wine ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult ); + + fromId = 0xdeadbeef; + toId = 0xdeadbeef; + memset( msgData, 0xcc, sizeof( msgData ) ); + msgDataSize = sizeof( msgData ); + hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); + todo_wine ok( hr == DP_OK, "got hr %#lx.\n", hr ); + todo_wine ok( fromId == 0x1337, "got source id %#lx.\n", fromId ); + todo_wine ok( toId == 0x07734, "got destination id %#lx.\n", toId ); + todo_wine ok( !memcmp( msgData, data0, sizeof( data0 ) ), "message data didn't match.\n" ); + todo_wine ok( msgDataSize == sizeof( data0 ), "got message size %lu.\n", msgDataSize ); + + msgDataSize = sizeof( msgData ); + hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); + ok( hr == DPERR_NOMESSAGES, "got hr %#lx.\n", hr ); + + closesocket( udpSock ); closesocket( recvSock ); closesocket( sendSock );
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 12 +++--- dlls/dpwsockx/dpwsockx_dll.h | 3 ++ dlls/dpwsockx/dpwsockx_main.c | 76 +++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 6 deletions(-)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 5ddb7e3a5e8..e5606b99540 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -8369,18 +8369,18 @@ static void test_Receive(void) sendGameMessage( udpSock, 0x1337, 0x07734, data0, sizeof( data0 ) );
waitResult = WaitForSingleObject( event0, 2000 ); - todo_wine ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult ); + ok( waitResult == WAIT_OBJECT_0, "message wait returned %lu\n", waitResult );
fromId = 0xdeadbeef; toId = 0xdeadbeef; memset( msgData, 0xcc, sizeof( msgData ) ); msgDataSize = sizeof( msgData ); hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); - todo_wine ok( hr == DP_OK, "got hr %#lx.\n", hr ); - todo_wine ok( fromId == 0x1337, "got source id %#lx.\n", fromId ); - todo_wine ok( toId == 0x07734, "got destination id %#lx.\n", toId ); - todo_wine ok( !memcmp( msgData, data0, sizeof( data0 ) ), "message data didn't match.\n" ); - todo_wine ok( msgDataSize == sizeof( data0 ), "got message size %lu.\n", msgDataSize ); + ok( hr == DP_OK, "got hr %#lx.\n", hr ); + ok( fromId == 0x1337, "got source id %#lx.\n", fromId ); + ok( toId == 0x07734, "got destination id %#lx.\n", toId ); + ok( !memcmp( msgData, data0, sizeof( data0 ) ), "message data didn't match.\n" ); + ok( msgDataSize == sizeof( data0 ), "got message size %lu.\n", msgDataSize );
msgDataSize = sizeof( msgData ); hr = IDirectPlayX_Receive( dp, &fromId, &toId, 0, msgData, &msgDataSize ); diff --git a/dlls/dpwsockx/dpwsockx_dll.h b/dlls/dpwsockx/dpwsockx_dll.h index 1e1ff3bac99..bf0fda78aa1 100644 --- a/dlls/dpwsockx/dpwsockx_dll.h +++ b/dlls/dpwsockx/dpwsockx_dll.h @@ -114,6 +114,9 @@ typedef struct tagDPWS_DATA
SOCKET udpSock; SOCKADDR_IN udpAddr; + WSAOVERLAPPED overlapped; + WSABUF wsaBuffer; + char buffer[ 65536 ];
CRITICAL_SECTION sendCs; DPWS_PLAYER nameserver; diff --git a/dlls/dpwsockx/dpwsockx_main.c b/dlls/dpwsockx/dpwsockx_main.c index b4995c91ef0..6bfa70e916b 100644 --- a/dlls/dpwsockx/dpwsockx_main.c +++ b/dlls/dpwsockx/dpwsockx_main.c @@ -231,12 +231,81 @@ static void DPWS_MessageBodyReceiveCompleted( DPWS_IN_CONNECTION *connection ) } }
+static void WINAPI DPWS_UdpReceiveCompleted( DWORD error, DWORD transferred, + WSAOVERLAPPED *overlapped, DWORD flags ) +{ + DPWS_DATA *dpwsData = (DPWS_DATA *)overlapped->hEvent; + DPSP_MSG_HEADER *header; + int messageBodySize; + char *messageBody; + + if ( error != ERROR_SUCCESS ) + { + ERR( "WSARecv() failed\n" ); + return; + } + + messageBody = dpwsData->buffer; + messageBodySize = transferred; + header = NULL; + + if ( transferred >= sizeof( DPSP_MSG_HEADER ) + sizeof( DWORD ) ) + { + DWORD signature = *(DWORD *)&dpwsData->buffer[ sizeof( DPSP_MSG_HEADER ) ]; + if ( signature == 0x79616c70 ) + { + int messageSize; + + header = (DPSP_MSG_HEADER *)dpwsData->buffer; + messageSize = DPSP_MSG_SIZE( header->mixed ); + + if ( messageSize < sizeof( DPSP_MSG_HEADER )) + { + ERR( "message is too short: %d\n", messageSize ); + return; + } + if ( messageSize > transferred ) + { + ERR( "truncated message\n" ); + return; + } + + messageBody = dpwsData->buffer + sizeof( DPSP_MSG_HEADER ); + messageBodySize = messageSize - sizeof( DPSP_MSG_HEADER ); + } + } + + IDirectPlaySP_HandleMessage( dpwsData->lpISP, messageBody, messageBodySize, header ); + + if ( SOCKET_ERROR == WSARecv( dpwsData->udpSock, &dpwsData->wsaBuffer, 1, &transferred, &flags, + &dpwsData->overlapped, DPWS_UdpReceiveCompleted ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSARecv() failed\n" ); + return; + } + } +} + static DWORD WINAPI DPWS_ThreadProc( void *param ) { DPWS_DATA *dpwsData = (DPWS_DATA *)param; + DWORD transferred; + DWORD flags = 0;
SetThreadDescription( GetCurrentThread(), L"dpwsockx" );
+ if ( SOCKET_ERROR == WSARecv( dpwsData->udpSock, &dpwsData->wsaBuffer, 1, &transferred, &flags, + &dpwsData->overlapped, DPWS_UdpReceiveCompleted ) ) + { + if ( WSAGetLastError() != WSA_IO_PENDING ) + { + ERR( "WSARecv() failed\n" ); + return 0; + } + } + for ( ;; ) { DPWS_IN_CONNECTION *connection; @@ -370,12 +439,17 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) return hr; }
+ dpwsData->overlapped.hEvent = (HANDLE)dpwsData; + dpwsData->wsaBuffer.len = sizeof( dpwsData->buffer ); + dpwsData->wsaBuffer.buf = dpwsData->buffer; + rb_init( &dpwsData->connections, DPWS_CompareConnections );
dpwsData->stopEvent = WSACreateEvent(); if ( !dpwsData->stopEvent ) { ERR( "WSACreateEvent() failed\n" ); + closesocket( dpwsData->udpSock ); WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); return DPERR_UNAVAILABLE; @@ -389,6 +463,7 @@ static HRESULT DPWS_Start( DPWS_DATA *dpwsData ) ERR( "CreateThread() failed\n" ); DeleteCriticalSection( &dpwsData->sendCs ); WSACloseEvent( dpwsData->stopEvent ); + closesocket( dpwsData->udpSock ); WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); return DPERR_UNAVAILABLE; @@ -430,6 +505,7 @@ static void DPWS_Stop( DPWS_DATA *dpwsData )
DeleteCriticalSection( &dpwsData->sendCs ); WSACloseEvent( dpwsData->stopEvent ); + closesocket( dpwsData->udpSock ); WSACloseEvent( dpwsData->acceptEvent ); closesocket( dpwsData->tcpSock ); }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/tests/dplayx.c | 118 +++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index e5606b99540..02746f2fe6a 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -971,6 +971,13 @@ typedef struct DPID toId; } GameMessage;
+typedef struct +{ + MessageHeader header; + DPID fromId; + DWORD tickCount; +} Ping; + #include "poppack.h"
#define bindUdp( port ) bindUdp_( __LINE__, port ) @@ -1974,6 +1981,69 @@ static void sendGameMessage_( int line, SOCKET sock, DPID fromId, DPID toId, voi ok_( __FILE__, line )( wsResult == size, "send() returned %d.\n", wsResult ); }
+#define sendPing( sock, port, fromId, tickCount ) \ + sendPing_( __LINE__, sock, port, fromId, tickCount ) +static void sendPing_( int line, SOCKET sock, unsigned short port, DPID fromId, DWORD tickCount ) +{ + struct + { + SpHeader spHeader; + Ping request; + } request = + { + .spHeader = + { + .mixed = 0xfab00000 + sizeof( request ), + .addr = + { + .sin_family = AF_INET, + .sin_port = htons( port ), + }, + }, + .request = + { + .header = + { + .magic = 0x79616c70, + .command = 22, + .version = 14, + }, + .fromId = fromId, + .tickCount = tickCount, + } + }; + int wsResult; + + wsResult = send( sock, (char *) &request, sizeof( request ), 0 ); + ok_( __FILE__, line )( wsResult == sizeof( request ), "send() returned %d.\n", wsResult ); +} + +#define receivePingReply( sock, expectedFromId, expectedTickCount ) \ + receivePingReply_( __LINE__, sock, expectedFromId, expectedTickCount ) +static unsigned short receivePingReply_( int line, SOCKET sock, DPID expectedFromId, DWORD expectedTickCount ) +{ + struct + { + SpHeader spHeader; + Ping request; + } request; + unsigned short port; + int wsResult; + + wsResult = receiveMessage_( line, sock, &request, sizeof( request ) ); + todo_wine ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult ); + if ( wsResult == SOCKET_ERROR ) + return 0; + + port = checkSpHeader_( line, &request.spHeader, sizeof( request ) ); + checkMessageHeader_( line, &request.request.header, 23 ); + ok_( __FILE__, line )( request.request.fromId == expectedFromId, "got source id %#lx.\n", request.request.fromId ); + ok_( __FILE__, line )( request.request.tickCount == expectedTickCount, "got tick count %#lx.\n", + request.request.tickCount ); + + return port; +} + static void init_TCPIP_provider( IDirectPlay4 *pDP, LPCSTR strIPAddressString, WORD port ) {
@@ -8678,6 +8748,53 @@ static void test_interactive_Receive(void)
}
+static void test_PING(void) +{ + DPSESSIONDESC2 appGuidDpsd = + { + .dwSize = sizeof( DPSESSIONDESC2 ), + .guidInstance = appGuid, + .guidApplication = appGuid, + }; + DPSESSIONDESC2 serverDpsd = + { + .dwSize = sizeof( DPSESSIONDESC2 ), + .guidApplication = appGuid, + .guidInstance = appGuid, + .lpszSessionName = (WCHAR *) L"normal", + .dwReserved1 = 0xaabbccdd, + }; + unsigned short udpPort; + SOCKET udpSendSock; + SOCKET udpRecvSock; + IDirectPlay4A *dp; + SOCKET sendSock; + SOCKET recvSock; + HRESULT hr; + + hr = CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlay4A, (void **) &dp ); + ok( hr == DP_OK, "got hr %#lx.\n", hr ); + + init_TCPIP_provider( dp, "127.0.0.1", 0 ); + + joinSession( dp, &appGuidDpsd, &serverDpsd, &sendSock, &recvSock, &udpPort ); + + udpSendSock = connectUdp( udpPort ); + + udpRecvSock = bindUdp( 2399 ); + + sendPing( udpSendSock, 2349, 0x51573, 0x44332211 ); + receivePingReply( udpRecvSock, 0x12345678, 0x44332211 ); + checkNoMoreMessages( udpRecvSock ); + + closesocket( udpRecvSock ); + closesocket( udpSendSock ); + closesocket( recvSock ); + closesocket( sendSock ); + + IDirectPlayX_Release( dp ); +} + /* GetMessageCount */
static void test_GetMessageCount(void) @@ -9934,6 +10051,7 @@ START_TEST(dplayx) test_CREATEPLAYER(); test_Send(); test_Receive(); + test_PING();
if (!winetest_interactive) {
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 22 +++++++++++++++++++ dlls/dplayx/dplayx_messages.c | 41 +++++++++++++++++++++++++++++++++++ dlls/dplayx/dplayx_messages.h | 11 +++++++++- dlls/dplayx/tests/dplayx.c | 4 +--- 4 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 4dbbd722730..d1b56afa5c2 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -545,6 +545,28 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, void *messageBody, DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */ break;
+ case DPMSGCMD_PING: { + const DPSP_MSG_PING *msg; + + if( dwMessageBodySize < sizeof( DPSP_MSG_PING ) ) + return DPERR_GENERIC; + msg = (const DPSP_MSG_PING *)messageBody; + + EnterCriticalSection( &This->lock ); + + if ( !This->dp2->bConnectionOpen ) + { + LeaveCriticalSection( &This->lock ); + return DP_OK; + } + + LeaveCriticalSection( &This->lock ); + + DP_MSG_SendPingReply( This, msg->fromId, This->dp2->systemPlayerId, msg->tickCount ); + + break; + } + case DPMSGCMD_ADDFORWARD: { DPSP_MSG_ADDFORWARD *msg; DPPLAYERINFO playerInfo; diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 52aea44a17f..3eeb8c23508 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -795,6 +795,47 @@ HRESULT DP_MSG_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWOR return DP_OK; }
+HRESULT DP_MSG_SendPingReply( IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount ) +{ + SGBUFFER buffers[ 2 ] = { 0 }; + DPSP_SENDEXDATA sendData; + DPSP_MSG_PING msg; + HRESULT hr; + + msg.envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; + msg.envelope.wCommandId = DPMSGCMD_PINGREPLY; + msg.envelope.wVersion = DPMSGVER_DP6; + msg.fromId = fromId; + msg.tickCount = tickCount; + + buffers[ 0 ].len = This->dp2->spData.dwSPHeaderSize; + buffers[ 0 ].pData = NULL; + buffers[ 1 ].len = sizeof( msg ); + buffers[ 1 ].pData = (UCHAR *)&msg; + + sendData.lpISP = This->dp2->spData.lpISP; + sendData.dwFlags = 0; + sendData.idPlayerTo = toId; + sendData.idPlayerFrom = This->dp2->systemPlayerId; + sendData.lpSendBuffers = buffers; + sendData.cBuffers = ARRAYSIZE( buffers ); + sendData.dwMessageSize = DP_MSG_ComputeMessageSize( sendData.lpSendBuffers, sendData.cBuffers ); + sendData.dwPriority = 0; + sendData.dwTimeout = 0; + sendData.lpDPContext = NULL; + sendData.lpdwSPMsgID = NULL; + sendData.bSystemMessage = TRUE; + + hr = (*This->dp2->spData.lpCB->SendEx)( &sendData ); + if( FAILED( hr ) ) + { + ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) ); + return hr; + } + + return DP_OK; +} + HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id ) { SGBUFFER buffers[ 2 ] = { 0 }; diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index fd432e5cb6c..2a3a15d5c73 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -57,6 +57,7 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer, WC HRESULT DP_MSG_SendCreatePlayer( IDirectPlayImpl *This, DPID toId, DPID id, DWORD flags, DPNAME *name, void *playerData, DWORD playerDataSize, DPID systemPlayerId ); +HRESULT DP_MSG_SendPingReply( IDirectPlayImpl *This, DPID toId, DPID fromId, DWORD tickCount ); HRESULT DP_MSG_SendAddForwardAck( IDirectPlayImpl *This, DPID id );
void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, @@ -107,7 +108,8 @@ typedef struct
#define DPMSGCMD_FORWARDADDPLAYER 19
-#define DPMSGCMD_PLAYERCHAT 22 +#define DPMSGCMD_PING 22 +#define DPMSGCMD_PINGREPLY 23
#define DPMSGCMD_FORWARDADDPLAYERNACK 36
@@ -268,6 +270,13 @@ typedef struct #define DPLAYI_SUPERPACKEDPLAYER_PARENT_ID_PRESENT 0x100 #define DPLAYI_SUPERPACKEDPLAYER_SHORTCUT_COUNT_SIZE( mask ) (((mask) >> 9) & 0x3)
+typedef struct +{ + DPMSG_SENDENVELOPE envelope; + DPID fromId; + DWORD tickCount; +} DPSP_MSG_PING; + typedef struct { DPMSG_SENDENVELOPE envelope; diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 02746f2fe6a..da3a9b533c2 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -2031,9 +2031,7 @@ static unsigned short receivePingReply_( int line, SOCKET sock, DPID expectedFro int wsResult;
wsResult = receiveMessage_( line, sock, &request, sizeof( request ) ); - todo_wine ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult ); - if ( wsResult == SOCKET_ERROR ) - return 0; + ok_( __FILE__, line )( wsResult == sizeof( request ), "recv() returned %d.\n", wsResult );
port = checkSpHeader_( line, &request.spHeader, sizeof( request ) ); checkMessageHeader_( line, &request.request.header, 23 );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149521
Your paranoid android.
=== debian11 (32 bit hi:IN report) ===
dplayx: dplayx.c:4654: Test failed: got UDP port 52428. dplayx.c:4660: Test failed: got UDP port 52428.
This merge request was approved by Alistair Leslie-Hughes.