1
0
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:
Daniel Collins 2011-09-08 22:23:00 +00:00
parent 431d0b8047
commit f837ac123d
2 changed files with 96 additions and 19 deletions

View File

@ -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);

View File

@ -14,3 +14,8 @@ EXPORTS
EnumProtocolsW
WSARecvEx
ioctlsocket
WSACreateEvent
WSACloseEvent
WSAEventSelect
WSAResetEvent