diff --git a/Makefile b/Makefile index 0f3e9a7..944b0d9 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ SOURCES := source INCLUDES := source # Bei jedem Release erhöhen - das Auto-Update vergleicht diese Nummer -VERSION := 3.0.5 +VERSION := 3.0.6 APP_TITLE := MBMNET APP_DESCRIPTION := Dein eigenes 3DS-Netzwerk diff --git a/source/admin.c b/source/admin.c index 850f037..4ebb560 100644 --- a/source/admin.c +++ b/source/admin.c @@ -16,13 +16,15 @@ static char CLIENT_ID[] = "87cd32617f1985439ea608c2746e4610"; static volatile bool isAdmin; -static Thread thread; static char server[64]; static char why[96] = "Werkzeuge: kein MBMNET-Konto angemeldet."; // warum (noch) keine Werkzeuge +static Result lastAct; // letzter Fehler von act (für die Wiederholung) +static bool wanted; // MBMNET-Konto angemeldet: prüfen -static void worker(void *arg) +// Holt den Nachweis und lässt ihn prüfen. Läuft im Auffrischen-Thread (main.c) direkt nach dem Konto-Abgleich: +// act bearbeitet nur eine Server-Anfrage auf einmal, gleichzeitig gab es "ungültiger Zustand" (C8A14F4B). +static void check_once(void) { - (void)arg; // 1. Anmelde-Nachweis vom Konto-Dienst (für das gerade angemeldete Konto). "shared": danach für jeden // Prozess abholbar - nur für diesen Prozess angefordert, gab act ihn nicht heraus (E0A14CCE). Handle done; @@ -33,7 +35,8 @@ static void worker(void *arg) Result rc = ACT_AcquireIndependentServiceToken(0xFE, CLIENT_ID, 0, false, true, pid, done); Result wait = R_SUCCEEDED(rc) ? svcWaitSynchronization(done, 15ULL * 1000 * 1000 * 1000) : rc; svcCloseHandle(done); - if (wait != 0) { snprintf(why, sizeof(why), "Werkzeuge: Anmelde-Nachweis nicht erhalten (%08lX).", (unsigned long)wait); return; } + lastAct = 0; + if (wait != 0) { lastAct = wait; snprintf(why, sizeof(why), "Werkzeuge: Anmelde-Nachweis nicht erhalten (%08lX).", (unsigned long)wait); return; } // Ergebnis der Anfrage beim Account-Server (z. B. abgelehnt oder keine Verbindung) Result result = ACT_GetLastResponseResult(); static IndependentServiceTokenV1 tok; @@ -42,10 +45,8 @@ static void worker(void *arg) // Notlösung: aus dem Zwischenspeicher von act (gerade eben geholt) if (R_FAILED(rc) || !tok.token[0]) rc = ACT_GetCachedIndependentServiceToken(&tok, 0xFE, CLIENT_ID, 3600, false, true); if (R_FAILED(rc) || !tok.token[0]) { - Result shown = R_FAILED(result) ? result : rc; - Result code = ACT_ResultToErrorCode(shown); // 022-XXXX wie in den Einstellungen - snprintf(why, sizeof(why), "Werkzeuge: kein Anmelde-Nachweis vom Server\n(%08lX, Fehler %03lu-%04lu).", - (unsigned long)shown, (unsigned long)(code / 10000), (unsigned long)(code % 10000)); + lastAct = R_FAILED(result) ? result : rc; + snprintf(why, sizeof(why), "Werkzeuge: kein Anmelde-Nachweis vom Server (%08lX).", (unsigned long)lastAct); return; } @@ -64,25 +65,27 @@ static void worker(void *arg) const char *admin_why(void) { return why; } -void admin_start(const char *srv, bool mbmnetLoggedIn) +void admin_prepare(const char *srv, bool mbmnetLoggedIn) { isAdmin = false; - snprintf(why, sizeof(why), "Werkzeuge: nur bei aktivem MBMNET mit angemeldetem Admin-Konto."); + wanted = mbmnetLoggedIn; + snprintf(why, sizeof(why), mbmnetLoggedIn ? "Werkzeuge: Server prüft noch ..." + : "Werkzeuge: nur bei aktivem MBMNET mit angemeldetem Admin-Konto."); remove(OLD_CACHE_FILE); - if (!mbmnetLoggedIn) return; snprintf(server, sizeof(server), "%s", srv); - s32 prio = 0x30; - svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); - thread = threadCreate(worker, NULL, 16 * 1024, prio + 1, -2, false); +} + +void admin_check(void) +{ + if (!wanted) return; + // act noch mit etwas anderem beschäftigt ("ungültiger Zustand"): kurz warten und noch einmal + for (int attempt = 0; attempt < 4; attempt++) { + check_once(); + if (isAdmin || !lastAct || ((lastAct >> 21) & 0x3F) != 5) break; // 5 = InvalidState + svcSleepThread(1000ULL * 1000 * 1000); + } } bool admin_is(void) { return isAdmin; } -bool admin_finish(void) -{ - if (!thread) return true; - if (R_FAILED(threadJoin(thread, 100ULL * 1000 * 1000))) return false; // läuft noch - threadFree(thread); - thread = NULL; - return true; -} +bool admin_finish(void) { return true; } // kein eigener Thread mehr (läuft im Auffrischen) diff --git a/source/admin.h b/source/admin.h index ae3e288..258d47f 100644 --- a/source/admin.h +++ b/source/admin.h @@ -2,9 +2,11 @@ #include <3ds/types.h> #include -// Prüft im Hintergrund, ob das angemeldete MBMNET-Konto Admin ist (signierter Anmelde-Nachweis, per HTTPS -// vom Server bestätigt, siehe admin.c). mbmnetLoggedIn = false: gar nicht fragen, keine Werkzeuge. -void admin_start(const char *server, bool mbmnetLoggedIn); +// Prüft, ob das angemeldete MBMNET-Konto Admin ist (signierter Anmelde-Nachweis, per HTTPS vom Server bestätigt, +// siehe admin.c). admin_prepare beim Start; mbmnetLoggedIn = false: keine Werkzeuge. +void admin_prepare(const char *server, bool mbmnetLoggedIn); +// Die eigentliche Prüfung (blockiert, im Hintergrund-Thread aufrufen, nicht gleichzeitig mit anderen act-Anfragen) +void admin_check(void); // Admin? Nur nach Bestätigung durch den Server in dieser Sitzung. bool admin_is(void); // Warum es (noch) keine Werkzeuge gibt (leer = Admin) diff --git a/source/main.c b/source/main.c index 7df0ba0..2a4ef84 100644 --- a/source/main.c +++ b/source/main.c @@ -369,6 +369,9 @@ static void maintenance_worker(void *arg) svcCloseHandle(done); } maintenanceBusy = false; + // 3b. Admin? (braucht act - deshalb erst nach dem Konto-Abgleich, nie gleichzeitig). Hält das Umschalten + // nicht auf: Tippt man vorher, fällt die Prüfung aus (nach dem Neustart gibt es eine neue). + if (!switchRequested) admin_check(); // 4. Miiverse-CA frisch vom Server (nur Netz; Patches nur neu bauen, wenn sie sich geändert hat) bool caChanged = false; if (!switchRequested && olvpatch_refresh_ca(MBMNET_SERVER, &caChanged) && caChanged && hadCa) @@ -639,7 +642,7 @@ int main(int argc, char **argv) // Das geht nur, solange das MBMNET-Konto angemeldet ist (MBMNET aktiv, ID verknüpft). { char mid[20]; - admin_start(server, st == STATE_MBMNET && frdswitch_current() == FRIEND_ACCOUNT_MBMNET && nnid_linked(mid, sizeof(mid))); + admin_prepare(server, st == STATE_MBMNET && frdswitch_current() == FRIEND_ACCOUNT_MBMNET && nnid_linked(mid, sizeof(mid))); } // Ein SpotPass-Test von früher (App mitten im Test verlassen) darf nicht weiterlaufen spotpass_test_cancel();