add lwIP TCP/IP stack as a runtime driver, native socket syscalls, SysGetMemoryStatus replacing CatchAllDebugBucket, fix timeGetTime to return milliseconds, fix SysSleep to interpret argument as milliseconds, SysGetTick now returns microseconds, harden all syscalls against bad user pointers with CopyFromUser/CopyToUser/MmProbeUser throughout, add networking test apps, port-forward 8080 in runa.bat, split LWIP_DRIVER_CFLAGS, add settings.ini to deploy, remove ethernet.c stub
This commit is contained in:
1 parent
18b4dd0f61
commit
df13b8056c
365 files changed
+143263
-1362
No files matched your search
@@ -0,0 +1,258 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
|
||||
static void print(const char* s) {
|
||||
if (s) SysWriteConsole(s, strlen(s));
|
||||
}
|
||||
|
||||
static void print_char(char c) {
|
||||
SysWriteConsole(&c, 1);
|
||||
}
|
||||
|
||||
static void print_u64(uint64_t v) {
|
||||
char buf[32];
|
||||
int n = 0;
|
||||
if (v == 0) { print("0"); return; }
|
||||
while (v && n < (int)sizeof(buf)) {
|
||||
buf[n++] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
while (n > 0) print_char(buf[--n]);
|
||||
}
|
||||
|
||||
static void append_char(char* dst, size_t cap, size_t* off, char c) {
|
||||
if (!dst || !off || cap == 0 || *off + 1 >= cap) return;
|
||||
dst[*off] = c;
|
||||
*off += 1;
|
||||
dst[*off] = 0;
|
||||
}
|
||||
|
||||
static void append_str(char* dst, size_t cap, size_t* off, const char* s) {
|
||||
if (!s) return;
|
||||
while (*s) append_char(dst, cap, off, *s++);
|
||||
}
|
||||
|
||||
static void append_u8(char* dst, size_t cap, size_t* off, uint8_t v) {
|
||||
if (v >= 100) {
|
||||
append_char(dst, cap, off, (char)('0' + v / 100));
|
||||
v %= 100;
|
||||
append_char(dst, cap, off, (char)('0' + v / 10));
|
||||
append_char(dst, cap, off, (char)('0' + v % 10));
|
||||
} else if (v >= 10) {
|
||||
append_char(dst, cap, off, (char)('0' + v / 10));
|
||||
append_char(dst, cap, off, (char)('0' + v % 10));
|
||||
} else {
|
||||
append_char(dst, cap, off, (char)('0' + v));
|
||||
}
|
||||
}
|
||||
|
||||
static void format_ipv4(char* dst, size_t cap, const uint8_t ip[4]) {
|
||||
size_t off = 0;
|
||||
if (!dst || cap == 0) return;
|
||||
dst[0] = 0;
|
||||
append_u8(dst, cap, &off, ip[0]); append_char(dst, cap, &off, '.');
|
||||
append_u8(dst, cap, &off, ip[1]); append_char(dst, cap, &off, '.');
|
||||
append_u8(dst, cap, &off, ip[2]); append_char(dst, cap, &off, '.');
|
||||
append_u8(dst, cap, &off, ip[3]);
|
||||
}
|
||||
|
||||
static bool parse_u8(const char** p, uint8_t* out) {
|
||||
const char* s = *p;
|
||||
uint32_t v = 0;
|
||||
int digits = 0;
|
||||
while (*s >= '0' && *s <= '9') {
|
||||
v = v * 10u + (uint32_t)(*s - '0');
|
||||
if (v > 255u) return false;
|
||||
s++;
|
||||
digits++;
|
||||
}
|
||||
if (digits == 0) return false;
|
||||
*out = (uint8_t)v;
|
||||
*p = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_ipv4(const char* s, uint8_t ip[4]) {
|
||||
if (!s || !ip) return false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!parse_u8(&s, &ip[i])) return false;
|
||||
if (i != 3) {
|
||||
if (*s != '.') return false;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
return *s == 0;
|
||||
}
|
||||
|
||||
static const char* next_token(const char* s, char* out, size_t outSize) {
|
||||
if (!s || !out || outSize == 0) return NULL;
|
||||
while (*s == ' ' || *s == '\t') s++;
|
||||
if (*s == 0) { out[0] = 0; return NULL; }
|
||||
|
||||
size_t n = 0;
|
||||
while (*s && *s != ' ' && *s != '\t') {
|
||||
if (n + 1 < outSize) out[n++] = *s;
|
||||
s++;
|
||||
}
|
||||
out[n] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void usage(void) {
|
||||
print("usage: httpget.exe [host-or-ipv4] [path]\n");
|
||||
print("default: httpget.exe 10.0.2.2 /\n");
|
||||
}
|
||||
|
||||
static uint32_t resolve_host(const char* host, uint8_t ip[4]) {
|
||||
if (parse_ipv4(host, ip))
|
||||
return SYS_STATUS_SUCCESS;
|
||||
|
||||
SYS_SOCKET_ADDRESS_IPV4 resolved;
|
||||
size_t resolvedSize = sizeof(resolved);
|
||||
SYS_RESOLVE_HOST_REQUEST req;
|
||||
memset(&resolved, 0, sizeof(resolved));
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Name = host;
|
||||
req.NameLength = strlen(host);
|
||||
req.Family = SYS_AF_INET;
|
||||
req.AddressOut = &resolved;
|
||||
req.AddressSizeInOut = &resolvedSize;
|
||||
|
||||
uint32_t st = SysResolveHost(&req);
|
||||
if (st != SYS_STATUS_SUCCESS)
|
||||
return st;
|
||||
if (resolved.Family != SYS_AF_INET)
|
||||
return SYS_STATUS_NOT_FOUND;
|
||||
|
||||
ip[0] = resolved.Address[0];
|
||||
ip[1] = resolved.Address[1];
|
||||
ip[2] = resolved.Address[2];
|
||||
ip[3] = resolved.Address[3];
|
||||
return SYS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
uint8_t ip[4] = {10, 0, 2, 2};
|
||||
char host[256];
|
||||
char path[128];
|
||||
strcpy(host, "10.0.2.2");
|
||||
path[0] = '/';
|
||||
path[1] = 0;
|
||||
|
||||
const char* cmd = SysGetPeb()->CommandLine;
|
||||
char tok[256];
|
||||
cmd = next_token(cmd, tok, sizeof(tok)); // program path
|
||||
if (cmd) {
|
||||
const char* rest = next_token(cmd, tok, sizeof(tok));
|
||||
if (tok[0]) {
|
||||
if (strlen(tok) >= sizeof(host)) {
|
||||
print("httpget: host too long\n");
|
||||
SysExitProcess(1);
|
||||
}
|
||||
strcpy(host, tok);
|
||||
cmd = rest;
|
||||
}
|
||||
if (cmd) {
|
||||
(void)next_token(cmd, tok, sizeof(tok));
|
||||
if (tok[0]) {
|
||||
size_t len = strlen(tok);
|
||||
if (len + 2 > sizeof(path)) {
|
||||
print("httpget: path too long\n");
|
||||
SysExitProcess(1);
|
||||
}
|
||||
if (tok[0] != '/') {
|
||||
path[0] = '/';
|
||||
memcpy(path + 1, tok, len + 1);
|
||||
} else {
|
||||
memcpy(path, tok, len + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t st = resolve_host(host, ip);
|
||||
if (st != SYS_STATUS_SUCCESS) {
|
||||
print("httpget: resolve failed "); print_u64(st); print(" for "); print(host); print("\n");
|
||||
usage();
|
||||
SysExitProcess(1);
|
||||
}
|
||||
|
||||
char ipText[16];
|
||||
format_ipv4(ipText, sizeof(ipText), ip);
|
||||
|
||||
print("httpget: GET http://");
|
||||
print(host);
|
||||
print(path);
|
||||
print(" (");
|
||||
print(ipText);
|
||||
print(")\n");
|
||||
|
||||
uint32_t sock = 0;
|
||||
st = SysSocket(SYS_AF_INET, SYS_SOCK_STREAM, SYS_IPPROTO_TCP, &sock);
|
||||
if (st != SYS_STATUS_SUCCESS) {
|
||||
print("httpget: SysSocket failed "); print_u64(st); print("\n");
|
||||
SysExitProcess(1);
|
||||
}
|
||||
|
||||
SYS_SOCKET_ADDRESS_IPV4 addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.Family = SYS_AF_INET;
|
||||
addr.Port = 80;
|
||||
addr.Address[0] = ip[0];
|
||||
addr.Address[1] = ip[1];
|
||||
addr.Address[2] = ip[2];
|
||||
addr.Address[3] = ip[3];
|
||||
|
||||
st = SysConnect(sock, &addr, sizeof(addr));
|
||||
if (st != SYS_STATUS_SUCCESS) {
|
||||
print("httpget: SysConnect failed "); print_u64(st); print("\n");
|
||||
SysCloseHandle(sock);
|
||||
SysExitProcess(1);
|
||||
}
|
||||
|
||||
char request[512];
|
||||
size_t off = 0;
|
||||
request[0] = 0;
|
||||
append_str(request, sizeof(request), &off, "GET ");
|
||||
append_str(request, sizeof(request), &off, path);
|
||||
append_str(request, sizeof(request), &off, " HTTP/1.0\r\nHost: ");
|
||||
append_str(request, sizeof(request), &off, host);
|
||||
append_str(request, sizeof(request), &off, "\r\nUser-Agent: nt-lite-sys-socket\r\nConnection: close\r\n\r\n");
|
||||
|
||||
size_t totalSent = 0;
|
||||
while (totalSent < off) {
|
||||
size_t sent = 0;
|
||||
st = SysSend(sock, request + totalSent, off - totalSent, 0, &sent);
|
||||
if (st != SYS_STATUS_SUCCESS || sent == 0) {
|
||||
print("httpget: SysSend failed "); print_u64(st); print(" sent="); print_u64(sent); print("\n");
|
||||
SysCloseHandle(sock);
|
||||
SysExitProcess(1);
|
||||
}
|
||||
totalSent += sent;
|
||||
}
|
||||
|
||||
char buf[513];
|
||||
size_t total = 0;
|
||||
for (;;) {
|
||||
size_t got = 0;
|
||||
st = SysRecv(sock, buf, sizeof(buf) - 1, 0, &got);
|
||||
if (st != SYS_STATUS_SUCCESS) {
|
||||
print("\nhttpget: SysRecv failed "); print_u64(st); print(" after "); print_u64(total); print(" bytes\n");
|
||||
SysCloseHandle(sock);
|
||||
SysExitProcess(1);
|
||||
}
|
||||
if (got == 0) break;
|
||||
buf[got] = 0;
|
||||
print(buf);
|
||||
total += got;
|
||||
}
|
||||
|
||||
print("\nhttpget: done, "); print_u64(total); print(" bytes\n");
|
||||
SysShutdown(sock, SYS_SHUTDOWN_BOTH);
|
||||
SysCloseHandle(sock);
|
||||
SysExitProcess(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user