110 lines
3.8 KiB
C
110 lines
3.8 KiB
C
// FTP-Server in der App (Entwickler-Werkzeuge). Läuft in einem eigenen Thread, solange die App offen ist.
|
|
//
|
|
// Das Hintergrund-Modul (ftpmodul/, eigener Prozess auf Kern 1) ist abgeschaltet: Es brachte den
|
|
// Kernel-Scheduler auf Kern 1 zum Absturz (PC FFF21584, kaputter Thread in der Warteschlange). Die App
|
|
// räumt seine Dateien weg, damit es nie wieder startet.
|
|
//
|
|
// Ohne Passwort, Port 5000, Lesen von der ganzen SD, Schreiben/Löschen nur in /3ds/mbmnet (ftp.c).
|
|
#include <3ds.h>
|
|
#include <arpa/inet.h>
|
|
#include <malloc.h>
|
|
#include <netinet/in.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
|
|
#include "ftpctl.h"
|
|
#include "../ftpmodul/source/ftp.h"
|
|
|
|
#define SOC_BUFFER_SIZE 0x100000
|
|
|
|
static u32 *socBuffer;
|
|
static Thread thread;
|
|
static volatile bool running;
|
|
static char address[32];
|
|
static char status[64];
|
|
|
|
bool ftp_should_exit(void) { return !running; }
|
|
|
|
static void server(void *arg)
|
|
{
|
|
(void)arg;
|
|
while (running) {
|
|
u32 ip = (u32)gethostid();
|
|
if (!ip) { snprintf(status, sizeof(status), "kein WLAN"); address[0] = 0; svcSleepThread(1000000000LL); continue; }
|
|
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(CONTROL_PORT), .sin_addr.s_addr = INADDR_ANY };
|
|
if (fd < 0 || bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 || listen(fd, 2) != 0) {
|
|
if (fd >= 0) close(fd);
|
|
snprintf(status, sizeof(status), "Port %d belegt", CONTROL_PORT);
|
|
svcSleepThread(2000000000LL);
|
|
continue;
|
|
}
|
|
snprintf(address, sizeof(address), "%lu.%lu.%lu.%lu:%d", (unsigned long)(ip & 0xFF), (unsigned long)((ip >> 8) & 0xFF),
|
|
(unsigned long)((ip >> 16) & 0xFF), (unsigned long)(ip >> 24), CONTROL_PORT);
|
|
ftp_serve(fd, ip); // bis WLAN weg, IP neu oder "FTP aus"
|
|
close(fd);
|
|
address[0] = 0;
|
|
}
|
|
}
|
|
|
|
// Reste des abgeschalteten Hintergrund-Moduls entfernen (sonst startete eine alte App-Version es wieder)
|
|
void ftpctl_cleanup_module(void)
|
|
{
|
|
remove("sdmc:/luma/sysmodules/0004013000F1E002.cxi");
|
|
remove("sdmc:/luma/sysmodules/0004013000F1E001.cxi");
|
|
remove("sdmc:/3ds/mbmnet/ftp-an");
|
|
remove("sdmc:/3ds/mbmnet/ftp-stopp");
|
|
remove("sdmc:/3ds/mbmnet/ftp-adresse.txt");
|
|
}
|
|
|
|
bool ftpctl_running(void) { return running; }
|
|
|
|
bool ftpctl_start(char *msg, size_t msglen)
|
|
{
|
|
if (running) return true;
|
|
socBuffer = memalign(0x1000, SOC_BUFFER_SIZE);
|
|
if (!socBuffer || R_FAILED(socInit(socBuffer, SOC_BUFFER_SIZE))) {
|
|
free(socBuffer);
|
|
socBuffer = NULL;
|
|
snprintf(msg, msglen, "FTP: Netzwerk nicht verfügbar.");
|
|
return false;
|
|
}
|
|
running = true;
|
|
status[0] = address[0] = 0;
|
|
s32 prio = 0x30;
|
|
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
|
thread = threadCreate(server, NULL, 32 * 1024, prio + 1, -2, false);
|
|
if (!thread) {
|
|
running = false;
|
|
socExit();
|
|
free(socBuffer);
|
|
socBuffer = NULL;
|
|
snprintf(msg, msglen, "FTP: konnte nicht starten.");
|
|
return false;
|
|
}
|
|
snprintf(msg, msglen, "FTP-Server an (läuft, solange die App offen ist).\nOhne Passwort, Port 5000. Herunterladen von der ganzen SD,\n"
|
|
"Hochladen/Löschen nur in /3ds/mbmnet.");
|
|
return true;
|
|
}
|
|
|
|
void ftpctl_stop(char *msg, size_t msglen)
|
|
{
|
|
if (running) {
|
|
running = false;
|
|
threadJoin(thread, 5000000000LL);
|
|
threadFree(thread);
|
|
thread = NULL;
|
|
socExit();
|
|
free(socBuffer);
|
|
socBuffer = NULL;
|
|
}
|
|
address[0] = 0;
|
|
if (msg) snprintf(msg, msglen, "FTP-Server aus.");
|
|
}
|
|
|
|
bool ftpctl_resume(char *msg, size_t msglen) { (void)msg; (void)msglen; return false; }
|
|
const char *ftpctl_address(void) { return address; }
|
|
const char *ftpctl_status(void) { return status[0] ? status : "startet ..."; }
|