mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Continued DirectPlay code tweaks
This commit is contained in:
parent
431d0b8047
commit
f837ac123d
110
src/directplay.c
110
src/directplay.c
@ -35,8 +35,9 @@ struct sp_data {
|
||||
struct sockaddr_ipx ns_addr; /* sa_family is 0 when undefined */
|
||||
DPID ns_id;
|
||||
|
||||
BOOL running;
|
||||
HANDLE worker_thread;
|
||||
DWORD worker_tid;
|
||||
WSAEVENT event;
|
||||
};
|
||||
|
||||
struct sp_data_cont {
|
||||
@ -83,12 +84,31 @@ static void release_sp_data(IDirectPlaySP *sp) {
|
||||
ReleaseMutex(cont->mutex);
|
||||
}
|
||||
|
||||
static DWORD WINAPI worker_main(LPVOID arg) {
|
||||
struct sp_data *sp_data = get_sp_data((IDirectPlaySP*)arg);
|
||||
static BOOL recv_packet(int sockfd, char *buf, IDirectPlaySP *sp) {
|
||||
struct sockaddr_ipx addr;
|
||||
int addrlen = sizeof(addr);
|
||||
|
||||
int sockfd = sp_data->sock;
|
||||
int r = recvfrom(sockfd, buf, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen);
|
||||
if(r == -1) {
|
||||
if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
log_printf("Read error (IPX): %s", w32_error(WSAGetLastError()));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
release_sp_data((IDirectPlaySP*)arg);
|
||||
HRESULT h = IDirectPlaySP_HandleMessage(sp, buf, r, &addr);
|
||||
if(h != DP_OK) {
|
||||
log_printf("HandleMessage error: %d", (int)h);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DWORD WINAPI worker_main(LPVOID sp) {
|
||||
struct sp_data *sp_data = get_sp_data((IDirectPlaySP*)sp);
|
||||
release_sp_data((IDirectPlaySP*)sp);
|
||||
|
||||
char *buf = malloc(PACKET_BUF_SIZE);
|
||||
if(!buf) {
|
||||
@ -96,19 +116,26 @@ static DWORD WINAPI worker_main(LPVOID arg) {
|
||||
}
|
||||
|
||||
while(1) {
|
||||
struct sockaddr_ipx addr;
|
||||
int addrlen = sizeof(addr);
|
||||
WaitForSingleObject(sp_data->event, INFINITE);
|
||||
|
||||
int r = recvfrom(sockfd, buf, PACKET_BUF_SIZE, 0, (struct sockaddr*)&addr, &addrlen);
|
||||
if(r == -1) {
|
||||
log_printf("recv failed");
|
||||
get_sp_data((IDirectPlaySP*)sp);
|
||||
|
||||
WSAResetEvent(sp_data->event);
|
||||
|
||||
if(!sp_data->running) {
|
||||
release_sp_data((IDirectPlaySP*)sp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT h = IDirectPlaySP_HandleMessage((IDirectPlaySP*)arg, buf, r, &addr);
|
||||
if(h != DP_OK) {
|
||||
log_printf("HandleMessage error: %d", (int)h);
|
||||
if(!recv_packet(sp_data->sock, buf, sp)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(sp_data->ns_sock != -1 && recv_packet(sp_data->ns_sock, buf, sp)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
release_sp_data((IDirectPlaySP*)sp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -122,7 +149,7 @@ static BOOL init_worker(IDirectPlaySP *sp) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sp_data->worker_thread = CreateThread(NULL, 0, &worker_main, sp, 0, &(sp_data->worker_tid));
|
||||
sp_data->worker_thread = CreateThread(NULL, 0, &worker_main, sp, 0, NULL);
|
||||
if(!sp_data->worker_thread) {
|
||||
log_printf("Failed to create worker thread");
|
||||
|
||||
@ -319,8 +346,9 @@ static HRESULT WINAPI IPX_Open(LPDPSP_OPENDATA data) {
|
||||
return DPERR_CANNOTCREATESERVER;
|
||||
}
|
||||
|
||||
BOOL reuse = TRUE;
|
||||
setsockopt(sp_data->ns_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(BOOL));
|
||||
BOOL t_bool = TRUE;
|
||||
setsockopt(sp_data->ns_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&t_bool, sizeof(BOOL));
|
||||
setsockopt(sp_data->ns_sock, SOL_SOCKET, SO_BROADCAST, (char*)&t_bool, sizeof(BOOL));
|
||||
|
||||
struct sockaddr_ipx addr;
|
||||
|
||||
@ -336,6 +364,16 @@ static HRESULT WINAPI IPX_Open(LPDPSP_OPENDATA data) {
|
||||
log_printf("Cannot bind ns_sock: %s", w32_error(WSAGetLastError()));
|
||||
return DPERR_CANNOTCREATESERVER;
|
||||
}
|
||||
|
||||
if(WSAEventSelect(sp_data->sock, sp_data->event, FD_READ) == -1) {
|
||||
closesocket(sp_data->ns_sock);
|
||||
sp_data->ns_sock = -1;
|
||||
|
||||
release_sp_data(data->lpISP);
|
||||
|
||||
log_printf("WSAEventSelect failed: %s", w32_error(WSAGetLastError()));
|
||||
return DPERR_CANNOTCREATESERVER;
|
||||
}
|
||||
}
|
||||
}else if(data->lpSPMessageHeader) {
|
||||
memcpy(&(sp_data->ns_addr), data->lpSPMessageHeader, sizeof(struct sockaddr_ipx));
|
||||
@ -365,14 +403,25 @@ static HRESULT WINAPI IPX_ShutdownEx(LPDPSP_SHUTDOWNDATA data) {
|
||||
|
||||
struct sp_data *sp_data = get_sp_data(data->lpISP);
|
||||
|
||||
if(sp_data->worker_thread && GetCurrentThreadId() != sp_data->worker_tid) {
|
||||
TerminateThread(sp_data->worker_thread, 0);
|
||||
if(sp_data->worker_thread) {
|
||||
sp_data->running = FALSE;
|
||||
|
||||
release_sp_data(data->lpISP);
|
||||
|
||||
if(WaitForSingleObject(sp_data->worker_thread, 3000) == WAIT_TIMEOUT) {
|
||||
log_printf("DirectPlay worker didn't exit in 3 seconds, killing");
|
||||
TerminateThread(sp_data->worker_thread, 0);
|
||||
}
|
||||
|
||||
sp_data->worker_thread = NULL;
|
||||
}
|
||||
|
||||
closesocket(sp_data->sock);
|
||||
|
||||
release_sp_data(data->lpISP);
|
||||
if(sp_data->ns_sock != -1) {
|
||||
closesocket(sp_data->ns_sock);
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
@ -412,7 +461,15 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) {
|
||||
return DPERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
if((sp_data->event = WSACreateEvent()) == WSA_INVALID_EVENT) {
|
||||
CloseHandle(mutex);
|
||||
free(sp_data);
|
||||
|
||||
return DPERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
if((sp_data->sock = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1) {
|
||||
WSACloseEvent(sp_data->event);
|
||||
CloseHandle(mutex);
|
||||
free(sp_data);
|
||||
|
||||
@ -426,6 +483,7 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) {
|
||||
|
||||
if(bind(sp_data->sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
closesocket(sp_data->sock);
|
||||
WSACloseEvent(sp_data->event);
|
||||
CloseHandle(mutex);
|
||||
free(sp_data);
|
||||
|
||||
@ -438,6 +496,7 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) {
|
||||
log_printf("getsockname failed: %s", w32_error(WSAGetLastError()));
|
||||
|
||||
closesocket(sp_data->sock);
|
||||
WSACloseEvent(sp_data->event);
|
||||
CloseHandle(mutex);
|
||||
free(sp_data);
|
||||
|
||||
@ -446,11 +505,23 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) {
|
||||
|
||||
sp_data->ns_sock = -1;
|
||||
sp_data->ns_addr.sa_family = 0;
|
||||
sp_data->running = TRUE;
|
||||
sp_data->worker_thread = NULL;
|
||||
|
||||
BOOL bcast = TRUE;
|
||||
setsockopt(sp_data->sock, SOL_SOCKET, SO_BROADCAST, (char*)&bcast, sizeof(BOOL));
|
||||
|
||||
if(WSAEventSelect(sp_data->sock, sp_data->event, FD_READ) == -1) {
|
||||
log_printf("WSAEventSelect failed: %s", w32_error(WSAGetLastError()));
|
||||
|
||||
closesocket(sp_data->sock);
|
||||
WSACloseEvent(sp_data->event);
|
||||
CloseHandle(mutex);
|
||||
free(sp_data);
|
||||
|
||||
return DPERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
struct sp_data_cont cont;
|
||||
cont.data = sp_data;
|
||||
cont.mutex = mutex;
|
||||
@ -460,6 +531,7 @@ HRESULT WINAPI SPInit(LPSPINITDATA data) {
|
||||
log_printf("SetSPData: %d", (int)r);
|
||||
|
||||
closesocket(sp_data->sock);
|
||||
WSACloseEvent(sp_data->event);
|
||||
CloseHandle(mutex);
|
||||
free(sp_data);
|
||||
|
||||
|
@ -14,3 +14,8 @@ EXPORTS
|
||||
EnumProtocolsW
|
||||
WSARecvEx
|
||||
ioctlsocket
|
||||
|
||||
WSACreateEvent
|
||||
WSACloseEvent
|
||||
WSAEventSelect
|
||||
WSAResetEvent
|
||||
|
Loading…
x
Reference in New Issue
Block a user