major restructuring, prepare for smp
This commit is contained in:
1 parent
b3569a2b90
commit
6bff37746d
229 files changed
+1617
-1489
No files matched your search
@@ -0,0 +1,258 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
static void print(const char* s) {
|
||||
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
|
||||
}
|
||||
|
||||
static void print_char(char c) {
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
|
||||
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 = SysSvFromCstr(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.Data;
|
||||
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