Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMake samples #84

Open
wants to merge 2 commits into
base: cmake
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ws2_32 should be split from this PR, cleaned, polished, and upstreamed.

Maybe @dracc or @Teufelchen1 (also @thrimbor or @Ryzee119, but those got too many tasks already)


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
NXDK_CXXFLAGS += -I$(NXDK_DIR)/lib/winapi/ws2_32

$(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
);
1 change: 1 addition & 0 deletions samples/cmake/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
3 changes: 3 additions & 0 deletions samples/cmake/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Dummy file, so the CI doesn't trip
# Ideally this should be building the CMake projects on CI
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

all:
50 changes: 50 additions & 0 deletions samples/cmake/enet/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
if(NXDK)
# Hack for winsock2.h and mmsystem.h
include_directories(SYSTEM "${NXDK_DIR}/lib/winapi/ws2_32;${NXDK_DIR}/lib/winapi/winmm")
Copy link
Owner Author

@JayFoxRox JayFoxRox Apr 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be part of default includes; I believe this is an upstream nxdk bug which will have to be integrated in #82

(speaking about winmm; obviously ws2_32 is a separate issue as it's part of this PR)


# Create lwip import lib
add_subdirectory(${NXDK_DIR}/lib/net/lwip "${CMAKE_BINARY_DIR}/lwip/")
get_target_property(LWIPCORE_INCLUDES lwipcore INCLUDE_DIRECTORIES)
message("${LWIPCORE_INCLUDES}")
set_target_properties(lwipcore
PROPERTIES INCLUDE_DIRECTORIES "${NXDK_DIR}/lib/net/lwip/src/include/;${NXDK_DIR}/lib/net/nforceif/include/")
set_target_properties(lwipcore
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${NXDK_DIR}/lib/net/lwip/src/include/;${NXDK_DIR}/lib/net/nforceif/include/")
get_target_property(LWIPCORE_INCLUDES lwipcore INCLUDE_DIRECTORIES)
message("${LWIPCORE_INCLUDES}")

# Add pktdrv
add_library(pktdrv ${NXDK_DIR}/lib/net/pktdrv/pktdrv.c)
target_include_directories(pktdrv PUBLIC ${NXDK_DIR}/lib/net/pktdrv/)

# Combine lwip and Xbox driver into libnet
add_library(net
"${NXDK_DIR}/lib/net/nforceif/src/driver.c"
"${NXDK_DIR}/lib/net/nforceif/src/sys_arch.c"
)
target_link_libraries(net lwipcore pktdrv)
endif()
Copy link
Owner Author

@JayFoxRox JayFoxRox Apr 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Combine lwip and Xbox driver into libnet

This should be part of nxdk, not of this sample.
Reported as upstream issue 454.

Copy link
Owner Author

@JayFoxRox JayFoxRox Apr 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Teufelchen1: This is probably a good task for you
Maybe a challenge for @kosmas12 if @Teufelchen1 doesn't want to do this.

(nxdk issue 454: "Network stack should be a static library")


# Add enet and fix a bug in enet where include folder is not known to itself
add_subdirectory(enet)
set_target_properties(enet
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/enet/include/")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is broken due to https://github.com/lsalzman/enet/blame/master/CMakeLists.txt#L58 using the wrong variable?

However, it should not be setting include directories for all targets anyway


if(NXDK)
# Make enet depend on Xbox network
set_target_properties(enet
PROPERTIES LINK_LIBRARIES "${NXDK_DIR}/lib/ws2_32.lib;${NXDK_DIR}/lib/winmm.lib;net")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't ws2_32 and winmm already deps of enet or the net library?
Should be fixed (upstream potentially?)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

endif()

# Build project
add_executable(server server.c)
target_link_libraries(server enet)
add_executable(client client.c)
target_link_libraries(client enet)
if(NXDK)
add_executable(default main.c)
endif()

if(NXDK)
create_xiso("${CMAKE_BINARY_DIR}/enet.iso" "${CMAKE_BINARY_DIR}/")
endif()
Loading