mirror of
https://github.com/solemnwarning/directplay-lite
synced 2024-12-30 16:45:37 +01:00
DirectPlay8Peer: Support cancelling in-progress connections.
This commit is contained in:
parent
f753f42d44
commit
c88355efb9
@ -185,6 +185,8 @@ HRESULT DirectPlay8Peer::EnumServiceProviders(CONST GUID* CONST pguidServiceProv
|
||||
|
||||
HRESULT DirectPlay8Peer::CancelAsyncOperation(CONST DPNHANDLE hAsyncHandle, CONST DWORD dwFlags)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(lock);
|
||||
|
||||
if(dwFlags & DPNCANCEL_PLAYER_SENDS)
|
||||
{
|
||||
/* Cancel sends to player ID in hAsyncHandle */
|
||||
@ -196,8 +198,6 @@ HRESULT DirectPlay8Peer::CancelAsyncOperation(CONST DPNHANDLE hAsyncHandle, CONS
|
||||
|
||||
if(dwFlags & (DPNCANCEL_ENUM | DPNCANCEL_ALL_OPERATIONS))
|
||||
{
|
||||
std::unique_lock<std::mutex> l(lock);
|
||||
|
||||
for(auto ei = host_enums.begin(); ei != host_enums.end(); ++ei)
|
||||
{
|
||||
ei->second.cancel();
|
||||
@ -206,7 +206,11 @@ HRESULT DirectPlay8Peer::CancelAsyncOperation(CONST DPNHANDLE hAsyncHandle, CONS
|
||||
|
||||
if(dwFlags & (DPNCANCEL_CONNECT | DPNCANCEL_ALL_OPERATIONS))
|
||||
{
|
||||
/* TODO: Cancel in-progress connect. */
|
||||
if((state == STATE_CONNECTING_TO_HOST || state == STATE_CONNECTING_TO_PEERS) && connect_handle != 0)
|
||||
{
|
||||
/* We have an ongoing asynchronous connection. */
|
||||
connect_fail(l, DPNERR_USERCANCEL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(dwFlags & DPNCANCEL_ALL_OPERATIONS)
|
||||
@ -218,8 +222,6 @@ HRESULT DirectPlay8Peer::CancelAsyncOperation(CONST DPNHANDLE hAsyncHandle, CONS
|
||||
}
|
||||
else if((hAsyncHandle & AsyncHandleAllocator::TYPE_MASK) == AsyncHandleAllocator::TYPE_ENUM)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(lock);
|
||||
|
||||
auto ei = host_enums.find(hAsyncHandle);
|
||||
if(ei == host_enums.end())
|
||||
{
|
||||
@ -233,7 +235,20 @@ HRESULT DirectPlay8Peer::CancelAsyncOperation(CONST DPNHANDLE hAsyncHandle, CONS
|
||||
}
|
||||
else if((hAsyncHandle & AsyncHandleAllocator::TYPE_MASK) == AsyncHandleAllocator::TYPE_CONNECT)
|
||||
{
|
||||
UNIMPLEMENTED("DirectPlay8Peer::CancelAsyncOperation");
|
||||
if(hAsyncHandle == connect_handle)
|
||||
{
|
||||
if(state == STATE_CONNECTING_TO_HOST || state == STATE_CONNECTING_TO_PEERS)
|
||||
{
|
||||
connect_fail(l, DPNERR_USERCANCEL, NULL, 0);
|
||||
return S_OK;
|
||||
}
|
||||
else{
|
||||
return DPNERR_CANNOTCANCEL;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return DPNERR_INVALIDHANDLE;
|
||||
}
|
||||
}
|
||||
else if((hAsyncHandle & AsyncHandleAllocator::TYPE_MASK) == AsyncHandleAllocator::TYPE_SEND)
|
||||
{
|
||||
@ -1415,6 +1430,15 @@ HRESULT DirectPlay8Peer::Close(CONST DWORD dwFlags)
|
||||
udp_socket = -1;
|
||||
}
|
||||
|
||||
if(state == STATE_CONNECTING_TO_HOST || state == STATE_CONNECTING_TO_PEERS)
|
||||
{
|
||||
/* connect_fail() will change the state to STATE_CONNECT_FAILED, then finally to
|
||||
* STATE_INITIALISED before it returns, this doesn't matter as we return it to
|
||||
* STATE_CLOSING before the lock is released again.
|
||||
*/
|
||||
connect_fail(l, DPNERR_NOCONNECTION, NULL, 0);
|
||||
}
|
||||
|
||||
state = STATE_CLOSING;
|
||||
|
||||
/* When Close() is called as a host, the DPNMSG_DESTROY_PLAYER for the local player comes
|
||||
|
@ -1873,6 +1873,286 @@ TEST(DirectPlay8Peer, ConnectAsyncFail)
|
||||
EXPECT_EQ(p1_seq, 1);
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, ConnectAsyncCancelByHandle)
|
||||
{
|
||||
/* We set up a host which blocks when processing DPN_MSGID_INDICATE_CONNECT, causing any
|
||||
* attempted Connect() by a peer to take a while, giving us time to cancel it.
|
||||
*/
|
||||
SessionHost host(APP_GUID_1, L"Session 1", PORT,
|
||||
[]
|
||||
(DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
if(dwMessageType == DPN_MSGID_INDICATE_CONNECT)
|
||||
{
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
TestPeer peer1("peer1");
|
||||
|
||||
DPN_APPLICATION_DESC connect_to_app;
|
||||
memset(&connect_to_app, 0, sizeof(connect_to_app));
|
||||
|
||||
connect_to_app.dwSize = sizeof(connect_to_app);
|
||||
connect_to_app.guidApplication = APP_GUID_1;
|
||||
|
||||
IDP8AddressInstance connect_to_addr(L"127.0.0.1", PORT);
|
||||
|
||||
DPNHANDLE p1_connect_handle;
|
||||
ASSERT_EQ(peer1->Connect(
|
||||
&connect_to_app, /* pdnAppDesc */
|
||||
connect_to_addr, /* pHostAddr */
|
||||
NULL, /* pDeviceInfo */
|
||||
NULL, /* pdnSecurity */
|
||||
NULL, /* pdnCredentials */
|
||||
NULL, /* pvUserConnectData */
|
||||
0, /* dwUserConnectDataSize */
|
||||
NULL, /* pvPlayerContext */
|
||||
(void*)(0xABCD), /* pvAsyncContext */
|
||||
&p1_connect_handle, /* phAsyncHandle */
|
||||
0 /* dwFlags */
|
||||
), DPNSUCCESS_PENDING);
|
||||
|
||||
peer1.expect_begin();
|
||||
peer1.expect_push([&p1_connect_handle](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_EQ(dwMessageType, DPN_MSGID_CONNECT_COMPLETE);
|
||||
|
||||
if(dwMessageType == DPN_MSGID_CONNECT_COMPLETE)
|
||||
{
|
||||
DPNMSG_CONNECT_COMPLETE *cc = (DPNMSG_CONNECT_COMPLETE*)(pMessage);
|
||||
|
||||
EXPECT_EQ(cc->dwSize, sizeof(DPNMSG_CONNECT_COMPLETE));
|
||||
EXPECT_EQ(cc->hAsyncOp, p1_connect_handle);
|
||||
EXPECT_EQ(cc->pvUserContext, (void*)(0xABCD));
|
||||
EXPECT_EQ(cc->hResultCode, DPNERR_USERCANCEL);
|
||||
|
||||
EXPECT_EQ(cc->pvApplicationReplyData, (PVOID)(NULL));
|
||||
EXPECT_EQ(cc->dwApplicationReplyDataSize, 0);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
ASSERT_EQ(peer1->CancelAsyncOperation(p1_connect_handle, 0), S_OK);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
peer1.expect_end();
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, ConnectAsyncCancelAllConnects)
|
||||
{
|
||||
/* We set up a host which blocks when processing DPN_MSGID_INDICATE_CONNECT, causing any
|
||||
* attempted Connect() by a peer to take a while, giving us time to cancel it.
|
||||
*/
|
||||
SessionHost host(APP_GUID_1, L"Session 1", PORT,
|
||||
[]
|
||||
(DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
if(dwMessageType == DPN_MSGID_INDICATE_CONNECT)
|
||||
{
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
TestPeer peer1("peer1");
|
||||
|
||||
DPN_APPLICATION_DESC connect_to_app;
|
||||
memset(&connect_to_app, 0, sizeof(connect_to_app));
|
||||
|
||||
connect_to_app.dwSize = sizeof(connect_to_app);
|
||||
connect_to_app.guidApplication = APP_GUID_1;
|
||||
|
||||
IDP8AddressInstance connect_to_addr(L"127.0.0.1", PORT);
|
||||
|
||||
DPNHANDLE p1_connect_handle;
|
||||
ASSERT_EQ(peer1->Connect(
|
||||
&connect_to_app, /* pdnAppDesc */
|
||||
connect_to_addr, /* pHostAddr */
|
||||
NULL, /* pDeviceInfo */
|
||||
NULL, /* pdnSecurity */
|
||||
NULL, /* pdnCredentials */
|
||||
NULL, /* pvUserConnectData */
|
||||
0, /* dwUserConnectDataSize */
|
||||
NULL, /* pvPlayerContext */
|
||||
(void*)(0xABCD), /* pvAsyncContext */
|
||||
&p1_connect_handle, /* phAsyncHandle */
|
||||
0 /* dwFlags */
|
||||
), DPNSUCCESS_PENDING);
|
||||
|
||||
peer1.expect_begin();
|
||||
peer1.expect_push([&p1_connect_handle](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_EQ(dwMessageType, DPN_MSGID_CONNECT_COMPLETE);
|
||||
|
||||
if(dwMessageType == DPN_MSGID_CONNECT_COMPLETE)
|
||||
{
|
||||
DPNMSG_CONNECT_COMPLETE *cc = (DPNMSG_CONNECT_COMPLETE*)(pMessage);
|
||||
|
||||
EXPECT_EQ(cc->dwSize, sizeof(DPNMSG_CONNECT_COMPLETE));
|
||||
EXPECT_EQ(cc->hAsyncOp, p1_connect_handle);
|
||||
EXPECT_EQ(cc->pvUserContext, (void*)(0xABCD));
|
||||
EXPECT_EQ(cc->hResultCode, DPNERR_USERCANCEL);
|
||||
|
||||
EXPECT_EQ(cc->pvApplicationReplyData, (PVOID)(NULL));
|
||||
EXPECT_EQ(cc->dwApplicationReplyDataSize, 0);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
ASSERT_EQ(peer1->CancelAsyncOperation(NULL, DPNCANCEL_CONNECT), S_OK);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
peer1.expect_end();
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, ConnectAsyncCancelAllOperations)
|
||||
{
|
||||
/* We set up a host which blocks when processing DPN_MSGID_INDICATE_CONNECT, causing any
|
||||
* attempted Connect() by a peer to take a while, giving us time to cancel it.
|
||||
*/
|
||||
SessionHost host(APP_GUID_1, L"Session 1", PORT,
|
||||
[]
|
||||
(DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
if(dwMessageType == DPN_MSGID_INDICATE_CONNECT)
|
||||
{
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
TestPeer peer1("peer1");
|
||||
|
||||
DPN_APPLICATION_DESC connect_to_app;
|
||||
memset(&connect_to_app, 0, sizeof(connect_to_app));
|
||||
|
||||
connect_to_app.dwSize = sizeof(connect_to_app);
|
||||
connect_to_app.guidApplication = APP_GUID_1;
|
||||
|
||||
IDP8AddressInstance connect_to_addr(L"127.0.0.1", PORT);
|
||||
|
||||
DPNHANDLE p1_connect_handle;
|
||||
ASSERT_EQ(peer1->Connect(
|
||||
&connect_to_app, /* pdnAppDesc */
|
||||
connect_to_addr, /* pHostAddr */
|
||||
NULL, /* pDeviceInfo */
|
||||
NULL, /* pdnSecurity */
|
||||
NULL, /* pdnCredentials */
|
||||
NULL, /* pvUserConnectData */
|
||||
0, /* dwUserConnectDataSize */
|
||||
NULL, /* pvPlayerContext */
|
||||
(void*)(0xABCD), /* pvAsyncContext */
|
||||
&p1_connect_handle, /* phAsyncHandle */
|
||||
0 /* dwFlags */
|
||||
), DPNSUCCESS_PENDING);
|
||||
|
||||
peer1.expect_begin();
|
||||
peer1.expect_push([&p1_connect_handle](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_EQ(dwMessageType, DPN_MSGID_CONNECT_COMPLETE);
|
||||
|
||||
if(dwMessageType == DPN_MSGID_CONNECT_COMPLETE)
|
||||
{
|
||||
DPNMSG_CONNECT_COMPLETE *cc = (DPNMSG_CONNECT_COMPLETE*)(pMessage);
|
||||
|
||||
EXPECT_EQ(cc->dwSize, sizeof(DPNMSG_CONNECT_COMPLETE));
|
||||
EXPECT_EQ(cc->hAsyncOp, p1_connect_handle);
|
||||
EXPECT_EQ(cc->pvUserContext, (void*)(0xABCD));
|
||||
EXPECT_EQ(cc->hResultCode, DPNERR_USERCANCEL);
|
||||
|
||||
EXPECT_EQ(cc->pvApplicationReplyData, (PVOID)(NULL));
|
||||
EXPECT_EQ(cc->dwApplicationReplyDataSize, 0);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
ASSERT_EQ(peer1->CancelAsyncOperation(NULL, DPNCANCEL_ALL_OPERATIONS), S_OK);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
peer1.expect_end();
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, ConnectAsyncCancelByClose)
|
||||
{
|
||||
/* We set up a host which blocks when processing DPN_MSGID_INDICATE_CONNECT, causing any
|
||||
* attempted Connect() by a peer to take a while, giving us time to cancel it.
|
||||
*/
|
||||
SessionHost host(APP_GUID_1, L"Session 1", PORT,
|
||||
[]
|
||||
(DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
if(dwMessageType == DPN_MSGID_INDICATE_CONNECT)
|
||||
{
|
||||
Sleep(2000);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
TestPeer peer1("peer1");
|
||||
|
||||
DPN_APPLICATION_DESC connect_to_app;
|
||||
memset(&connect_to_app, 0, sizeof(connect_to_app));
|
||||
|
||||
connect_to_app.dwSize = sizeof(connect_to_app);
|
||||
connect_to_app.guidApplication = APP_GUID_1;
|
||||
|
||||
IDP8AddressInstance connect_to_addr(L"127.0.0.1", PORT);
|
||||
|
||||
DPNHANDLE p1_connect_handle;
|
||||
ASSERT_EQ(peer1->Connect(
|
||||
&connect_to_app, /* pdnAppDesc */
|
||||
connect_to_addr, /* pHostAddr */
|
||||
NULL, /* pDeviceInfo */
|
||||
NULL, /* pdnSecurity */
|
||||
NULL, /* pdnCredentials */
|
||||
NULL, /* pvUserConnectData */
|
||||
0, /* dwUserConnectDataSize */
|
||||
NULL, /* pvPlayerContext */
|
||||
(void*)(0xABCD), /* pvAsyncContext */
|
||||
&p1_connect_handle, /* phAsyncHandle */
|
||||
0 /* dwFlags */
|
||||
), DPNSUCCESS_PENDING);
|
||||
|
||||
peer1.expect_begin();
|
||||
peer1.expect_push([&p1_connect_handle](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_EQ(dwMessageType, DPN_MSGID_CONNECT_COMPLETE);
|
||||
|
||||
if(dwMessageType == DPN_MSGID_CONNECT_COMPLETE)
|
||||
{
|
||||
DPNMSG_CONNECT_COMPLETE *cc = (DPNMSG_CONNECT_COMPLETE*)(pMessage);
|
||||
|
||||
EXPECT_EQ(cc->dwSize, sizeof(DPNMSG_CONNECT_COMPLETE));
|
||||
EXPECT_EQ(cc->hAsyncOp, p1_connect_handle);
|
||||
EXPECT_EQ(cc->pvUserContext, (void*)(0xABCD));
|
||||
EXPECT_EQ(cc->hResultCode, DPNERR_NOCONNECTION);
|
||||
|
||||
EXPECT_EQ(cc->pvApplicationReplyData, (PVOID)(NULL));
|
||||
EXPECT_EQ(cc->dwApplicationReplyDataSize, 0);
|
||||
}
|
||||
|
||||
return DPN_OK;
|
||||
});
|
||||
|
||||
peer1->Close(DPNCLOSE_IMMEDIATE);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
peer1.expect_end();
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, ConnectToIPX)
|
||||
{
|
||||
std::atomic<bool> testing(true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user