// HTTP über den Systemdienst http:C. Alles läuft über den MBMNET-Server (einfaches HTTP), // der Katalog, Symbole und Downloads von Universal-DB und GitHub holt. #include <3ds.h> #include #include #include "net.h" #define CHUNK (128 * 1024) static Result open_request(httpcContext *ctx, const char *url, u32 *status) { Result rc = httpcOpenContext(ctx, HTTPC_METHOD_GET, url, 1); if (R_FAILED(rc)) return rc; httpcAddRequestHeaderField(ctx, "User-Agent", "MBMNET-Shop/" APP_VERSION); httpcSetKeepAlive(ctx, HTTPC_KEEPALIVE_DISABLED); if (R_SUCCEEDED(rc = httpcBeginRequest(ctx))) rc = httpcGetResponseStatusCodeTimeout(ctx, status, 30ULL * 1000 * 1000 * 1000); if (R_FAILED(rc)) httpcCloseContext(ctx); return rc; } u32 net_stream(const char *url, NetSink sink, void *ctx, Result *rcOut) { httpcContext http; u32 status = 0, total = 0, got; Result rc = open_request(&http, url, &status); if (rcOut) *rcOut = rc; if (R_FAILED(rc)) return 0; if (status != 200) { httpcCloseContext(&http); return status; } httpcGetDownloadSizeState(&http, NULL, &total); u8 *buf = malloc(CHUNK); if (!buf) { httpcCloseContext(&http); if (rcOut) *rcOut = -2; return 0; } do { got = 0; rc = httpcDownloadData(&http, buf, CHUNK, &got); if (got && !sink(ctx, buf, got, total)) { rc = -3; break; } // -3 = Empfänger hat abgebrochen } while (rc == (Result)HTTPC_RESULTCODE_DOWNLOADPENDING); free(buf); httpcCloseContext(&http); if (rcOut) *rcOut = rc; return R_SUCCEEDED(rc) ? 200 : 0; } typedef struct { u8 *data; u32 size, cap, max; } MemSink; static bool to_memory(void *p, const u8 *data, u32 len, u32 total) { MemSink *m = p; if (m->size + len > m->max) return false; if (m->size + len > m->cap) { u32 cap = m->cap ? m->cap : (total && total <= m->max ? total : 64 * 1024); while (cap < m->size + len) cap *= 2; u8 *bigger = realloc(m->data, cap); if (!bigger) return false; m->data = bigger; m->cap = cap; } memcpy(m->data + m->size, data, len); m->size += len; return true; } u32 net_get(const char *url, u8 **out, u32 *size, u32 max, Result *rc) { MemSink m = { NULL, 0, 0, max }; u32 status = net_stream(url, to_memory, &m, rc); if (status != 200) { free(m.data); m.data = NULL; m.size = 0; } *out = m.data; *size = m.size; return status; }