skunkworks-c/src/net/http_client.c

108 lines
2.0 KiB
C

#include "net/http_client.h"
#include "error.h"
#include "str.h"
#include <string.h>
#include <windows.h>
#include <wininet.h>
static HINTERNET internet = 0;
#define REQ_PROGRESS 0
#define REQ_DONE 1
#define REQ_FREE 2
struct request {
u8 *response;
u32 response_length;
HINTERNET handle;
u8 status;
};
static struct request *requests = 0;
static u32 request_count = 0;
static void init_internet();
static u32 next_free_request();
struct sw_http_request_handle sw_http_request_async(char *url) {
HINTERNET session, http;
u16 port;
char *proto, *rest;
char *server, *rest2;
u32 req;
sw_str_split2(url, "://", &proto, &rest);
if(proto == 0) {
sw_error("url requires ://");
}
if(strcmp(proto, "https") == 0) {
port = INTERNET_DEFAULT_HTTPS_PORT;
} else if(strcmp(proto, "http") == 0) {
port = INTERNET_DEFAULT_HTTP_PORT;
} else {
sw_error("unknown protocol '%s'", proto);
}
sw_str_split2(url, "/", &server, &rest2);
/* TODO: handle urls without / */
init_internet();
session = InternetConnect(
internet, server, port, 0, 0, INTERNET_SERVICE_HTTP, 0, 0
);
if(session == 0) {
sw_win32_error();
}
http = HttpOpenRequest(session, "GET", rest2, "HTTP/1.1", 0, 0, 0, 0);
if(http == 0) {
sw_win32_error();
}
if(!HttpSendRequest(http, 0, 0, 0, 0)) {
sw_win32_error();
}
req = next_free_request();
requests[req].handle = http;
return (struct sw_http_request_handle){req};
}
static void init_internet() {
if(internet == 0) {
internet = InternetOpen(
"Skunkworks", INTERNET_OPEN_TYPE_DIRECT, 0, 0, INTERNET_FLAG_ASYNC
);
if(internet == 0) {
sw_win32_error();
}
}
}
static u32 next_free_request() {
u32 i;
for(i = 0; i < request_count; ++i) {
if(requests[i].status == REQ_FREE) {
return i;
}
}
request_count += 1;
requests = realloc(requests, sizeof(struct request) * request_count);
requests[request_count - 1].handle = 0;
requests[request_count - 1].response = 0;
requests[request_count - 1].response_length = 0;
requests[request_count - 1].status = REQ_PROGRESS;
return request_count - 1;
}