Skip to content

Commit

Permalink
feat(winapi): add winsock2
Browse files Browse the repository at this point in the history
Co-Authored-By: Jannik Vogel <[email protected]>
  • Loading branch information
ReenigneArcher and JayFoxRox committed Oct 19, 2024
1 parent 56cdc3d commit ef6b420
Show file tree
Hide file tree
Showing 4 changed files with 331 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/winapi/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include $(NXDK_DIR)/lib/winapi/winmm/Makefile
include $(NXDK_DIR)/lib/winapi/ws2_32/Makefile

WINAPI_SRCS := \
$(NXDK_DIR)/lib/winapi/badptr.c \
Expand Down
19 changes: 19 additions & 0 deletions lib/winapi/ws2_32/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
NXDK_NET=y

WS2_32_SRCS := \
$(wildcard $(NXDK_DIR)/lib/winapi/ws2_32/*.c)

WS2_32_OBJS = $(addsuffix .obj, $(basename $(WS2_32_SRCS)))

NXDK_CFLAGS += -I$(NXDK_DIR)/lib/winapi/ws2_32 -I$(NXDK_DIR)/lib/net/pktdrv
NXDK_CXXFLAGS += -I$(NXDK_DIR)/lib/winapi/ws2_32 -I$(NXDK_DIR)/lib/net/pktdrv

$(NXDK_DIR)/lib/ws2_32.lib: $(WS2_32_OBJS)

main.exe: $(NXDK_DIR)/lib/ws2_32.lib

CLEANRULES += clean-ws2_32

.PHONY: clean-ws2_32
clean-ws2_32:
$(VE)rm -f $(WS2_32_OBJS) $(NXDK_DIR)/lib/ws2_32.lib
232 changes: 232 additions & 0 deletions lib/winapi/ws2_32/winsock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#define DHCP


#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include <lwip/debug.h>
#ifdef DHCP
#include <lwip/dhcp.h>
#else
#include <lwip/autoip.h>
#endif
#include <lwip/init.h>
#include <lwip/netif.h>
#include <lwip/sys.h>
#include <lwip/tcpip.h>
#include <lwip/timeouts.h>
#include <netif/etharp.h>
#include <pktdrv.h>
#include <xboxkrnl/xboxkrnl.h>

#include <hal/debug.h>

#include "winsock2.h"


#define PKT_TMR_INTERVAL 5 /* ms */
#define DEBUGGING 0

struct netif nforce_netif, *g_pnetif;

err_t nforceif_init(struct netif *netif);
static void packet_timer(void *arg);

static void tcpip_init_done(void *arg)
{
sys_sem_t *init_complete = arg;
sys_sem_signal(init_complete);
}

static void packet_timer(void *arg)
{
LWIP_UNUSED_ARG(arg);
Pktdrv_ReceivePackets();
sys_timeout(PKT_TMR_INTERVAL, packet_timer, NULL);
}

#include <windows.h>
#include <assert.h>

static int map_error_to_winsock(int error) {
switch(error) {
#define MAP_ERROR(error_name) case error_name: return WSA ## error_name;
#undef MAP_ERROR
default:
debugPrint("unhandled error: %d\n", error);
assert(0);
break;
}
return -1;
}


int WSAStartup(
WORD wVersionRequired,
LPWSADATA lpWSAData
) {
assert(wVersionRequired == MAKEDWORD(1,1));
lpWSAData->wVersion = wVersionRequired;
lpWSAData->wHighVersion = MAKEDWORD(1,1);





sys_sem_t init_complete;
const ip4_addr_t *ip;
static ip4_addr_t ipaddr, netmask, gw;

#if DEBUGGING
asm volatile ("jmp .");
debug_flags = LWIP_DBG_ON;
#else
debug_flags = 0;
#endif

/* Initialize the TCP/IP stack. Wait for completion. */
sys_sem_new(&init_complete, 0);
tcpip_init(tcpip_init_done, &init_complete);
sys_sem_wait(&init_complete);
sys_sem_free(&init_complete);

g_pnetif = netif_add(&nforce_netif, &ipaddr, &netmask, &gw,
NULL, nforceif_init, ethernet_input);
if (!g_pnetif) {
debugPrint("netif_add failed\n");
return 1;
}

netif_set_default(g_pnetif);
netif_set_up(g_pnetif);

#ifdef DHCP
dhcp_start(g_pnetif);
#else
autoip_start(g_pnetif);
#endif

packet_timer(NULL);


#ifdef DHCP
debugPrint("Waiting for IP (DHCP)...\n");
while (dhcp_supplied_address(g_pnetif) == 0)
NtYieldExecution();
#else
debugPrint("Waiting for IP (AUTOIP)...\n");
while (autoip_supplied_address(g_pnetif) == 0)
NtYieldExecution();
#endif
debugPrint("IP bound!\n");

debugPrint("\n");
debugPrint("IP address.. %s\n", ip4addr_ntoa(netif_ip4_addr(g_pnetif)));
debugPrint("Mask........ %s\n", ip4addr_ntoa(netif_ip4_netmask(g_pnetif)));
debugPrint("Gateway..... %s\n", ip4addr_ntoa(netif_ip4_gw(g_pnetif)));
debugPrint("\n");



return 0;
}


static int last_winsock_error = 0;

int WSAGetLastError() {
return last_winsock_error;
}

void WSASetLastError(
int iError
) {
last_winsock_error = iError;
}

int WSAAPI WSASendTo(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
const sockaddr *lpTo,
int iTolen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
) {
assert(lpOverlapped == NULL);
assert(lpCompletionRoutine == NULL);

int flags = dwFlags; //FIXME: Should we filter certain flags?

struct iovec *iov = __builtin_alloca(sizeof(struct iovec) * dwBufferCount);
for(int i = 0; i < dwBufferCount; i++) {
iov[i].iov_base = lpBuffers[i].buf;
iov[i].iov_len = lpBuffers[i].len;
}

struct msghdr msg;

msg.msg_name = (const sockaddr *)lpTo;
msg.msg_namelen = iTolen;
msg.msg_iov = iov;
msg.msg_iovlen = dwBufferCount;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
ssize_t ret = sendmsg(s, &msg, flags);
if (ret == -1) {
WSASetLastError(map_error_to_winsock(errno));
return SOCKET_ERROR;
}

*lpNumberOfBytesSent = ret;

return 0;
}

int WSAAPI WSARecvFrom(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
sockaddr *lpFrom,
LPINT lpFromlen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
) {
assert(lpOverlapped == NULL);
assert(lpCompletionRoutine == NULL);
assert(dwBufferCount == 1);

int flags = *lpFlags; //FIXME: Should we filter certain flags?

struct iovec *iov = __builtin_alloca(sizeof(struct iovec) * dwBufferCount);
for(int i = 0; i < dwBufferCount; i++) {
iov[i].iov_base = lpBuffers[i].buf;
iov[i].iov_len = lpBuffers[i].len;
}

struct msghdr msg;

msg.msg_name = (const sockaddr *)lpFrom;
msg.msg_namelen = *lpFromlen;
msg.msg_iov = iov;
msg.msg_iovlen = dwBufferCount;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
ssize_t ret = recvmsg(s, &msg, flags);
if (ret == -1) {
WSASetLastError(map_error_to_winsock(errno));
return SOCKET_ERROR;
}

*lpFromlen = msg.msg_namelen; //FIXME: Is this updated? It almost certainly isn't winsock behaviour
*lpFlags = msg.msg_flags;
*lpNumberOfBytesRecvd = ret;

return 0;
}
79 changes: 79 additions & 0 deletions lib/winapi/ws2_32/winsock2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@

typedef unsigned long u_long;

// We do not support this
#define gethostbyaddr(...) NULL
#define WSACleanup(...) Pktdrv_Quit()

#define SOMAXCONN 128

#define MSG_PARTIAL 0

#include <lwip/sockets.h>
#include <lwip/netdb.h>

#include <windows.h>

#define WSAAPI

#define MAKEDWORD(...) 1
#define HIBYTE(...) 1
#define LOBYTE(...) 1
#define MAKEWORD(...) 1

typedef int SOCKET;
#define INVALID_SOCKET ((SOCKET)-1)
#define SOCKET_ERROR -1

typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
//FIXME: There's potentially more here
} WSADATA;

typedef struct sockaddr sockaddr;

typedef WSADATA *LPWSADATA;

typedef void *LPWSAOVERLAPPED_COMPLETION_ROUTINE; //FIXME: !!!
typedef void *LPWSAOVERLAPPED; //FIXME: !!!

int WSAStartup(
WORD wVersionRequired,
LPWSADATA lpWSAData
);

typedef struct _WSABUF {
ULONG len;
CHAR *buf;
} WSABUF, *LPWSABUF;

int WSAGetLastError();

void WSASetLastError(
int iError
);

int WSAAPI WSASendTo(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
const sockaddr *lpTo,
int iTolen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

int WSAAPI WSARecvFrom(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
sockaddr *lpFrom,
LPINT lpFromlen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

0 comments on commit ef6b420

Please sign in to comment.