This commit is contained in:
maj0r authored and GitHub committed 2026-05-24 15:47:51 -03:00
1 parent 5936ae096d
commit 2dbcf21f80
3 files changed
+120 -35

No files matched your search

+49 -27
View File
@@ -118,8 +118,8 @@ query_value(const char *query, const char *key, char *out, size_t out_size) {
return -1;
}
static const char *
status_text_for(int status) {
static const char *
status_text_for(int status) {
switch (status) {
case 200:
return "OK";
@@ -141,13 +141,31 @@ status_text_for(int status) {
return "Bad Gateway";
case 503:
return "Service Unavailable";
default:
return "OK";
}
}
void
http_send_response(int fd, int status, const char *content_type, const uint8_t *body, size_t body_len) {
default:
return "OK";
}
}
static int
socket_send_all(int fd, const void *buf, size_t len) {
const uint8_t *p = (const uint8_t *)buf;
size_t sent = 0;
while (sent < len) {
ssize_t n = send(fd, p + sent, len - sent, 0);
if (n > 0) {
sent += (size_t)n;
continue;
}
if (n < 0 && errno == EINTR) {
continue;
}
return -1;
}
return 0;
}
void
http_send_response(int fd, int status, const char *content_type, const uint8_t *body, size_t body_len) {
char header[512];
int n = snprintf(header, sizeof(header),
"HTTP/1.1 %d %s\r\n"
@@ -157,15 +175,17 @@ http_send_response(int fd, int status, const char *content_type, const uint8_t *
"Access-Control-Allow-Origin: *\r\n"
"Cache-Control: no-cache\r\n"
"\r\n",
status, status_text_for(status), content_type ? content_type : "application/octet-stream",
(unsigned int)body_len);
if (n > 0) {
send(fd, header, (size_t)n, 0);
if (body_len > 0) {
send(fd, body, body_len, 0);
}
}
}
status, status_text_for(status), content_type ? content_type : "application/octet-stream",
(unsigned int)body_len);
if (n > 0) {
if (socket_send_all(fd, header, (size_t)n) != 0) {
return;
}
if (body_len > 0) {
(void)socket_send_all(fd, body, body_len);
}
}
}
void
http_send_json(int fd, int status, const char *body) {
@@ -3722,20 +3742,22 @@ void
http_send_png_asset(int fd) {
char header[256];
size_t len = sizeof(g_cheatrunner_png);
int n = snprintf(header, sizeof(header),
int n = snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: image/png\r\n"
"Content-Length: %u\r\n"
"Connection: close\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Cache-Control: public, max-age=86400\r\n"
"\r\n",
(unsigned int)len);
if (n > 0) {
send(fd, header, (size_t)n, 0);
send(fd, g_cheatrunner_png, len, 0);
}
}
"Cache-Control: public, max-age=86400\r\n"
"\r\n",
(unsigned int)len);
if (n > 0) {
if (socket_send_all(fd, header, (size_t)n) != 0) {
return;
}
(void)socket_send_all(fd, g_cheatrunner_png, len);
}
}
void
http_route(int fd, const char *method, const char *path, const char *query, const char *token_header,
+34 -4
View File
@@ -36,6 +36,24 @@ long long cr_http_too_many_requests_count(void) { return g_too_many_requests_cou
typedef struct { int fd; char ip[64]; } http_client_ctx_t;
static void http_handle_client(int fd, const char *client_ip);
static int
socket_send_all(int fd, const void *buf, size_t len) {
const uint8_t *p = (const uint8_t *)buf;
size_t sent = 0;
while (sent < len) {
ssize_t n = send(fd, p + sent, len - sent, 0);
if (n > 0) {
sent += (size_t)n;
continue;
}
if (n < 0 && errno == EINTR) {
continue;
}
return -1;
}
return 0;
}
static void *
http_client_thread(void *arg) {
http_client_ctx_t *ctx = (http_client_ctx_t *)arg;
@@ -122,8 +140,8 @@ http_send_json(int fd, int status, const char *body) {
"\r\n",
status, (unsigned int)strlen(payload));
if (n > 0) {
send(fd, header, (size_t)n, 0);
send(fd, payload, strlen(payload), 0);
(void)socket_send_all(fd, header, (size_t)n);
(void)socket_send_all(fd, payload, strlen(payload));
}
}
@@ -139,9 +157,10 @@ http_handle_client(int fd, const char *client_ip) {
size_t body_len = 0;
struct timeval tv;
tv.tv_sec = 3;
tv.tv_sec = 10;
tv.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
for (;;) {
if (off >= MAX_REQ_SIZE) {
@@ -149,6 +168,9 @@ http_handle_client(int fd, const char *client_ip) {
}
int n = recv(fd, req + off, MAX_REQ_SIZE - off, 0);
if (n <= 0) {
if (n < 0 && errno == EINTR) {
continue;
}
if (off == 0) {
free(req);
return;
@@ -196,6 +218,9 @@ http_handle_client(int fd, const char *client_ip) {
}
int n = recv(fd, req + off, MAX_REQ_SIZE - off, 0);
if (n <= 0) {
if (n < 0 && errno == EINTR) {
continue;
}
break;
}
off += (size_t)n;
@@ -320,7 +345,12 @@ http_server_thread(void *arg) {
if (g_shutdown_requested) {
break;
}
break;
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
}
log_msg("[HTTP] accept() failed: %d", errno);
sleep(1);
continue;
}
char client_ip[64] = {0};
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));
+37 -4
View File
@@ -2,6 +2,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "http_client.h"
@@ -45,6 +46,14 @@ http_ssl_cb(void) {
return 0;
}
static int
http_should_retry(int rc, int status_code) {
if (rc != 0) {
return 1;
}
return status_code == 429 || status_code == 500 || status_code == 502 || status_code == 503 || status_code == 504;
}
static int
http_init(http_ctx_t *ctx, const char *agent, const char *url, int timeout_ms) {
int err = 0;
@@ -141,6 +150,13 @@ http_request(http_ctx_t *ctx, uint8_t **data, size_t *len, int *status_out, size
for (;;) {
if ((cap - off) < 4096) {
size_t new_cap = cap * 2;
if (max_bytes > 0 && new_cap > max_bytes) {
new_cap = max_bytes;
}
if (new_cap <= cap) {
free(buf);
return -2;
}
uint8_t *nbuf = realloc(buf, new_cap);
if (!nbuf) {
free(buf);
@@ -221,6 +237,9 @@ http_get_url_ex_timeout(const char *agent, const char *url, size_t max_bytes, in
size_t body_len = 0;
int status = -1;
int rc = 0;
int init_rc = 0;
int attempts = 3;
int effective_timeout_ms = timeout_ms > 0 ? timeout_ms : 15000;
if (!url || !data_out || !len_out) {
return -1;
@@ -235,16 +254,30 @@ http_get_url_ex_timeout(const char *agent, const char *url, size_t max_bytes, in
agent = "CheatRunner/0.1";
}
if (http_init(&ctx, agent, url, timeout_ms) < 0) {
for (int attempt = 0; attempt < attempts; attempt++) {
body = NULL;
body_len = 0;
status = -1;
rc = -1;
init_rc = http_init(&ctx, agent, url, effective_timeout_ms);
if (init_rc >= 0) {
rc = http_request(&ctx, &body, &body_len, &status, max_bytes);
}
http_fini(&ctx);
return -1;
if (!http_should_retry(rc, status) || attempt == attempts - 1) {
break;
}
free(body);
body = NULL;
body_len = 0;
usleep((useconds_t)((attempt + 1) * 250000));
}
rc = http_request(&ctx, &body, &body_len, &status, max_bytes);
if (status_out) {
*status_out = status;
}
http_fini(&ctx);
if (rc != 0) {
free(body);
return rc;