diff --git a/sysmodules/rosalina/include/sock_util.h b/sysmodules/rosalina/include/sock_util.h index 4c047d2..dd0d0b7 100644 --- a/sysmodules/rosalina/include/sock_util.h +++ b/sysmodules/rosalina/include/sock_util.h @@ -68,10 +68,11 @@ typedef struct sock_server sock_free_func free; Handle shall_terminate_event; + Result init_result; } sock_server; Result server_init(struct sock_server *serv); -void server_bind(struct sock_server *serv, u16 port); +Result server_bind(struct sock_server *serv, u16 port); void server_run(struct sock_server *serv); void server_kill_connections(struct sock_server *serv); void server_set_should_close_all(struct sock_server *serv); diff --git a/sysmodules/rosalina/source/gdb/server.c b/sysmodules/rosalina/source/gdb/server.c index b40b52d..847040a 100644 --- a/sysmodules/rosalina/source/gdb/server.c +++ b/sysmodules/rosalina/source/gdb/server.c @@ -74,13 +74,14 @@ void GDB_DecrementServerReferenceCount(GDBServer *server) void GDB_RunServer(GDBServer *server) { - server_bind(&server->super, GDB_PORT_BASE); - server_bind(&server->super, GDB_PORT_BASE + 1); - server_bind(&server->super, GDB_PORT_BASE + 2); + Result res = server_bind(&server->super, GDB_PORT_BASE); + if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 1); + if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 2); - server_bind(&server->super, GDB_PORT_BASE + 3); // next application + if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 3); // next application - server_run(&server->super); + if(R_SUCCEEDED(res)) + server_run(&server->super); } void GDB_LockAllContexts(GDBServer *server) diff --git a/sysmodules/rosalina/source/input_redirection.c b/sysmodules/rosalina/source/input_redirection.c index 7dc941e..77cf736 100644 --- a/sysmodules/rosalina/source/input_redirection.c +++ b/sysmodules/rosalina/source/input_redirection.c @@ -55,17 +55,38 @@ int inputRedirectionStartResult; void inputRedirectionThreadMain(void) { Result res = 0; + inputRedirectionStartResult = 0; + res = miniSocInit(); if(R_FAILED(res)) + { + // Socket services broken + inputRedirectionStartResult = res; + + miniSocExit(); + // Still signal the event + svcSignalEvent(inputRedirectionThreadStartedEvent); return; + } int sock = socSocket(AF_INET, SOCK_DGRAM, 0); - while(sock == -1) + u32 tries = 15; + while(sock == -1 && --tries > 0) { - svcSleepThread(1000 * 0000 * 0000LL); + svcSleepThread(100 * 1000 * 1000LL); sock = socSocket(AF_INET, SOCK_DGRAM, 0); } + if (sock < -10000 || tries == 0) { + // Socket services broken + inputRedirectionStartResult = -1; + + miniSocExit(); + // Still signal the event + svcSignalEvent(inputRedirectionThreadStartedEvent); + return; + } + struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(4950); @@ -76,6 +97,9 @@ void inputRedirectionThreadMain(void) socClose(sock); miniSocExit(); inputRedirectionStartResult = res; + + // Still signal the event + svcSignalEvent(inputRedirectionThreadStartedEvent); return; } @@ -125,8 +149,11 @@ void inputRedirectionThreadMain(void) srvPublishToSubscriber(0x203, 0); } } + else if(pollres < -10000) + break; } + inputRedirectionEnabled = false; struct linger linger; linger.l_onoff = 1; linger.l_linger = 0; @@ -147,6 +174,8 @@ Result InputRedirection_DoOrUndoPatches(void) Handle processHandle; Result res = OpenProcessByName("hid", &processHandle); + static bool hidPatched = false; + static bool irPatched = false; if(R_SUCCEEDED(res)) { @@ -173,11 +202,12 @@ Result InputRedirection_DoOrUndoPatches(void) static u32 *hidRegPatchOffsets[2]; static u32 *hidPatchJumpLoc; - if(inputRedirectionEnabled) + if(hidPatched) { memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode)); + hidPatched = false; } else { @@ -218,6 +248,7 @@ Result InputRedirection_DoOrUndoPatches(void) *off = *off2 = hidDataPhys; memcpy(off3, &hidHook, sizeof(hidHook)); + hidPatched = true; } } @@ -264,7 +295,7 @@ Result InputRedirection_DoOrUndoPatches(void) static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc; - if(inputRedirectionEnabled) + if(irPatched) { memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode)); if(useOldSyncCode) @@ -272,6 +303,8 @@ Result InputRedirection_DoOrUndoPatches(void) else memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode)); memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode)); + + irPatched = false; } else { @@ -331,6 +364,8 @@ Result InputRedirection_DoOrUndoPatches(void) // This NOPs out a flag check in ir:user's CPP emulation *irCppFlagLoc = 0xE3150000; // tst r5, #0 + + irPatched = true; } } diff --git a/sysmodules/rosalina/source/menus/debugger.c b/sysmodules/rosalina/source/menus/debugger.c index c536966..9918618 100644 --- a/sysmodules/rosalina/source/menus/debugger.c +++ b/sysmodules/rosalina/source/menus/debugger.c @@ -115,16 +115,18 @@ void DebuggerMenu_EnableDebugger(void) if(!done) { res = GDB_InitializeServer(&gdbServer); + Handle handles[3] = { gdbServer.super.started_event, gdbServer.super.shall_terminate_event, terminationRequestEvent }; + s32 idx; if(R_SUCCEEDED(res)) { debuggerCreateSocketThread(); debuggerCreateDebugThread(); - res = svcWaitSynchronization(gdbServer.super.started_event, 10 * 1000 * 1000 * 1000LL); + res = svcWaitSynchronizationN(&idx, handles, 3, false, 10 * 1000 * 1000 * 1000LL); + if(res == 0) res = gdbServer.super.init_result; } if(res != 0) sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res); - done = true; } if(res == 0) diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 6c391b3..ad17960 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -288,7 +288,12 @@ void MiscellaneousMenu_InputRedirection(void) res = (Result)inputRedirectionStartResult; if(res != 0) + { + svcCloseHandle(inputRedirectionThreadStartedEvent); InputRedirection_DoOrUndoPatches(); + inputRedirectionEnabled = false; + } + inputRedirectionStartResult = 0; } } diff --git a/sysmodules/rosalina/source/minisoc.c b/sysmodules/rosalina/source/minisoc.c index 52953ca..8b23b07 100644 --- a/sysmodules/rosalina/source/minisoc.c +++ b/sysmodules/rosalina/source/minisoc.c @@ -10,7 +10,8 @@ #include <3ds/ipc.h> #include <3ds/os.h> #include <3ds/synchronization.h> -#include "memory.h" +#include <3ds/result.h> +#include s32 _net_convert_error(s32 sock_retval); @@ -167,7 +168,7 @@ int socSocket(int domain, int type, int protocol) if(ret != 0) { //errno = SYNC_ERROR; - return ret; + return R_FAILED(ret) ? ret : -1; } ret = (int)cmdbuf[1]; @@ -389,7 +390,7 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout) staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { - return ret; + return R_FAILED(ret) ? ret : -1; } ret = (int)cmdbuf[1]; diff --git a/sysmodules/rosalina/source/ntp.c b/sysmodules/rosalina/source/ntp.c index 30040c9..e002f02 100644 --- a/sysmodules/rosalina/source/ntp.c +++ b/sysmodules/rosalina/source/ntp.c @@ -104,6 +104,11 @@ Result ntpGetTimeStamp(time_t *outTimestamp) return res; int sock = socSocket(AF_INET, SOCK_DGRAM, 0); + if (sock < -10000) { + // Socket services broken + return sock; + } + struct sockaddr_in servAddr = {0}; // Server address data structure. NtpPacket packet = {0}; diff --git a/sysmodules/rosalina/source/sock_util.c b/sysmodules/rosalina/source/sock_util.c index 561084a..e0038f2 100644 --- a/sysmodules/rosalina/source/sock_util.c +++ b/sysmodules/rosalina/source/sock_util.c @@ -101,29 +101,36 @@ Result server_init(struct sock_server *serv) return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY); } -void server_bind(struct sock_server *serv, u16 port) +Result server_bind(struct sock_server *serv, u16 port) { int server_sockfd; Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event }; s32 idx = -1; server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); - int res; - while(server_sockfd == -1) + int res; + u32 tries = 15; + while(server_sockfd == -1 && --tries > 0) { if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0) - return; + return -1; server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); } + if (server_sockfd < -10000 || tries == 0) { + // Socket services broken + serv->init_result = -1; + svcSignalEvent(serv->shall_terminate_event); + return -1; + } + struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = socGethostid(); res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); - if(res == 0) { res = socListen(server_sockfd, 2); @@ -143,6 +150,15 @@ void server_bind(struct sock_server *serv, u16 port) serv->ctx_ptrs[idx] = new_ctx; } } + + if (res != 0) { + // Socket services broken + serv->init_result = res; + svcSignalEvent(serv->shall_terminate_event); + return res; + } + + return 0; } static bool server_should_exit(struct sock_server *serv) @@ -171,7 +187,7 @@ void server_run(struct sock_server *serv) fds[i].revents = 0; int pollres = socPoll(fds, serv->nfds, 50); - if(server_should_exit(serv)) + if(server_should_exit(serv) || pollres < -10000) goto abort_connections; for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++) @@ -256,6 +272,7 @@ abort_connections: server_kill_connections(serv); serv->running = false; svcClearEvent(serv->started_event); + svcSignalEvent(serv->shall_terminate_event); } void server_set_should_close_all(struct sock_server *serv)