PS2: Not really working networking

This commit is contained in:
UnknownShadow200 2023-11-25 10:37:23 +11:00
parent 4b3e520ec3
commit ae52ab9761
3 changed files with 225 additions and 16 deletions

View File

@ -4,7 +4,7 @@ CFILES := $(wildcard src/*.c)
OBJS :=$(patsubst %.c, %.o, $(CFILES))
EE_BIN = ClassiCube-ps2.elf
EE_OBJS = $(OBJS)
EE_OBJS = $(OBJS) DEV9_irx.o NETMAN_irx.o SMAP_irx.o
EE_LIBS = -lpatches -lpad -lpacket -ldma -lgraph -ldraw -lc
EE_CFLAGS = -DPLAT_PS2
@ -12,6 +12,15 @@ all: $(EE_BIN)
clean:
rm -f $(EE_BIN) $(EE_OBJS)
DEV9_irx.c: $(PS2SDK)/iop/irx/ps2dev9.irx
bin2c $< DEV9_irx.c DEV9_irx
NETMAN_irx.c: $(PS2SDK)/iop/irx/netman.irx
bin2c $< NETMAN_irx.c NETMAN_irx
SMAP_irx.c: $(PS2SDK)/iop/irx/smap.irx
bin2c $< SMAP_irx.c SMAP_irx
include $(PS2SDK)/samples/Makefile.pref
include $(PS2SDK)/samples/Makefile.eeglobal

View File

@ -197,7 +197,7 @@ cc_result File_Length(cc_file file, cc_uint32* len) {
/*########################################################################################################################*
*--------------------------------------------------------Threading--------------------------------------------------------*
*#########################################################################################################################*/
// !!! NOTE: Dreamcast uses cooperative multithreading (not preemptive multithreading) !!!
// !!! NOTE: Dreamcast is configured to use preemptive multithreading !!!
void Thread_Sleep(cc_uint32 milliseconds) {
thd_sleep(milliseconds);
}

View File

@ -29,13 +29,13 @@
#include <loadfile.h>
#include <iopcontrol.h>
#include <sbv_patches.h>
#include <netman.h>
#include <ps2ip.h>
#include "_PlatformConsole.h"
const cc_result ReturnCode_FileShareViolation = 1000000000; // not used
const cc_result ReturnCode_FileNotFound = 0x80010006; // ENOENT;
//const cc_result ReturnCode_SocketInProgess = 0x80010032; // EINPROGRESS
//const cc_result ReturnCode_SocketWouldBlock = 0x80010001; // EWOULDBLOCK;
const cc_result ReturnCode_DirectoryExists = 0x80010014; // EEXIST
const cc_result ReturnCode_FileNotFound = ENOENT;
const cc_result ReturnCode_DirectoryExists = EEXIST;
const cc_result ReturnCode_SocketInProgess = EINPROGRESS;
const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK;
@ -337,41 +337,240 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
/*########################################################################################################################*
*-------------------------------------------------------Networking--------------------------------------------------------*
*#########################################################################################################################*/
// https://github.com/ps2dev/ps2sdk/blob/master/NETMAN.txt
// https://github.com/ps2dev/ps2sdk/blob/master/ee/network/tcpip/samples/tcpip_dhcp/ps2ip.c
extern unsigned char DEV9_irx[];
extern unsigned int size_DEV9_irx;
extern unsigned char SMAP_irx[];
extern unsigned int size_SMAP_irx;
extern unsigned char NETMAN_irx[];
extern unsigned int size_NETMAN_irx;
static void ethStatusCheckCb(s32 alarm_id, u16 time, void *common) {
int threadID = *(int*)common;
iWakeupThread(threadID);
}
static int WaitValidNetState(int (*checkingFunction)(void)) {
// Wait for a valid network status
int threadID = GetThreadId();
for (int retries = 0; checkingFunction() == 0; retries++)
{
// Sleep for 500ms
SetAlarm(500 * 16, &ethStatusCheckCb, &threadID);
SleepThread();
if (retries >= 10) // 5s = 10 * 500ms
return -1;
}
return 0;
}
static int ethGetNetIFLinkStatus(void) {
return NetManIoctl(NETMAN_NETIF_IOCTL_GET_LINK_STATUS, NULL, 0, NULL, 0) == NETMAN_NETIF_ETH_LINK_STATE_UP;
}
static int ethWaitValidNetIFLinkState(void) {
return WaitValidNetState(&ethGetNetIFLinkStatus);
}
static int ethGetDHCPStatus(void) {
t_ip_info ip_info;
int result;
if ((result = ps2ip_getconfig("sm0", &ip_info)) < 0) return result;
if (ip_info.dhcp_enabled) {
return ip_info.dhcp_status == DHCP_STATE_BOUND || ip_info.dhcp_status == DHCP_STATE_OFF;
}
return -1;
}
static int ethWaitValidDHCPState(void) {
return WaitValidNetState(&ethGetDHCPStatus);
}
static int ethEnableDHCP(void) {
t_ip_info ip_info;
int result;
// SMAP is registered as the "sm0" device to the TCP/IP stack.
if ((result = ps2ip_getconfig("sm0", &ip_info)) < 0) return result;
if (!ip_info.dhcp_enabled) {
ip_info.dhcp_enabled = 1;
return ps2ip_setconfig(&ip_info);
}
return 0;
}
static void SetupNetworking(void) {
struct ip4_addr IP = { 0 }, NM = { 0 }, GW = { 0 };
ps2ipInit(&IP, &NM, &GW);
ethEnableDHCP();
Platform_LogConst("Waiting for net link connection...");
if(ethWaitValidNetIFLinkState() != 0) {
Platform_LogConst("Failed to establish net link");
return;
}
Platform_LogConst("Waiting for DHCP lease...");
if (ethWaitValidDHCPState() != 0) {
Platform_LogConst("Failed to acquire DHCP lease");
return;
}
Platform_LogConst("Network setup done");
}
static void InitNetworking(void) {
//SifExecModuleBuffer(DEV9_irx, size_DEV9_irx, 0, NULL, NULL);
//SifExecModuleBuffer(NETMAN_irx, size_NETMAN_irx, 0, NULL, NULL);
//SifExecModuleBuffer(SMAP_irx, size_SMAP_irx, 0, NULL, NULL);
//NetManInit();
SifExecModuleBuffer(DEV9_irx, size_DEV9_irx, 0, NULL, NULL);
SifExecModuleBuffer(NETMAN_irx, size_NETMAN_irx, 0, NULL, NULL);
SifExecModuleBuffer(SMAP_irx, size_SMAP_irx, 0, NULL, NULL);
NetManInit();
}
/*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/
union SocketAddress {
struct sockaddr raw;
struct sockaddr_in v4;
};
static int ParseHost(union SocketAddress* addr, const char* host) {
struct addrinfo hints = { 0 };
struct addrinfo* result;
struct addrinfo* cur;
int found = false;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int res = getaddrinfo(host, NULL, &hints, &result);
if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST;
if (res) return res;
for (cur = result; cur; cur = cur->ai_next) {
if (cur->ai_family != AF_INET) continue;
found = true;
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen);
break;
}
freeaddrinfo(result);
return found ? 0 : ERR_INVALID_ARGUMENT;
}
static int ParseAddress(union SocketAddress* addr, const cc_string* address) {
char str[NATIVE_STR_LEN];
String_EncodeUtf8(str, address);
if (inet_aton(str, &addr->v4.sin_addr) > 0) return 0;
return ParseHost(addr, str);
}
int Socket_ValidAddress(const cc_string* address) {
return false;
union SocketAddress addr;
return ParseAddress(&addr, address) == 0;
}
static cc_result GetSocketError(cc_socket s) {
socklen_t resultSize = sizeof(socklen_t);
cc_result res = 0;
getsockopt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize);
return res;
}
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
return ERR_NOT_SUPPORTED;
union SocketAddress addr;
int res;
*s = -1;
if ((res = ParseAddress(&addr, address))) return res;
*s = socket(AF_INET, SOCK_STREAM, 0);
if (*s < 0) return *s;
if (nonblocking) {
int blocking_raw = -1; // non-blocking mode
//ioctlsocket(*s, FIONBIO, &blocking_raw); TODO doesn't work
}
addr.v4.sin_family = AF_INET;
addr.v4.sin_port = htons(port);
res = connect(*s, &addr.raw, sizeof(addr.v4));
return res == -1 ? GetSocketError(*s) : 0;
}
cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
return ERR_NOT_SUPPORTED;
Platform_Log1("PREPARE TO READ: %i", &count);
int recvCount = recv(s, data, count, 0);
Platform_Log1(" .. read %i", &recvCount);
if (recvCount != -1) { *modified = recvCount; return 0; }
int ERR = GetSocketError(s);
Platform_Log1("ERR: %i", &ERR);
*modified = 0; return ERR;
}
cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
return ERR_NOT_SUPPORTED;
Platform_Log1("PREPARE TO WRITE: %i", &count);
int sentCount = send(s, data, count, 0);
Platform_Log1(" .. wrote %i", &sentCount);
if (sentCount != -1) { *modified = sentCount; return 0; }
int ERR = GetSocketError(s);
Platform_Log1("ERR: %i", &ERR);
*modified = 0; return ERR;
}
void Socket_Close(cc_socket s) {
shutdown(s, SHUT_RDWR);
close(s);
}
static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) {
fd_set read_set, write_set, error_set;
struct timeval time = { 0 };
int selectCount;
FD_ZERO(&read_set);
FD_SET(s, &read_set);
FD_ZERO(&write_set);
FD_SET(s, &write_set);
FD_ZERO(&error_set);
FD_SET(s, &error_set);
selectCount = select(s + 1, &read_set, &write_set, &error_set, &time);
Platform_Log4("SELECT %i = %h / %h / %h", &selectCount, &read_set, &write_set, &error_set);
if (selectCount == -1) { *success = false; return errno; }
*success = FD_ISSET(s, &write_set) != 0; return 0;
}
cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) {
return ERR_NOT_SUPPORTED;
Platform_LogConst("POLL READ");
return Socket_Poll(s, SOCKET_POLL_READ, readable);
}
static int tries;
cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) {
return ERR_NOT_SUPPORTED;
cc_result res = Socket_Poll(s, SOCKET_POLL_WRITE, writable);
Platform_Log1("POLL WRITE: %i", &res);
if (res || *writable) return res;
// INPROGRESS error code returned if connect is still in progress
res = GetSocketError(s);
Platform_Log1("POLL FAIL: %i", &res);
if (res == EINPROGRESS) res = 0;
if (tries++ > 20) { *writable = true; }
return res;
}
@ -396,6 +595,7 @@ void Platform_Init(void) {
sbv_patch_enable_lmb();
InitNetworking();
SetupNetworking();
// Create root directory
Directory_Create(&String_Empty);
}