mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
DirectPlay: Refactor worker loop.
Hold the lock while reading to ensure the socket isn't closed during the recvfrom() call, allow either socket to be closed and close either socket if the recvfrom() call fails.
This commit is contained in:
parent
a89948c2f9
commit
8ded8da35a
@ -66,30 +66,55 @@ static void release_sp_data(struct sp_data *data) {
|
||||
LeaveCriticalSection(&(data->lock));
|
||||
}
|
||||
|
||||
static BOOL recv_packet(int sockfd, char *buf, IDirectPlaySP *sp) {
|
||||
static void recv_packet(SOCKET *sockfd, char *buf, IDirectPlaySP *sp)
|
||||
{
|
||||
struct sp_data *sp_data = get_sp_data((IDirectPlaySP*)(sp));
|
||||
|
||||
if(*sockfd == -1)
|
||||
{
|
||||
release_sp_data(sp_data);
|
||||
return;
|
||||
}
|
||||
|
||||
struct sockaddr_ipx addr;
|
||||
int addrlen = sizeof(addr);
|
||||
|
||||
int r = recvfrom(sockfd, buf, MAX_DATA_SIZE, 0, (struct sockaddr*)&addr, &addrlen);
|
||||
if(r == -1) {
|
||||
if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET) {
|
||||
return TRUE;
|
||||
int size = recvfrom(*sockfd, buf, MAX_DATA_SIZE, 0, (struct sockaddr*)(&addr), &addrlen);
|
||||
if(size == -1)
|
||||
{
|
||||
if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET)
|
||||
{
|
||||
/* WSAEWOULDBLOCK - No packets waiting on this socket.
|
||||
* WSAECONNRESET - We got an ICMP error on this port.
|
||||
*/
|
||||
release_sp_data(sp_data);
|
||||
return;
|
||||
}
|
||||
|
||||
log_printf(LOG_ERROR, "Read error (IPX): %s", w32_error(WSAGetLastError()));
|
||||
return FALSE;
|
||||
log_printf(LOG_ERROR, "DirectPlay read error: %s", w32_error(WSAGetLastError()));
|
||||
log_printf(LOG_DEBUG, "Closing socket %u", (unsigned int)(*sockfd));
|
||||
|
||||
closesocket(*sockfd);
|
||||
*sockfd = -1;
|
||||
|
||||
release_sp_data(sp_data);
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT h = IDirectPlaySP_HandleMessage(sp, buf, r, &addr);
|
||||
if(h != DP_OK) {
|
||||
log_printf(LOG_ERROR, "HandleMessage error: %d", (int)h);
|
||||
}
|
||||
release_sp_data(sp_data);
|
||||
|
||||
return TRUE;
|
||||
/* Pass the message on to DirectPlay to be processed. */
|
||||
|
||||
IPX_STRING_ADDR(str_addr, addr32_in(addr.sa_netnum), addr48_in(addr.sa_nodenum), addr.sa_socket);
|
||||
log_printf(LOG_DEBUG, "About to HandleMessage from %s", str_addr);
|
||||
|
||||
HRESULT r = IDirectPlaySP_HandleMessage(sp, buf, size, &addr);
|
||||
|
||||
log_printf(LOG_DEBUG, "HandleMessage returned %x", (unsigned int)(r));
|
||||
}
|
||||
|
||||
static DWORD WINAPI worker_main(LPVOID sp) {
|
||||
struct sp_data *sp_data = get_sp_data((IDirectPlaySP*)sp);
|
||||
struct sp_data *sp_data = get_sp_data((IDirectPlaySP*)(sp));
|
||||
release_sp_data(sp_data);
|
||||
|
||||
char *buf = malloc(MAX_DATA_SIZE);
|
||||
@ -100,33 +125,23 @@ static DWORD WINAPI worker_main(LPVOID sp) {
|
||||
while(1) {
|
||||
WaitForSingleObject(sp_data->event, INFINITE);
|
||||
|
||||
get_sp_data((IDirectPlaySP*)sp);
|
||||
get_sp_data((IDirectPlaySP*)(sp));
|
||||
|
||||
WSAResetEvent(sp_data->event);
|
||||
|
||||
if(!sp_data->running) {
|
||||
release_sp_data(sp_data);
|
||||
return 0;
|
||||
if(!sp_data->running)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
release_sp_data(sp_data);
|
||||
|
||||
if(!recv_packet(sp_data->sock, buf, sp)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(sp_data->ns_sock != -1 && !recv_packet(sp_data->ns_sock, buf, sp)) {
|
||||
log_printf(LOG_ERROR, "Closing ns_sock due to error");
|
||||
|
||||
get_sp_data((IDirectPlaySP*)sp);
|
||||
|
||||
closesocket(sp_data->ns_sock);
|
||||
sp_data->ns_sock = -1;
|
||||
|
||||
release_sp_data(sp_data);
|
||||
}
|
||||
recv_packet(&(sp_data->sock), buf, sp);
|
||||
recv_packet(&(sp_data->ns_sock), buf, sp);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user