mirror of
https://github.com/solemnwarning/directplay-lite
synced 2024-12-30 16:45:37 +01:00
Remove code duplication in disconnect/cleanup paths.
This commit is contained in:
parent
b74b018ff2
commit
9fc69d67ea
@ -1475,23 +1475,7 @@ HRESULT DirectPlay8Peer::Close(CONST DWORD dwFlags)
|
|||||||
ei->second.cancel();
|
ei->second.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(discovery_socket != -1)
|
close_main_sockets();
|
||||||
{
|
|
||||||
closesocket(discovery_socket);
|
|
||||||
discovery_socket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(listener_socket != -1)
|
|
||||||
{
|
|
||||||
closesocket(listener_socket);
|
|
||||||
listener_socket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(udp_socket != -1)
|
|
||||||
{
|
|
||||||
closesocket(udp_socket);
|
|
||||||
udp_socket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(state == STATE_CONNECTING_TO_HOST || state == STATE_CONNECTING_TO_PEERS)
|
if(state == STATE_CONNECTING_TO_HOST || state == STATE_CONNECTING_TO_PEERS)
|
||||||
{
|
{
|
||||||
@ -1513,66 +1497,16 @@ HRESULT DirectPlay8Peer::Close(CONST DWORD dwFlags)
|
|||||||
if(was_hosting)
|
if(was_hosting)
|
||||||
{
|
{
|
||||||
/* Raise a DPNMSG_DESTROY_PLAYER for ourself. */
|
/* Raise a DPNMSG_DESTROY_PLAYER for ourself. */
|
||||||
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_NORMAL);
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
|
||||||
dp.dpnidPlayer = local_player_id;
|
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_NORMAL;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dwFlags & DPNCLOSE_IMMEDIATE)
|
if(dwFlags & DPNCLOSE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
while(!peers.empty())
|
peer_destroy_all(l, DPNERR_USERCANCEL, DPNDESTROYPLAYERREASON_NORMAL);
|
||||||
{
|
|
||||||
unsigned int peer_id = peers.begin()->first;
|
|
||||||
peer_destroy(l, peer_id, DPNERR_USERCANCEL, DPNDESTROYPLAYERREASON_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for(auto pi = peers.begin(); pi != peers.end();)
|
/* Initiate graceful shutdown of all peers. */
|
||||||
{
|
peer_shutdown_all(l, DPNERR_USERCANCEL, DPNDESTROYPLAYERREASON_NORMAL);
|
||||||
unsigned int peer_id = pi->first;
|
|
||||||
Peer *peer = pi->second;
|
|
||||||
|
|
||||||
if(peer->state == Peer::PS_CONNECTED)
|
|
||||||
{
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(dp);
|
|
||||||
dp.dpnidPlayer = peer->player_id;
|
|
||||||
dp.pvPlayerContext = peer->player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_NORMAL;
|
|
||||||
|
|
||||||
peer->state = Peer::PS_CLOSING;
|
|
||||||
|
|
||||||
/* Wake up a worker to deal with closing the connection. */
|
|
||||||
SetEvent(peer->event);
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
pi = peers.begin();
|
|
||||||
}
|
|
||||||
else if(peer->state == Peer::PS_CLOSING)
|
|
||||||
{
|
|
||||||
/* Do nothing. We're waiting for this peer to go away. */
|
|
||||||
++pi;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
peer_destroy(l, peer_id, DPNERR_USERCANCEL, DPNDESTROYPLAYERREASON_NORMAL);
|
|
||||||
|
|
||||||
pi = peers.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for remaining peers to finish disconnecting. */
|
/* Wait for remaining peers to finish disconnecting. */
|
||||||
peer_destroyed.wait(l, [this]() { return peers.empty(); });
|
peer_destroyed.wait(l, [this]() { return peers.empty(); });
|
||||||
@ -1581,18 +1515,7 @@ HRESULT DirectPlay8Peer::Close(CONST DWORD dwFlags)
|
|||||||
if(was_connected)
|
if(was_connected)
|
||||||
{
|
{
|
||||||
/* Raise a DPNMSG_DESTROY_PLAYER for ourself. */
|
/* Raise a DPNMSG_DESTROY_PLAYER for ourself. */
|
||||||
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_NORMAL);
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
|
||||||
dp.dpnidPlayer = local_player_id;
|
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_NORMAL;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for outstanding EnumHosts() calls. */
|
/* Wait for outstanding EnumHosts() calls. */
|
||||||
@ -1719,6 +1642,9 @@ HRESULT DirectPlay8Peer::DestroyPeer(CONST DPNID dpnidClient, CONST void* CONST
|
|||||||
return DPNERR_INVALIDPLAYER;
|
return DPNERR_INVALIDPLAYER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dpnidClient must be present in player_to_peer_id for the above to have succeeded. */
|
||||||
|
unsigned int peer_id = player_to_peer_id[dpnidClient];
|
||||||
|
|
||||||
PacketSerialiser destroy_peer_base(DPLITE_MSGID_DESTROY_PEER);
|
PacketSerialiser destroy_peer_base(DPLITE_MSGID_DESTROY_PEER);
|
||||||
destroy_peer_base.append_dword(peer->player_id);
|
destroy_peer_base.append_dword(peer->player_id);
|
||||||
|
|
||||||
@ -1729,22 +1655,7 @@ HRESULT DirectPlay8Peer::DestroyPeer(CONST DPNID dpnidClient, CONST void* CONST
|
|||||||
/* Notify the peer we are destroying it and initiate the connection shutdown. */
|
/* Notify the peer we are destroying it and initiate the connection shutdown. */
|
||||||
|
|
||||||
peer->sq.send(SendQueue::SEND_PRI_HIGH, destroy_peer_full, NULL, [](std::unique_lock<std::mutex> &l, HRESULT result) {});
|
peer->sq.send(SendQueue::SEND_PRI_HIGH, destroy_peer_full, NULL, [](std::unique_lock<std::mutex> &l, HRESULT result) {});
|
||||||
|
peer_shutdown(l, peer_id, DPNERR_HOSTTERMINATEDSESSION, DPNDESTROYPLAYERREASON_HOSTDESTROYEDPLAYER);
|
||||||
peer->state = Peer::PS_CLOSING;
|
|
||||||
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(dp);
|
|
||||||
dp.dpnidPlayer = peer->player_id;
|
|
||||||
dp.pvPlayerContext = peer->player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_HOSTDESTROYEDPLAYER;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
player_to_peer_id.erase(dpnidClient);
|
|
||||||
|
|
||||||
/* Notify the other peers, in case the other peer is malfunctioning and doesn't remove
|
/* Notify the other peers, in case the other peer is malfunctioning and doesn't remove
|
||||||
* itself from the session gracefully.
|
* itself from the session gracefully.
|
||||||
@ -1975,23 +1886,7 @@ HRESULT DirectPlay8Peer::TerminateSession(void* CONST pvTerminateData, CONST DWO
|
|||||||
case STATE_TERMINATED: return DPNERR_HOSTTERMINATEDSESSION;
|
case STATE_TERMINATED: return DPNERR_HOSTTERMINATEDSESSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(discovery_socket != -1)
|
close_main_sockets();
|
||||||
{
|
|
||||||
closesocket(discovery_socket);
|
|
||||||
discovery_socket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(listener_socket != -1)
|
|
||||||
{
|
|
||||||
closesocket(listener_socket);
|
|
||||||
listener_socket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(udp_socket != -1)
|
|
||||||
{
|
|
||||||
closesocket(udp_socket);
|
|
||||||
udp_socket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First, we iterate over all the peers.
|
/* First, we iterate over all the peers.
|
||||||
*
|
*
|
||||||
@ -2051,36 +1946,13 @@ HRESULT DirectPlay8Peer::TerminateSession(void* CONST pvTerminateData, CONST DWO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Raise a DPNMSG_DESTROY_PLAYER for ourself. */
|
/* Raise a DPNMSG_DESTROY_PLAYER for ourself. */
|
||||||
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||||
{
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
|
||||||
dp.dpnidPlayer = local_player_id;
|
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_SESSIONTERMINATED;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Raise a DPNMSG_DESTROY_PLAYER for each connected peer. */
|
/* Raise a DPNMSG_DESTROY_PLAYER for each connected peer. */
|
||||||
|
|
||||||
for(auto cp = closing_peers.begin(); cp != closing_peers.end(); ++cp)
|
for(auto cp = closing_peers.begin(); cp != closing_peers.end(); ++cp)
|
||||||
{
|
{
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
dispatch_destroy_player(l, cp->first, cp->second, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(dp);
|
|
||||||
dp.dpnidPlayer = cp->first;
|
|
||||||
dp.pvPlayerContext = cp->second;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_SESSIONTERMINATED;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy any peers which weren't fully connected. */
|
/* Destroy any peers which weren't fully connected. */
|
||||||
@ -2838,14 +2710,6 @@ void DirectPlay8Peer::peer_destroy(std::unique_lock<std::mutex> &l, unsigned int
|
|||||||
{
|
{
|
||||||
DPNID killed_player_id = peer->player_id;
|
DPNID killed_player_id = peer->player_id;
|
||||||
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(dp);
|
|
||||||
dp.dpnidPlayer = peer->player_id;
|
|
||||||
dp.pvPlayerContext = peer->player_ctx;
|
|
||||||
dp.dwReason = destroy_player_reason;
|
|
||||||
|
|
||||||
/* Bodge to prevent io_peer_send() initiating a graceful shutdown
|
/* Bodge to prevent io_peer_send() initiating a graceful shutdown
|
||||||
* while the application is handling the DPNMSG_DESTROY_PLAYER.
|
* while the application is handling the DPNMSG_DESTROY_PLAYER.
|
||||||
*/
|
*/
|
||||||
@ -2853,9 +2717,7 @@ void DirectPlay8Peer::peer_destroy(std::unique_lock<std::mutex> &l, unsigned int
|
|||||||
|
|
||||||
peer->state = Peer::PS_CLOSING;
|
peer->state = Peer::PS_CLOSING;
|
||||||
|
|
||||||
l.unlock();
|
dispatch_destroy_player(l, peer->player_id, peer->player_ctx, destroy_player_reason);
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
player_to_peer_id.erase(killed_player_id);
|
player_to_peer_id.erase(killed_player_id);
|
||||||
|
|
||||||
@ -2883,17 +2745,7 @@ void DirectPlay8Peer::peer_destroy(std::unique_lock<std::mutex> &l, unsigned int
|
|||||||
message_handler(message_handler_ctx, DPN_MSGID_TERMINATE_SESSION, &ts);
|
message_handler(message_handler_ctx, DPN_MSGID_TERMINATE_SESSION, &ts);
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_NORMAL);
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
|
||||||
dp.dpnidPlayer = local_player_id;
|
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_NORMAL;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
while(!peers.empty())
|
while(!peers.empty())
|
||||||
{
|
{
|
||||||
@ -2925,34 +2777,91 @@ void DirectPlay8Peer::peer_destroy(std::unique_lock<std::mutex> &l, unsigned int
|
|||||||
peer_destroyed.notify_all();
|
peer_destroyed.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Immediately close all sockets and erase all peers. */
|
void DirectPlay8Peer::peer_destroy_all(std::unique_lock<std::mutex> &l, HRESULT outstanding_op_result, DWORD destroy_player_reason)
|
||||||
void DirectPlay8Peer::close_everything_now(std::unique_lock<std::mutex> &l, HRESULT outstanding_op_result, DWORD destroy_player_reason)
|
|
||||||
{
|
{
|
||||||
while(!peers.empty())
|
while(!peers.empty())
|
||||||
{
|
{
|
||||||
peer_destroy(l, peers.begin()->first, outstanding_op_result, destroy_player_reason);
|
unsigned int peer_id = peers.begin()->first;
|
||||||
|
peer_destroy(l, peer_id, outstanding_op_result, destroy_player_reason);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectPlay8Peer::peer_shutdown(std::unique_lock<std::mutex> &l, unsigned int peer_id, HRESULT outstanding_op_result, DWORD destroy_player_reason)
|
||||||
|
{
|
||||||
|
Peer *peer = get_peer_by_peer_id(peer_id);
|
||||||
|
assert(peer != NULL);
|
||||||
|
|
||||||
|
if(peer->state == Peer::PS_CONNECTED)
|
||||||
|
{
|
||||||
|
/* Peer is a fully connected player, initiate a graceful shutdown and raise a
|
||||||
|
* DPNMSG_DESTROY_PLAYER message.
|
||||||
|
*/
|
||||||
|
|
||||||
|
peer->state = Peer::PS_CLOSING;
|
||||||
|
SetEvent(peer->event);
|
||||||
|
|
||||||
|
dispatch_destroy_player(l, peer->player_id, peer->player_ctx, destroy_player_reason);
|
||||||
|
|
||||||
|
player_to_peer_id.erase(peer_id);
|
||||||
|
}
|
||||||
|
else if(peer->state == Peer::PS_CLOSING)
|
||||||
|
{
|
||||||
|
/* We're waiting for this peer to go away. Do nothing. */
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
/* Peer is not a fully fledged player, just destroy it. */
|
||||||
|
peer_destroy(l, peer_id, outstanding_op_result, destroy_player_reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectPlay8Peer::peer_shutdown_all(std::unique_lock<std::mutex> &l, HRESULT outstanding_op_result, DWORD destroy_player_reason)
|
||||||
|
{
|
||||||
|
for(auto p = peers.begin(); p != peers.end();)
|
||||||
|
{
|
||||||
|
unsigned int peer_id = p->first;
|
||||||
|
Peer *peer = p->second;
|
||||||
|
|
||||||
|
if(peer->state == Peer::PS_CLOSING)
|
||||||
|
{
|
||||||
|
/* Peer is already shutting down. Do nothing. */
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
/* Gracefully shutdown or destroy the peer as appropriate. Restart the
|
||||||
|
* loop as any iterator into peers may have been invalidated within the
|
||||||
|
* peer_shutdown() call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
peer_shutdown(l, peer_id, outstanding_op_result, destroy_player_reason);
|
||||||
|
p = peers.begin();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
peer = get_peer_by_peer_id(peer_id);
|
||||||
|
if(peer != NULL)
|
||||||
|
{
|
||||||
|
assert(peer->state == Peer::PS_CLOSING);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectPlay8Peer::close_main_sockets()
|
||||||
|
{
|
||||||
if(discovery_socket != -1)
|
if(discovery_socket != -1)
|
||||||
{
|
{
|
||||||
WSAEventSelect(discovery_socket, other_socket_event, 0);
|
|
||||||
|
|
||||||
closesocket(discovery_socket);
|
closesocket(discovery_socket);
|
||||||
discovery_socket = -1;
|
discovery_socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(listener_socket != -1)
|
if(listener_socket != -1)
|
||||||
{
|
{
|
||||||
WSAEventSelect(listener_socket, other_socket_event, 0);
|
|
||||||
|
|
||||||
closesocket(listener_socket);
|
closesocket(listener_socket);
|
||||||
listener_socket = -1;
|
listener_socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(udp_socket != -1)
|
if(udp_socket != -1)
|
||||||
{
|
{
|
||||||
WSAEventSelect(udp_socket, udp_socket_event, 0);
|
|
||||||
|
|
||||||
closesocket(udp_socket);
|
closesocket(udp_socket);
|
||||||
udp_socket = -1;
|
udp_socket = -1;
|
||||||
}
|
}
|
||||||
@ -3863,56 +3772,27 @@ void DirectPlay8Peer::handle_destroy_peer(std::unique_lock<std::mutex> &l, unsig
|
|||||||
message_handler(message_handler_ctx, DPN_MSGID_TERMINATE_SESSION, &ts);
|
message_handler(message_handler_ctx, DPN_MSGID_TERMINATE_SESSION, &ts);
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
/* Forward destroyed player notification to all peers so they may raise
|
||||||
dp.dpnidPlayer = local_player_id;
|
* DPNMSG_DESTROY_PLAYER with the correct dwReason.
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
*/
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_SESSIONTERMINATED;
|
|
||||||
|
|
||||||
l.unlock();
|
for(auto pi = peers.begin(); pi != peers.end(); ++pi)
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
for(auto pi = peers.begin(); pi != peers.end();)
|
|
||||||
{
|
{
|
||||||
unsigned int peer_id = pi->first;
|
unsigned int peer_id = pi->first;
|
||||||
Peer *peer = pi->second;
|
Peer *peer = pi->second;
|
||||||
|
|
||||||
if(peer->state == Peer::PS_CONNECTED)
|
if(peer->state == Peer::PS_CONNECTED)
|
||||||
{
|
{
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(dp);
|
|
||||||
dp.dpnidPlayer = peer->player_id;
|
|
||||||
dp.pvPlayerContext = peer->player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_SESSIONTERMINATED;
|
|
||||||
|
|
||||||
PacketSerialiser destroy_peer(DPLITE_MSGID_DESTROY_PEER);
|
PacketSerialiser destroy_peer(DPLITE_MSGID_DESTROY_PEER);
|
||||||
destroy_peer.append_dword(local_player_id);
|
destroy_peer.append_dword(local_player_id);
|
||||||
|
|
||||||
peer->sq.send(SendQueue::SEND_PRI_HIGH, destroy_peer, NULL, [](std::unique_lock<std::mutex> &l, HRESULT result) {});
|
peer->sq.send(SendQueue::SEND_PRI_HIGH, destroy_peer, NULL, [](std::unique_lock<std::mutex> &l, HRESULT result) {});
|
||||||
peer->state = Peer::PS_CLOSING;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
pi = peers.begin();
|
|
||||||
}
|
|
||||||
else if(peer->state == Peer::PS_CLOSING)
|
|
||||||
{
|
|
||||||
/* Do nothing. We're waiting for this peer to go away. */
|
|
||||||
++pi;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
peer_destroy(l, peer_id, DPNERR_HOSTTERMINATEDSESSION, DPNDESTROYPLAYERREASON_NORMAL);
|
|
||||||
|
|
||||||
pi = peers.begin();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peer_shutdown_all(l, DPNERR_HOSTTERMINATEDSESSION, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
/* The host called DestroyPeer() on another peer in the session.
|
/* The host called DestroyPeer() on another peer in the session.
|
||||||
@ -3976,55 +3856,9 @@ void DirectPlay8Peer::handle_terminate_session(std::unique_lock<std::mutex> &l,
|
|||||||
message_handler(message_handler_ctx, DPN_MSGID_TERMINATE_SESSION, &ts);
|
message_handler(message_handler_ctx, DPN_MSGID_TERMINATE_SESSION, &ts);
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
peer_shutdown_all(l, DPNERR_HOSTTERMINATEDSESSION, DPNDESTROYPLAYERREASON_SESSIONTERMINATED);
|
||||||
dp.dpnidPlayer = local_player_id;
|
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_SESSIONTERMINATED;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
for(auto pi = peers.begin(); pi != peers.end();)
|
|
||||||
{
|
|
||||||
unsigned int peer_id = pi->first;
|
|
||||||
Peer *peer = pi->second;
|
|
||||||
|
|
||||||
if(peer->state == Peer::PS_CONNECTED)
|
|
||||||
{
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(dp);
|
|
||||||
dp.dpnidPlayer = peer->player_id;
|
|
||||||
dp.pvPlayerContext = peer->player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_SESSIONTERMINATED;
|
|
||||||
|
|
||||||
peer->state = Peer::PS_CLOSING;
|
|
||||||
|
|
||||||
/* Wake up a worker to deal with closing the connection. */
|
|
||||||
SetEvent(peer->event);
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
|
|
||||||
pi = peers.begin();
|
|
||||||
}
|
|
||||||
else if(peer->state == Peer::PS_CLOSING)
|
|
||||||
{
|
|
||||||
/* Do nothing. We're waiting for this peer to go away. */
|
|
||||||
++pi;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
peer_destroy(l, peer_id, DPNERR_USERCANCEL, DPNDESTROYPLAYERREASON_NORMAL);
|
|
||||||
|
|
||||||
pi = peers.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(const PacketDeserialiser::Error &e)
|
catch(const PacketDeserialiser::Error &e)
|
||||||
{
|
{
|
||||||
@ -4106,7 +3940,8 @@ void DirectPlay8Peer::connect_fail(std::unique_lock<std::mutex> &l, HRESULT hRes
|
|||||||
|
|
||||||
state = STATE_CONNECT_FAILED;
|
state = STATE_CONNECT_FAILED;
|
||||||
|
|
||||||
close_everything_now(l, DPNERR_GENERIC, DPNDESTROYPLAYERREASON_CONNECTIONLOST);
|
close_main_sockets();
|
||||||
|
peer_destroy_all(l, DPNERR_GENERIC, DPNDESTROYPLAYERREASON_CONNECTIONLOST);
|
||||||
|
|
||||||
if(old_state == STATE_CONNECTING_TO_PEERS)
|
if(old_state == STATE_CONNECTING_TO_PEERS)
|
||||||
{
|
{
|
||||||
@ -4114,17 +3949,7 @@ void DirectPlay8Peer::connect_fail(std::unique_lock<std::mutex> &l, HRESULT hRes
|
|||||||
* raised DPNMSG_CREATE_PLAYER for the local player. Undo it.
|
* raised DPNMSG_CREATE_PLAYER for the local player. Undo it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DPNMSG_DESTROY_PLAYER dp;
|
dispatch_destroy_player(l, local_player_id, local_player_ctx, DPNDESTROYPLAYERREASON_NORMAL);
|
||||||
memset(&dp, 0, sizeof(dp));
|
|
||||||
|
|
||||||
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
|
||||||
dp.dpnidPlayer = local_player_id;
|
|
||||||
dp.pvPlayerContext = local_player_ctx;
|
|
||||||
dp.dwReason = DPNDESTROYPLAYERREASON_NORMAL;
|
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
message_handler(message_handler_ctx, DPN_MSGID_DESTROY_PLAYER, &dp);
|
|
||||||
l.lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPNMSG_CONNECT_COMPLETE cc;
|
DPNMSG_CONNECT_COMPLETE cc;
|
||||||
@ -4149,6 +3974,44 @@ void DirectPlay8Peer::connect_fail(std::unique_lock<std::mutex> &l, HRESULT hRes
|
|||||||
connect_cv.notify_all();
|
connect_cv.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT DirectPlay8Peer::dispatch_message(std::unique_lock<std::mutex> &l, DWORD dwMessageType, PVOID pvMessage)
|
||||||
|
{
|
||||||
|
l.unlock();
|
||||||
|
HRESULT result = message_handler(message_handler_ctx, dwMessageType, pvMessage);
|
||||||
|
l.lock();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT DirectPlay8Peer::dispatch_create_player(std::unique_lock<std::mutex> &l, DPNID dpnidPlayer, void **ppvPlayerContext)
|
||||||
|
{
|
||||||
|
DPNMSG_CREATE_PLAYER cp;
|
||||||
|
memset(&cp, 0, sizeof(cp));
|
||||||
|
|
||||||
|
cp.dwSize = sizeof(cp);
|
||||||
|
cp.dpnidPlayer = dpnidPlayer;
|
||||||
|
cp.pvPlayerContext = *ppvPlayerContext;
|
||||||
|
|
||||||
|
HRESULT result = dispatch_message(l, DPN_MSGID_CREATE_PLAYER, &cp);
|
||||||
|
|
||||||
|
*ppvPlayerContext = cp.pvPlayerContext;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT DirectPlay8Peer::dispatch_destroy_player(std::unique_lock<std::mutex> &l, DPNID dpnidPlayer, void *pvPlayerContext, DWORD dwReason)
|
||||||
|
{
|
||||||
|
DPNMSG_DESTROY_PLAYER dp;
|
||||||
|
memset(&dp, 0, sizeof(dp));
|
||||||
|
|
||||||
|
dp.dwSize = sizeof(DPNMSG_DESTROY_PLAYER);
|
||||||
|
dp.dpnidPlayer = dpnidPlayer;
|
||||||
|
dp.pvPlayerContext = pvPlayerContext;
|
||||||
|
dp.dwReason = dwReason;
|
||||||
|
|
||||||
|
return dispatch_message(l, DPN_MSGID_DESTROY_PLAYER, &dp);
|
||||||
|
}
|
||||||
|
|
||||||
DirectPlay8Peer::Peer::Peer(enum PeerState state, int sock, uint32_t ip, uint16_t port):
|
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)
|
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)
|
||||||
{}
|
{}
|
||||||
|
@ -197,8 +197,11 @@ class DirectPlay8Peer: public IDirectPlay8Peer
|
|||||||
void peer_accept(std::unique_lock<std::mutex> &l);
|
void peer_accept(std::unique_lock<std::mutex> &l);
|
||||||
bool peer_connect(Peer::PeerState initial_state, uint32_t remote_ip, uint16_t remote_port, DPNID player_id = 0);
|
bool peer_connect(Peer::PeerState initial_state, uint32_t remote_ip, uint16_t remote_port, DPNID player_id = 0);
|
||||||
void peer_destroy(std::unique_lock<std::mutex> &l, unsigned int peer_id, HRESULT outstanding_op_result, DWORD destroy_player_reason);
|
void peer_destroy(std::unique_lock<std::mutex> &l, unsigned int peer_id, HRESULT outstanding_op_result, DWORD destroy_player_reason);
|
||||||
|
void peer_destroy_all(std::unique_lock<std::mutex> &l, HRESULT outstanding_op_result, DWORD destroy_player_reason);
|
||||||
|
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 close_everything_now(std::unique_lock<std::mutex> &l, HRESULT outstanding_op_result, DWORD destroy_player_reason);
|
void close_main_sockets();
|
||||||
|
|
||||||
void handle_host_enum_request(std::unique_lock<std::mutex> &l, const PacketDeserialiser &pd, const struct sockaddr_in *from_addr);
|
void handle_host_enum_request(std::unique_lock<std::mutex> &l, const PacketDeserialiser &pd, const struct sockaddr_in *from_addr);
|
||||||
void handle_host_connect_request(std::unique_lock<std::mutex> &l, unsigned int peer_id, const PacketDeserialiser &pd);
|
void handle_host_connect_request(std::unique_lock<std::mutex> &l, unsigned int peer_id, const PacketDeserialiser &pd);
|
||||||
@ -217,6 +220,10 @@ class DirectPlay8Peer: public IDirectPlay8Peer
|
|||||||
void connect_check(std::unique_lock<std::mutex> &l);
|
void connect_check(std::unique_lock<std::mutex> &l);
|
||||||
void connect_fail(std::unique_lock<std::mutex> &l, HRESULT hResultCode, const void *pvApplicationReplyData, DWORD dwApplicationReplyDataSize);
|
void connect_fail(std::unique_lock<std::mutex> &l, HRESULT hResultCode, const void *pvApplicationReplyData, DWORD dwApplicationReplyDataSize);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DirectPlay8Peer(std::atomic<unsigned int> *global_refcount);
|
DirectPlay8Peer(std::atomic<unsigned int> *global_refcount);
|
||||||
virtual ~DirectPlay8Peer();
|
virtual ~DirectPlay8Peer();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user