74 lines
2.4 KiB
C
74 lines
2.4 KiB
C
// 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 <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
}
|