mirror of
https://github.com/solemnwarning/directplay-lite
synced 2024-12-30 16:45:37 +01:00
Handle group cleanups for session end etc
This commit is contained in:
parent
e8e35c1c45
commit
6df47cee60
@ -2478,6 +2478,8 @@ HRESULT DirectPlay8Peer::Close(CONST DWORD dwFlags)
|
||||
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_NORMAL);
|
||||
}
|
||||
|
||||
group_destroy_all(l, DPNDESTROYGROUPREASON_NORMAL);
|
||||
|
||||
/* Wait for outstanding EnumHosts() calls. */
|
||||
host_enum_completed.wait(l, [this]() { return async_host_enums.empty() && sync_host_enums.empty(); });
|
||||
|
||||
@ -2945,6 +2947,8 @@ HRESULT DirectPlay8Peer::TerminateSession(void* CONST pvTerminateData, CONST DWO
|
||||
dispatch_destroy_player(l, cp->first, cp->second, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||
}
|
||||
|
||||
group_destroy_all(l, DPNDESTROYGROUPREASON_NORMAL);
|
||||
|
||||
/* Destroy any peers which weren't fully connected. */
|
||||
|
||||
for(auto dp = destroy_peers.begin(); dp != destroy_peers.end();)
|
||||
@ -3788,6 +3792,8 @@ void DirectPlay8Peer::peer_destroy(std::unique_lock<std::mutex> &l, unsigned int
|
||||
auto peer_id = peers.begin()->first;
|
||||
peer_destroy(l, peer_id, outstanding_op_result, destroy_player_reason);
|
||||
}
|
||||
|
||||
group_destroy_all(l, DPNDESTROYGROUPREASON_NORMAL);
|
||||
}
|
||||
|
||||
RENEW_PEER_OR_RETURN();
|
||||
@ -3882,6 +3888,23 @@ void DirectPlay8Peer::peer_shutdown_all(std::unique_lock<std::mutex> &l, HRESULT
|
||||
}
|
||||
}
|
||||
|
||||
void DirectPlay8Peer::group_destroy_all(std::unique_lock<std::mutex> &l, DWORD dwReason)
|
||||
{
|
||||
for(std::map<DPNID, Group>::iterator g; (g = groups.begin()) != groups.end();)
|
||||
{
|
||||
DPNID group_id = g->first;
|
||||
Group *group = &(g->second);
|
||||
|
||||
if(destroyed_groups.find(group_id) == destroyed_groups.end())
|
||||
{
|
||||
destroyed_groups.insert(group_id);
|
||||
dispatch_destroy_group(l, group_id, group->ctx, dwReason);
|
||||
}
|
||||
|
||||
groups.erase(group_id);
|
||||
}
|
||||
}
|
||||
|
||||
void DirectPlay8Peer::close_main_sockets()
|
||||
{
|
||||
if(discovery_socket != -1)
|
||||
@ -4581,6 +4604,8 @@ void DirectPlay8Peer::handle_connect_peer(std::unique_lock<std::mutex> &l, unsig
|
||||
|
||||
/* Send DPLITE_MSGID_GROUP_CREATE for each group. */
|
||||
|
||||
std::set<DPNID> member_group_ids;
|
||||
|
||||
for(auto gi = groups.begin(); gi != groups.end(); ++gi)
|
||||
{
|
||||
DPNID group_id = gi->first;
|
||||
@ -4599,6 +4624,11 @@ void DirectPlay8Peer::handle_connect_peer(std::unique_lock<std::mutex> &l, unsig
|
||||
|
||||
peer->sq.send(SendQueue::SEND_PRI_HIGH, group_create, NULL,
|
||||
[](std::unique_lock<std::mutex> &l, HRESULT result) {});
|
||||
|
||||
if(group->player_ids.find(local_player_id) != group->player_ids.end())
|
||||
{
|
||||
member_group_ids.insert(group_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send DPLITE_MSGID_CONNECT_PEER_OK. */
|
||||
@ -4607,7 +4637,12 @@ void DirectPlay8Peer::handle_connect_peer(std::unique_lock<std::mutex> &l, unsig
|
||||
connect_peer_ok.append_wstring(local_player_name);
|
||||
connect_peer_ok.append_data(local_player_data.data(), local_player_data.size());
|
||||
|
||||
/* TODO: Include our group memberships. */
|
||||
connect_peer_ok.append_dword(member_group_ids.size());
|
||||
|
||||
for(auto i = member_group_ids.begin(); i != member_group_ids.end(); ++i)
|
||||
{
|
||||
connect_peer_ok.append_dword(*i);
|
||||
}
|
||||
|
||||
peer->sq.send(SendQueue::SEND_PRI_HIGH,
|
||||
connect_peer_ok,
|
||||
@ -4655,6 +4690,14 @@ void DirectPlay8Peer::handle_connect_peer_ok(std::unique_lock<std::mutex> &l, un
|
||||
(const unsigned char*)(player_data.first),
|
||||
(const unsigned char*)(player_data.first) + player_data.second);
|
||||
|
||||
DWORD peer_group_count = pd.get_dword(2);
|
||||
std::set<DPNID> peer_groups;
|
||||
|
||||
for(DWORD i = 0; i < peer_group_count; ++i)
|
||||
{
|
||||
peer_groups.insert(pd.get_dword(3 + i));
|
||||
}
|
||||
|
||||
peer->state = Peer::PS_CONNECTED;
|
||||
|
||||
/* player_id initialised in handling of DPLITE_MSGID_CONNECT_HOST_OK. */
|
||||
@ -4677,7 +4720,46 @@ void DirectPlay8Peer::handle_connect_peer_ok(std::unique_lock<std::mutex> &l, un
|
||||
peer->player_ctx = cp.pvPlayerContext;
|
||||
}
|
||||
|
||||
/* TODO: Add peer to specified groups. */
|
||||
for(auto g = peer_groups.begin(); g != peer_groups.end(); ++g)
|
||||
{
|
||||
DPNID group_id = *g;
|
||||
|
||||
if(destroyed_groups.find(group_id) != destroyed_groups.end())
|
||||
{
|
||||
/* Group is already in the process of being destroyed. */
|
||||
continue;
|
||||
}
|
||||
|
||||
Group *group = get_group_by_id(group_id);
|
||||
if(group == NULL)
|
||||
{
|
||||
/* Unknown group ID... very rarely normal. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if(group->player_ids.find(peer->player_id) != group->player_ids.end())
|
||||
{
|
||||
/* Already in group... somehow?! */
|
||||
continue;
|
||||
}
|
||||
|
||||
group->player_ids.insert(peer->player_id);
|
||||
|
||||
DPNMSG_ADD_PLAYER_TO_GROUP ap;
|
||||
memset(&ap, 0, sizeof(ap));
|
||||
|
||||
ap.dwSize = sizeof(ap);
|
||||
ap.dpnidGroup = group_id;
|
||||
ap.pvGroupContext = group->ctx;
|
||||
ap.dpnidPlayer = peer->player_id;
|
||||
ap.pvPlayerContext = peer->player_ctx;
|
||||
|
||||
l.unlock();
|
||||
message_handler(message_handler_ctx, DPN_MSGID_ADD_PLAYER_TO_GROUP, &ap);
|
||||
l.lock();
|
||||
|
||||
RENEW_PEER_OR_RETURN();
|
||||
}
|
||||
|
||||
connect_check(l);
|
||||
}
|
||||
@ -4966,6 +5048,8 @@ void DirectPlay8Peer::handle_destroy_peer(std::unique_lock<std::mutex> &l, unsig
|
||||
}
|
||||
|
||||
peer_shutdown_all(l, DPNERR_HOSTTERMINATEDSESSION, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||
|
||||
group_destroy_all(l, DPNDESTROYGROUPREASON_SESSIONTERMINATED);
|
||||
}
|
||||
else{
|
||||
/* The host called DestroyPeer() on another peer in the session.
|
||||
@ -5032,6 +5116,8 @@ void DirectPlay8Peer::handle_terminate_session(std::unique_lock<std::mutex> &l,
|
||||
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||
|
||||
peer_shutdown_all(l, DPNERR_HOSTTERMINATEDSESSION, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||
|
||||
group_destroy_all(l, DPNDESTROYGROUPREASON_SESSIONTERMINATED);
|
||||
}
|
||||
catch(const PacketDeserialiser::Error &e)
|
||||
{
|
||||
@ -5627,6 +5713,36 @@ HRESULT DirectPlay8Peer::dispatch_create_player(std::unique_lock<std::mutex> &l,
|
||||
|
||||
HRESULT DirectPlay8Peer::dispatch_destroy_player(std::unique_lock<std::mutex> &l, DPNID dpnidPlayer, void *pvPlayerContext, DWORD dwReason)
|
||||
{
|
||||
/* HACK: Remove the player ID from any groups it is still in. */
|
||||
for(auto g = groups.begin(); g != groups.end();)
|
||||
{
|
||||
DPNID group_id = g->first;
|
||||
Group *group = &(g->second);
|
||||
|
||||
if(group->player_ids.find(dpnidPlayer) != group->player_ids.end())
|
||||
{
|
||||
group->player_ids.erase(dpnidPlayer);
|
||||
|
||||
DPNMSG_REMOVE_PLAYER_FROM_GROUP rp;
|
||||
memset(&rp, 0, sizeof(rp));
|
||||
|
||||
rp.dwSize = sizeof(rp);
|
||||
rp.dpnidGroup = group_id;
|
||||
rp.pvGroupContext = group->ctx;
|
||||
rp.dpnidPlayer = dpnidPlayer;
|
||||
rp.pvPlayerContext = pvPlayerContext;
|
||||
|
||||
l.unlock();
|
||||
message_handler(message_handler_ctx, DPN_MSGID_REMOVE_PLAYER_FROM_GROUP, &rp);
|
||||
l.lock();
|
||||
|
||||
g = groups.begin();
|
||||
}
|
||||
else{
|
||||
++g;
|
||||
}
|
||||
}
|
||||
|
||||
DPNMSG_DESTROY_PLAYER dp;
|
||||
memset(&dp, 0, sizeof(dp));
|
||||
|
||||
@ -5638,6 +5754,18 @@ HRESULT DirectPlay8Peer::dispatch_destroy_player(std::unique_lock<std::mutex> &l
|
||||
return dispatch_message(l, DPN_MSGID_DESTROY_PLAYER, &dp);
|
||||
}
|
||||
|
||||
HRESULT DirectPlay8Peer::dispatch_destroy_group(std::unique_lock<std::mutex> &l, DPNID dpnidGroup, void *pvGroupContext, DWORD dwReason)
|
||||
{
|
||||
DPNMSG_DESTROY_GROUP dg;
|
||||
|
||||
dg.dwSize = sizeof(dg);
|
||||
dg.dpnidGroup = dpnidGroup;
|
||||
dg.pvGroupContext = pvGroupContext;
|
||||
dg.dwReason = dwReason;
|
||||
|
||||
return dispatch_message(l, DPN_MSGID_DESTROY_GROUP, &dg);
|
||||
}
|
||||
|
||||
DirectPlay8Peer::Peer::Peer(enum PeerState state, int sock, uint32_t ip, uint16_t port):
|
||||
state(state), sock(sock), ip(ip), port(port), recv_busy(false), recv_buf_cur(0), events(0), sq(event), send_open(true), next_ack_id(1)
|
||||
{}
|
||||
|
@ -218,6 +218,8 @@ class DirectPlay8Peer: public IDirectPlay8Peer
|
||||
void peer_shutdown(std::unique_lock<std::mutex> &l, unsigned int peer_id, HRESULT outstanding_op_result, DWORD destroy_player_reason);
|
||||
void peer_shutdown_all(std::unique_lock<std::mutex> &l, HRESULT outstanding_op_result, DWORD destroy_player_reason);
|
||||
|
||||
void group_destroy_all(std::unique_lock<std::mutex> &l, DWORD dwReason);
|
||||
|
||||
void close_main_sockets();
|
||||
|
||||
void handle_host_enum_request(std::unique_lock<std::mutex> &l, const PacketDeserialiser &pd, const struct sockaddr_in *from_addr);
|
||||
@ -246,6 +248,7 @@ class DirectPlay8Peer: public IDirectPlay8Peer
|
||||
HRESULT dispatch_message(std::unique_lock<std::mutex> &l, DWORD dwMessageType, PVOID pvMessage);
|
||||
HRESULT dispatch_create_player(std::unique_lock<std::mutex> &l, DPNID dpnidPlayer, void **ppvPlayerContext);
|
||||
HRESULT dispatch_destroy_player(std::unique_lock<std::mutex> &l, DPNID dpnidPlayer, void *pvPlayerContext, DWORD dwReason);
|
||||
HRESULT dispatch_destroy_group(std::unique_lock<std::mutex> &l, DPNID dpnidGroup, void *pvGroupContext, DWORD dwReason);
|
||||
|
||||
public:
|
||||
DirectPlay8Peer(std::atomic<unsigned int> *global_refcount);
|
||||
|
@ -9477,6 +9477,108 @@ TEST(DirectPlay8Peer, DestroyGroupByTerminateSession)
|
||||
peer1.expect_end();
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, DestroyGroupByDestroyPeer)
|
||||
{
|
||||
DPN_APPLICATION_DESC app_desc;
|
||||
memset(&app_desc, 0, sizeof(app_desc));
|
||||
|
||||
app_desc.dwSize = sizeof(app_desc);
|
||||
app_desc.guidApplication = APP_GUID_1;
|
||||
app_desc.pwszSessionName = L"Session 1";
|
||||
|
||||
IDP8AddressInstance host_addr(CLSID_DP8SP_TCPIP, PORT);
|
||||
|
||||
TestPeer host("host");
|
||||
ASSERT_EQ(host->Host(&app_desc, &(host_addr.instance), 1, NULL, NULL, 0, 0), S_OK);
|
||||
|
||||
IDP8AddressInstance connect_addr(CLSID_DP8SP_TCPIP, L"127.0.0.1", PORT);
|
||||
|
||||
TestPeer peer1("peer1");
|
||||
ASSERT_EQ(peer1->Connect(
|
||||
&app_desc, /* pdnAppDesc */
|
||||
connect_addr, /* pHostAddr */
|
||||
NULL, /* pDeviceInfo */
|
||||
NULL, /* pdnSecurity */
|
||||
NULL, /* pdnCredentials */
|
||||
NULL, /* pvUserConnectData */
|
||||
0, /* dwUserConnectDataSize */
|
||||
0, /* pvPlayerContext */
|
||||
NULL, /* pvAsyncContext */
|
||||
NULL, /* phAsyncHandle */
|
||||
DPNCONNECT_SYNC /* dwFlags */
|
||||
), S_OK);
|
||||
|
||||
Sleep(100);
|
||||
|
||||
DPNID p1_cg_dpnidGroup;
|
||||
|
||||
peer1.expect_begin();
|
||||
peer1.expect_push([&host, &p1_cg_dpnidGroup](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_EQ(dwMessageType, DPN_MSGID_CREATE_GROUP);
|
||||
if(dwMessageType == DPN_MSGID_CREATE_GROUP)
|
||||
{
|
||||
DPNMSG_CREATE_GROUP *cg = (DPNMSG_CREATE_GROUP*)(pMessage);
|
||||
cg->pvGroupContext = (void*)(0xBCDE);
|
||||
|
||||
p1_cg_dpnidGroup = cg->dpnidGroup;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
DPN_GROUP_INFO group_info;
|
||||
memset(&group_info, 0, sizeof(group_info));
|
||||
|
||||
group_info.dwSize = sizeof(group_info);
|
||||
group_info.dwInfoFlags = DPNINFO_NAME | DPNINFO_DATA;
|
||||
group_info.pwszName = L"Test Group";
|
||||
group_info.pvData = NULL;
|
||||
group_info.dwDataSize = 0;
|
||||
group_info.dwGroupFlags = 0;
|
||||
|
||||
ASSERT_EQ(host->CreateGroup(
|
||||
&group_info, /* pdpnGroupInfo */
|
||||
NULL, /* pvGroupContext */
|
||||
NULL, /* pvAsyncContext */
|
||||
NULL, /* phAsyncHandle */
|
||||
DPNCREATEGROUP_SYNC), /* dwFlags */
|
||||
S_OK);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
peer1.expect_end();
|
||||
|
||||
peer1.expect_begin();
|
||||
peer1.expect_push([](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_TRUE(dwMessageType == DPN_MSGID_DESTROY_PLAYER
|
||||
|| dwMessageType == DPN_MSGID_TERMINATE_SESSION);
|
||||
return S_OK;
|
||||
}, 3);
|
||||
peer1.expect_push([&host, &p1_cg_dpnidGroup](DWORD dwMessageType, PVOID pMessage)
|
||||
{
|
||||
EXPECT_EQ(dwMessageType, DPN_MSGID_DESTROY_GROUP);
|
||||
if(dwMessageType == DPN_MSGID_DESTROY_GROUP)
|
||||
{
|
||||
DPNMSG_DESTROY_GROUP *dg = (DPNMSG_DESTROY_GROUP*)(pMessage);
|
||||
|
||||
EXPECT_EQ(dg->dwSize, sizeof(DPNMSG_DESTROY_GROUP));
|
||||
EXPECT_EQ(dg->dpnidGroup, p1_cg_dpnidGroup);
|
||||
EXPECT_EQ(dg->pvGroupContext, (void*)(0xBCDE));
|
||||
EXPECT_EQ(dg->dwReason, DPNDESTROYGROUPREASON_SESSIONTERMINATED);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
ASSERT_EQ(host->DestroyPeer(peer1.first_cc_dpnidLocal, NULL, 0, 0), S_OK);
|
||||
|
||||
Sleep(250);
|
||||
|
||||
peer1.expect_end();
|
||||
}
|
||||
|
||||
TEST(DirectPlay8Peer, AddPlayerToGroupSync)
|
||||
{
|
||||
const unsigned char GROUP_DATA[] = { 0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06 };
|
||||
|
Loading…
x
Reference in New Issue
Block a user