Simplify amalgamation script
This commit is contained in:
@@ -11,12 +11,10 @@ OFILES = $(patsubst %.c,%.o,$(CFILES))
|
|||||||
# Library names
|
# Library names
|
||||||
LIBNAME = chttp
|
LIBNAME = chttp
|
||||||
STATIC_LIB = lib$(LIBNAME).a
|
STATIC_LIB = lib$(LIBNAME).a
|
||||||
SHARED_LIB = lib$(LIBNAME).so
|
|
||||||
|
|
||||||
# Detect OS and set executable extension
|
# Detect OS and set executable extension
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
EXT = .exe
|
EXT = .exe
|
||||||
SHARED_LIB = $(LIBNAME).dll
|
|
||||||
else
|
else
|
||||||
EXT = .out
|
EXT = .out
|
||||||
endif
|
endif
|
||||||
@@ -36,10 +34,10 @@ EXAMPLES_ENGINE := $(patsubst %.c,%$(EXT),$(EXAMPLES_ENGINE_SRC))
|
|||||||
|
|
||||||
all: chttp.c chttp.h examples lib
|
all: chttp.c chttp.h examples lib
|
||||||
|
|
||||||
lib: $(STATIC_LIB) $(SHARED_LIB)
|
lib: $(STATIC_LIB)
|
||||||
|
|
||||||
chttp.c chttp.h: $(HFILES) $(CFILES)
|
chttp.c chttp.h: $(HFILES) $(CFILES)
|
||||||
python misc/amalg.py
|
python amalg.py
|
||||||
|
|
||||||
# Object files from source files
|
# Object files from source files
|
||||||
%.o: %.c $(HFILES)
|
%.o: %.c $(HFILES)
|
||||||
@@ -49,10 +47,6 @@ chttp.c chttp.h: $(HFILES) $(CFILES)
|
|||||||
$(STATIC_LIB): $(OFILES)
|
$(STATIC_LIB): $(OFILES)
|
||||||
$(AR) rcs $@ $^
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
# Shared library
|
|
||||||
$(SHARED_LIB): $(OFILES)
|
|
||||||
$(CC) -shared -o $@ $^ $(LFLAGS)
|
|
||||||
|
|
||||||
examples: $(EXAMPLES_CLIENT) $(EXAMPLES_SERVER) $(EXAMPLES_ENGINE)
|
examples: $(EXAMPLES_CLIENT) $(EXAMPLES_SERVER) $(EXAMPLES_ENGINE)
|
||||||
|
|
||||||
examples/client/%$(EXT): examples/client/%.c chttp.c chttp.h
|
examples/client/%$(EXT): examples/client/%.c chttp.c chttp.h
|
||||||
@@ -64,28 +58,11 @@ examples/server/%$(EXT): examples/server/%.c chttp.c chttp.h
|
|||||||
examples/engine/%$(EXT): examples/engine/%.c chttp.c chttp.h
|
examples/engine/%$(EXT): examples/engine/%.c chttp.c chttp.h
|
||||||
$(CC) $(CFLAGS) $< chttp.c -o $@ $(LFLAGS)
|
$(CC) $(CFLAGS) $< chttp.c -o $@ $(LFLAGS)
|
||||||
|
|
||||||
# Installation targets
|
|
||||||
install: install-lib install-headers
|
|
||||||
|
|
||||||
install-lib: $(STATIC_LIB) $(SHARED_LIB)
|
|
||||||
install -d $(LIBDIR)
|
|
||||||
install -m 644 $(STATIC_LIB) $(LIBDIR)/
|
|
||||||
install -m 755 $(SHARED_LIB) $(LIBDIR)/
|
|
||||||
|
|
||||||
install-headers: chttp.h
|
|
||||||
install -d $(INCDIR)
|
|
||||||
install -m 644 chttp.h $(INCDIR)/
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f $(LIBDIR)/$(STATIC_LIB)
|
|
||||||
rm -f $(LIBDIR)/$(SHARED_LIB)
|
|
||||||
rm -f $(INCDIR)/chttp.h
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f client_example server_example
|
rm -f client_example server_example
|
||||||
rm -f examples/client/*$(EXT) examples/server/*$(EXT) examples/engine/*$(EXT)
|
rm -f examples/client/*$(EXT) examples/server/*$(EXT) examples/engine/*$(EXT)
|
||||||
rm -f $(OFILES)
|
rm -f $(OFILES)
|
||||||
rm -f $(STATIC_LIB) $(SHARED_LIB)
|
rm -f $(STATIC_LIB)
|
||||||
rm -f chttp.c chttp.h
|
rm -f chttp.c chttp.h
|
||||||
|
|
||||||
.PHONY: all lib examples install install-lib install-headers uninstall clean
|
.PHONY: all lib examples install install-lib install-headers uninstall clean
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
class Amalgamator:
|
||||||
|
def __init__(self):
|
||||||
|
self.out = ""
|
||||||
|
|
||||||
|
def append_text(self, text):
|
||||||
|
self.out += text
|
||||||
|
|
||||||
|
def append_file(self, file):
|
||||||
|
|
||||||
|
self.out += "\n"
|
||||||
|
self.out += "////////////////////////////////////////////////////////////////////////////////////////\n"
|
||||||
|
self.out += "// " + file + "\n"
|
||||||
|
self.out += "////////////////////////////////////////////////////////////////////////////////////////\n"
|
||||||
|
self.out += "\n"
|
||||||
|
self.out += "#line 1 \"" + file + "\"\n"
|
||||||
|
self.out += open(file).read()
|
||||||
|
|
||||||
|
if len(self.out) > 0 and self.out[len(self.out)-1] != '\n':
|
||||||
|
self.out += "\n"
|
||||||
|
|
||||||
|
def save(self, file):
|
||||||
|
open(file, 'w').write(self.out)
|
||||||
|
|
||||||
|
desc = """
|
||||||
|
// This file was generated automatically. Do not modify directly!
|
||||||
|
"""
|
||||||
|
|
||||||
|
header = Amalgamator()
|
||||||
|
header.append_text("#ifndef HTTP_AMALGAMATION\n")
|
||||||
|
header.append_text("#define HTTP_AMALGAMATION\n")
|
||||||
|
header.append_text(desc)
|
||||||
|
header.append_file("src/basic.h")
|
||||||
|
header.append_file("src/parse.h")
|
||||||
|
header.append_file("src/engine.h")
|
||||||
|
header.append_file("src/cert.h")
|
||||||
|
header.append_file("src/client.h")
|
||||||
|
header.append_file("src/server.h")
|
||||||
|
header.append_file("src/router.h")
|
||||||
|
header.append_text("#endif // HTTP_AMALGAMATION\n")
|
||||||
|
header.save("chttp.h")
|
||||||
|
|
||||||
|
source = Amalgamator()
|
||||||
|
source.append_text("#include \"chttp.h\"\n")
|
||||||
|
source.append_file("src/socket.h")
|
||||||
|
source.append_file("src/basic.c")
|
||||||
|
source.append_file("src/parse.c")
|
||||||
|
source.append_file("src/engine.c")
|
||||||
|
source.append_file("src/cert.c")
|
||||||
|
source.append_file("src/socket.c")
|
||||||
|
source.append_file("src/client.c")
|
||||||
|
source.append_file("src/server.c")
|
||||||
|
source.append_file("src/router.c")
|
||||||
|
source.save("chttp.c")
|
||||||
@@ -1,55 +1,10 @@
|
|||||||
/*
|
|
||||||
* cHTTP Library - Amalgamated Source
|
|
||||||
* Generated automatically - do not edit manually
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "chttp.h"
|
#include "chttp.h"
|
||||||
|
|
||||||
#include <assert.h>
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// src/cert.h
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef CERT_INCLUDED
|
|
||||||
#define CERT_INCLUDED
|
|
||||||
|
|
||||||
#include "basic.h"
|
|
||||||
|
|
||||||
// This is an utility to create self-signed certificates
|
|
||||||
// useful when testing HTTPS servers locally. This is only
|
|
||||||
// meant to be used by people starting out with a library
|
|
||||||
// and simplifying the zero to one phase.
|
|
||||||
//
|
|
||||||
// The C, O, and CN are respectively country name, organization name,
|
|
||||||
// and common name of the certificate. For instance:
|
|
||||||
//
|
|
||||||
// C="IT"
|
|
||||||
// O="My Organization"
|
|
||||||
// CN="my_website.com"
|
|
||||||
//
|
|
||||||
// The output is a certificate file in PEM format and a private
|
|
||||||
// key file with the key used to sign the certificate.
|
|
||||||
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|
||||||
HTTP_String cert_file, HTTP_String key_file);
|
|
||||||
|
|
||||||
#endif // CERT_INCLUDED//////////////////////////////////////////////////////////////////////
|
|
||||||
// src/socket.h
|
// src/socket.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/socket.h"
|
||||||
#ifndef SOCKET_INCLUDED
|
#ifndef SOCKET_INCLUDED
|
||||||
#define SOCKET_INCLUDED
|
#define SOCKET_INCLUDED
|
||||||
// This is a socket abstraction module for non-blocking TCP and TLS sockets.
|
// This is a socket abstraction module for non-blocking TCP and TLS sockets.
|
||||||
@@ -105,13 +60,17 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|||||||
// which means the user needs to call socket_free to free the socket
|
// which means the user needs to call socket_free to free the socket
|
||||||
// as it's not unusable.
|
// as it's not unusable.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef HTTPS_ENABLED
|
#ifdef HTTPS_ENABLED
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int is_ipv6;
|
int is_ipv6;
|
||||||
@@ -187,9 +146,19 @@ void socket_close (Socket *sock);
|
|||||||
void socket_free (Socket *sock);
|
void socket_free (Socket *sock);
|
||||||
int socket_wait (Socket **socks, int num_socks);
|
int socket_wait (Socket **socks, int num_socks);
|
||||||
|
|
||||||
#endif // SOCKET_INCLUDED//////////////////////////////////////////////////////////////////////
|
#endif // SOCKET_INCLUDED
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/basic.c
|
// src/basic.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/basic.c"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool http_streq(HTTP_String s1, HTTP_String s2)
|
bool http_streq(HTTP_String s1, HTTP_String s2)
|
||||||
{
|
{
|
||||||
@@ -246,6 +215,7 @@ static bool is_printable(char c)
|
|||||||
return c >= ' ' && c <= '~';
|
return c >= ' ' && c <= '~';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
void print_bytes(HTTP_String prefix, HTTP_String src)
|
void print_bytes(HTTP_String prefix, HTTP_String src)
|
||||||
{
|
{
|
||||||
if (src.len == 0)
|
if (src.len == 0)
|
||||||
@@ -285,9 +255,22 @@ void print_bytes(HTTP_String prefix, HTTP_String src)
|
|||||||
cur++;
|
cur++;
|
||||||
}
|
}
|
||||||
putc('\n', stream);
|
putc('\n', stream);
|
||||||
}//////////////////////////////////////////////////////////////////////
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/parse.c
|
// src/parse.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/parse.c"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "parse.h"
|
||||||
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// From RFC 9112
|
// From RFC 9112
|
||||||
// request-target = origin-form
|
// request-target = origin-form
|
||||||
@@ -1318,9 +1301,28 @@ HTTP_String http_getcookie(HTTP_Request *req, HTTP_String name)
|
|||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
return (HTTP_String) {NULL, 0};
|
return (HTTP_String) {NULL, 0};
|
||||||
}//////////////////////////////////////////////////////////////////////
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/engine.c
|
// src/engine.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/engine.c"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h> // TODO: remove some of these headers
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "basic.h"
|
||||||
|
#include "engine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is the implementation of a byte queue useful
|
// This is the implementation of a byte queue useful
|
||||||
// for systems that need to process engs of bytes.
|
// for systems that need to process engs of bytes.
|
||||||
@@ -2301,9 +2303,16 @@ void http_engine_undo(HTTP_Engine *eng)
|
|||||||
eng->state = HTTP_ENGINE_STATE_CLIENT_PREP_URL;
|
eng->state = HTTP_ENGINE_STATE_CLIENT_PREP_URL;
|
||||||
else
|
else
|
||||||
eng->state = HTTP_ENGINE_STATE_SERVER_PREP_STATUS;
|
eng->state = HTTP_ENGINE_STATE_SERVER_PREP_STATUS;
|
||||||
}//////////////////////////////////////////////////////////////////////
|
}
|
||||||
// src/socket.c
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/cert.c
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/cert.c"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef HTTPS_ENABLED
|
#ifdef HTTPS_ENABLED
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
@@ -2313,12 +2322,195 @@ void http_engine_undo(HTTP_Engine *eng)
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "cert.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
|
||||||
|
static EVP_PKEY *generate_rsa_key_pair(int key_bits)
|
||||||
|
{
|
||||||
|
EVP_PKEY_CTX *ctx;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
|
// Create the context for key generation
|
||||||
|
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||||
|
if (!ctx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (EVP_PKEY_keygen_init(ctx) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return pkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
static X509 *create_certificate(EVP_PKEY *pkey, HTTP_String C, HTTP_String O, HTTP_String CN, int days)
|
||||||
|
{
|
||||||
|
X509 *x509 = X509_new();
|
||||||
|
if (!x509)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Set version (version 3)
|
||||||
|
X509_set_version(x509, 2);
|
||||||
|
|
||||||
|
// Set serial number
|
||||||
|
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
|
||||||
|
|
||||||
|
// Set validity period
|
||||||
|
X509_gmtime_adj(X509_get_notBefore(x509), 0);
|
||||||
|
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L * days); // days * seconds_per_year
|
||||||
|
|
||||||
|
// Set public key
|
||||||
|
X509_set_pubkey(x509, pkey);
|
||||||
|
|
||||||
|
// Set subject name
|
||||||
|
X509_NAME *name = X509_get_subject_name(x509);
|
||||||
|
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*) C.ptr, C.len, -1, 0);
|
||||||
|
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*) O.ptr, O.len, -1, 0);
|
||||||
|
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*) CN.ptr, CN.len, -1, 0);
|
||||||
|
|
||||||
|
// Set issuer name (same as subject for self-signed)
|
||||||
|
X509_set_issuer_name(x509, name);
|
||||||
|
|
||||||
|
if (!X509_sign(x509, pkey, EVP_sha256())) {
|
||||||
|
X509_free(x509);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return x509;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int save_private_key(EVP_PKEY *pkey, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(filename, "wb");
|
||||||
|
if (!fp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Write private key in PEM format
|
||||||
|
if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) {
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cert_save(X509 *x509, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(filename, "wb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Error opening file for certificate: %s\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write certificate in PEM format
|
||||||
|
if (!PEM_write_X509(fp, x509)) {
|
||||||
|
fprintf(stderr, "Error writing certificate\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
printf("Certificate saved to: %s\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
|
HTTP_String cert_file, HTTP_String key_file)
|
||||||
|
{
|
||||||
|
EVP_PKEY *pkey = generate_rsa_key_pair(2048);
|
||||||
|
if (pkey == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
X509 *x509 = create_certificate(pkey, C, O, CN, 1)
|
||||||
|
if (x509 == NULL) {
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_private_key(pkey, key_file) < 0) {
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_certificate(x509, cert_file) < 0) {
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
|
HTTP_String cert_file, HTTP_String key_file)
|
||||||
|
{
|
||||||
|
(void) C;
|
||||||
|
(void) O;
|
||||||
|
(void) CN;
|
||||||
|
(void) cert_file;
|
||||||
|
(void) key_file;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/socket.c
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/socket.c"
|
||||||
|
#include <assert.h> // TODO: organize these includes
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
#include <poll.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "socket.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void socket_global_init(void)
|
void socket_global_init(void)
|
||||||
{
|
{
|
||||||
#ifdef HTTPS_ENABLED
|
#ifdef HTTPS_ENABLED
|
||||||
@@ -3173,12 +3365,34 @@ int socket_wait(Socket **socks, int num_socks) // TODO: is this used?
|
|||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}//////////////////////////////////////////////////////////////////////
|
}
|
||||||
// src/client.c
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TODO
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#define ERROR printf("error at %s:%d\n", __FILE__, __LINE__);
|
// src/client.c
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/client.c"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <winsock2.h>
|
||||||
|
#define POLL WSAPoll
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <poll.h>
|
||||||
|
#define POLL poll
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "client.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "engine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CLIENT_MAX_CONNS 256
|
#define CLIENT_MAX_CONNS 256
|
||||||
|
|
||||||
@@ -3370,7 +3584,7 @@ int http_client_wait(HTTP_Client *client, HTTP_RequestHandle *handle)
|
|||||||
if (num_polled == 0)
|
if (num_polled == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
poll(polled, num_polled, -1);
|
POLL(polled, num_polled, -1);
|
||||||
|
|
||||||
for (int i = 0; i < num_polled; i++) {
|
for (int i = 0; i < num_polled; i++) {
|
||||||
|
|
||||||
@@ -3445,7 +3659,6 @@ void http_request_line(HTTP_RequestHandle handle, HTTP_Method method, HTTP_Strin
|
|||||||
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
||||||
if (ret != url.len) {
|
if (ret != url.len) {
|
||||||
// TODO
|
// TODO
|
||||||
ERROR;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3454,7 +3667,6 @@ void http_request_line(HTTP_RequestHandle handle, HTTP_Method method, HTTP_Strin
|
|||||||
secure = true;
|
secure = true;
|
||||||
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
||||||
// TODO
|
// TODO
|
||||||
ERROR;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3474,7 +3686,6 @@ void http_request_line(HTTP_RequestHandle handle, HTTP_Method method, HTTP_Strin
|
|||||||
|
|
||||||
case HTTP_HOST_MODE_VOID:
|
case HTTP_HOST_MODE_VOID:
|
||||||
// TODO
|
// TODO
|
||||||
ERROR;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3619,167 +3830,40 @@ HTTP_Response *http_post(HTTP_String url, HTTP_String *headers, int num_headers,
|
|||||||
|
|
||||||
*phandle = handle;
|
*phandle = handle;
|
||||||
return res;
|
return res;
|
||||||
}//////////////////////////////////////////////////////////////////////
|
|
||||||
// src/cert.c
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifdef HTTPS_ENABLED
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/conf.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HTTPS_ENABLED
|
|
||||||
|
|
||||||
static EVP_PKEY *generate_rsa_key_pair(int key_bits)
|
|
||||||
{
|
|
||||||
EVP_PKEY_CTX *ctx;
|
|
||||||
EVP_PKEY *pkey;
|
|
||||||
|
|
||||||
// Create the context for key generation
|
|
||||||
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
|
||||||
if (!ctx)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (EVP_PKEY_keygen_init(ctx) <= 0) {
|
|
||||||
EVP_PKEY_CTX_free(ctx);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits) <= 0) {
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
EVP_PKEY_CTX_free(ctx);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
|
|
||||||
EVP_PKEY_CTX_free(ctx);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EVP_PKEY_CTX_free(ctx);
|
|
||||||
return pkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
static X509 *create_certificate(EVP_PKEY *pkey, HTTP_String C, HTTP_String O, HTTP_String CN, int days)
|
|
||||||
{
|
|
||||||
X509 *x509 = X509_new();
|
|
||||||
if (!x509)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Set version (version 3)
|
|
||||||
X509_set_version(x509, 2);
|
|
||||||
|
|
||||||
// Set serial number
|
|
||||||
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
|
|
||||||
|
|
||||||
// Set validity period
|
|
||||||
X509_gmtime_adj(X509_get_notBefore(x509), 0);
|
|
||||||
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L * days); // days * seconds_per_year
|
|
||||||
|
|
||||||
// Set public key
|
|
||||||
X509_set_pubkey(x509, pkey);
|
|
||||||
|
|
||||||
// Set subject name
|
|
||||||
X509_NAME *name = X509_get_subject_name(x509);
|
|
||||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*) C.ptr, C.len, -1, 0);
|
|
||||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*) O.ptr, O.len, -1, 0);
|
|
||||||
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*) CN.ptr, CN.len, -1, 0);
|
|
||||||
|
|
||||||
// Set issuer name (same as subject for self-signed)
|
|
||||||
X509_set_issuer_name(x509, name);
|
|
||||||
|
|
||||||
if (!X509_sign(x509, pkey, EVP_sha256())) {
|
|
||||||
X509_free(x509);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x509;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int save_private_key(EVP_PKEY *pkey, const char *filename)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(filename, "wb");
|
|
||||||
if (!fp)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// Write private key in PEM format
|
|
||||||
if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) {
|
|
||||||
fclose(fp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cert_save(X509 *x509, const char *filename)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(filename, "wb");
|
|
||||||
if (!fp) {
|
|
||||||
fprintf(stderr, "Error opening file for certificate: %s\n", filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write certificate in PEM format
|
|
||||||
if (!PEM_write_X509(fp, x509)) {
|
|
||||||
fprintf(stderr, "Error writing certificate\n");
|
|
||||||
fclose(fp);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
printf("Certificate saved to: %s\n", filename);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|
||||||
HTTP_String cert_file, HTTP_String key_file)
|
|
||||||
{
|
|
||||||
EVP_PKEY *pkey = generate_rsa_key_pair(2048);
|
|
||||||
if (pkey == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
X509 *x509 = create_certificate(pkey, C, O, CN, 1)
|
|
||||||
if (x509 == NULL) {
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (save_private_key(pkey, key_file) < 0) {
|
|
||||||
X509_free(x509);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (save_certificate(x509, cert_file) < 0) {
|
|
||||||
X509_free(x509);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509_free(x509);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|
||||||
HTTP_String cert_file, HTTP_String key_file)
|
|
||||||
{
|
|
||||||
(void) C;
|
|
||||||
(void) O;
|
|
||||||
(void) CN;
|
|
||||||
(void) cert_file;
|
|
||||||
(void) key_file;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif//////////////////////////////////////////////////////////////////////
|
|
||||||
// src/server.c
|
// src/server.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/server.c"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <winsock2.h>
|
||||||
|
#define POLL WSAPoll
|
||||||
|
#define CLOSE_SOCKET closesocket
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#define POLL poll
|
||||||
|
#define CLOSE_SOCKET close
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "engine.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "server.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_CONNS (1<<10)
|
#define MAX_CONNS (1<<10)
|
||||||
|
|
||||||
@@ -3813,12 +3897,12 @@ static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
{
|
{
|
||||||
int flags = fcntl(listen_fd, F_GETFL, 0);
|
int flags = fcntl(listen_fd, F_GETFL, 0);
|
||||||
if (flags < 0) {
|
if (flags < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3835,7 +3919,7 @@ static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
|
|
||||||
_Static_assert(sizeof(struct in_addr) == sizeof(HTTP_IPv4));
|
_Static_assert(sizeof(struct in_addr) == sizeof(HTTP_IPv4));
|
||||||
if (http_parse_ipv4(addr.ptr, addr.len, (HTTP_IPv4*) &addr_buf) < 0) {
|
if (http_parse_ipv4(addr.ptr, addr.len, (HTTP_IPv4*) &addr_buf) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3845,12 +3929,12 @@ static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
bind_buf.sin_addr = addr_buf;
|
bind_buf.sin_addr = addr_buf;
|
||||||
bind_buf.sin_port = htons(port);
|
bind_buf.sin_port = htons(port);
|
||||||
if (bind(listen_fd, (struct sockaddr*) &bind_buf, sizeof(bind_buf)) < 0) {
|
if (bind(listen_fd, (struct sockaddr*) &bind_buf, sizeof(bind_buf)) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(listen_fd, backlog) < 0) {
|
if (listen(listen_fd, backlog) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3893,7 +3977,7 @@ HTTP_Server *http_server_init_ex(HTTP_String addr, uint16_t port,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
if (socket_group_init_server(&server->group, cert_key, private_key) < 0) {
|
if (socket_group_init_server(&server->group, cert_key, private_key) < 0) {
|
||||||
close(server->listen_fd);
|
CLOSE_SOCKET(server->listen_fd);
|
||||||
free(server);
|
free(server);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -3901,7 +3985,7 @@ HTTP_Server *http_server_init_ex(HTTP_String addr, uint16_t port,
|
|||||||
server->secure_fd = listen_socket(addr, secure_port, reuse_addr, backlog);
|
server->secure_fd = listen_socket(addr, secure_port, reuse_addr, backlog);
|
||||||
if (server->secure_fd < 0) {
|
if (server->secure_fd < 0) {
|
||||||
socket_group_free(&server->group);
|
socket_group_free(&server->group);
|
||||||
close(server->listen_fd);
|
CLOSE_SOCKET(server->listen_fd);
|
||||||
free(server);
|
free(server);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -3930,8 +4014,8 @@ void http_server_free(HTTP_Server *server)
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
close(server->secure_fd);
|
CLOSE_SOCKET(server->secure_fd);
|
||||||
close(server->listen_fd);
|
CLOSE_SOCKET(server->listen_fd);
|
||||||
if (server->secure_fd != -1)
|
if (server->secure_fd != -1)
|
||||||
socket_group_free(&server->group);
|
socket_group_free(&server->group);
|
||||||
free(server);
|
free(server);
|
||||||
@@ -4006,7 +4090,7 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
|
|||||||
}
|
}
|
||||||
|
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
poll(polled, num_polled, timeout);
|
POLL(polled, num_polled, timeout);
|
||||||
|
|
||||||
for (int i = 0; i < num_polled; i++) {
|
for (int i = 0; i < num_polled; i++) {
|
||||||
|
|
||||||
@@ -4212,16 +4296,43 @@ void http_response_done(HTTP_ResponseHandle res)
|
|||||||
http_engine_free(&conn->engine);
|
http_engine_free(&conn->engine);
|
||||||
server->num_conns--;
|
server->num_conns--;
|
||||||
}
|
}
|
||||||
}//////////////////////////////////////////////////////////////////////
|
}
|
||||||
// src/router.c
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/router.c
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/router.c"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "router.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
bool is_alpha(char c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
bool is_digit(char c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
#endif // HTTP_AMALGAMATION
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ROUTE_STATIC_DIR,
|
ROUTE_STATIC_DIR,
|
||||||
ROUTE_DYNAMIC,
|
ROUTE_DYNAMIC,
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
/*
|
#ifndef HTTP_AMALGAMATION
|
||||||
* cHTTP Library - Amalgamated Header
|
#define HTTP_AMALGAMATION
|
||||||
* Generated automatically - do not edit manually
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HTTP_AMALGAMATION_H
|
// This file was generated automatically. Do not modify directly!
|
||||||
#define HTTP_AMALGAMATION_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// src/basic.h
|
// src/basic.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/basic.h"
|
||||||
#ifndef CHTTP_BASIC_INCLUDED
|
#ifndef CHTTP_BASIC_INCLUDED
|
||||||
#define CHTTP_BASIC_INCLUDED
|
#define CHTTP_BASIC_INCLUDED
|
||||||
|
|
||||||
@@ -91,13 +85,19 @@ HTTP_String http_trim(HTTP_String s);
|
|||||||
#define HTTP_ASSERT(X) {if (!(X)) { __builtin_trap(); }}
|
#define HTTP_ASSERT(X) {if (!(X)) { __builtin_trap(); }}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // CHTTP_BASIC_INCLUDED//////////////////////////////////////////////////////////////////////
|
#endif // CHTTP_BASIC_INCLUDED
|
||||||
// src/parse.h
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/parse.h
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/parse.h"
|
||||||
#ifndef PARSE_INCLUDED
|
#ifndef PARSE_INCLUDED
|
||||||
#define PARSE_INCLUDED
|
#define PARSE_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HTTP_MAX_HEADERS 32
|
#define HTTP_MAX_HEADERS 32
|
||||||
|
|
||||||
@@ -187,13 +187,19 @@ HTTP_String http_getqueryparam (HTTP_Request *req, HTTP_String name);
|
|||||||
HTTP_String http_getbodyparam (HTTP_Request *req, HTTP_String name);
|
HTTP_String http_getbodyparam (HTTP_Request *req, HTTP_String name);
|
||||||
HTTP_String http_getcookie (HTTP_Request *req, HTTP_String name);
|
HTTP_String http_getcookie (HTTP_Request *req, HTTP_String name);
|
||||||
|
|
||||||
#endif // PARSE_INCLUDED//////////////////////////////////////////////////////////////////////
|
#endif // PARSE_INCLUDED
|
||||||
// src/engine.h
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/engine.h
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/engine.h"
|
||||||
#ifndef HTTP_ENGINE_INCLUDED
|
#ifndef HTTP_ENGINE_INCLUDED
|
||||||
#define HTTP_ENGINE_INCLUDED
|
#define HTTP_ENGINE_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HTTP_MEMFUNC_MALLOC,
|
HTTP_MEMFUNC_MALLOC,
|
||||||
@@ -309,15 +315,52 @@ void http_engine_bodyack (HTTP_Engine *eng, int num);
|
|||||||
void http_engine_done (HTTP_Engine *eng);
|
void http_engine_done (HTTP_Engine *eng);
|
||||||
void http_engine_undo (HTTP_Engine *eng);
|
void http_engine_undo (HTTP_Engine *eng);
|
||||||
|
|
||||||
#endif // HTTP_ENGINE_INCLUDED//////////////////////////////////////////////////////////////////////
|
#endif // HTTP_ENGINE_INCLUDED
|
||||||
// src/client.h
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/cert.h
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/cert.h"
|
||||||
|
#ifndef CERT_INCLUDED
|
||||||
|
#define CERT_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is an utility to create self-signed certificates
|
||||||
|
// useful when testing HTTPS servers locally. This is only
|
||||||
|
// meant to be used by people starting out with a library
|
||||||
|
// and simplifying the zero to one phase.
|
||||||
|
//
|
||||||
|
// The C, O, and CN are respectively country name, organization name,
|
||||||
|
// and common name of the certificate. For instance:
|
||||||
|
//
|
||||||
|
// C="IT"
|
||||||
|
// O="My Organization"
|
||||||
|
// CN="my_website.com"
|
||||||
|
//
|
||||||
|
// The output is a certificate file in PEM format and a private
|
||||||
|
// key file with the key used to sign the certificate.
|
||||||
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
|
HTTP_String cert_file, HTTP_String key_file);
|
||||||
|
|
||||||
|
#endif // CERT_INCLUDED
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/client.h
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/client.h"
|
||||||
#ifndef CLIENT_INCLUDED
|
#ifndef CLIENT_INCLUDED
|
||||||
#define CLIENT_INCLUDED
|
#define CLIENT_INCLUDED
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize the global state of cHTTP.
|
// Initialize the global state of cHTTP.
|
||||||
//
|
//
|
||||||
@@ -415,15 +458,21 @@ HTTP_Response *http_post(HTTP_String url,
|
|||||||
HTTP_String *headers, int num_headers,
|
HTTP_String *headers, int num_headers,
|
||||||
HTTP_String body, HTTP_RequestHandle *phandle);
|
HTTP_String body, HTTP_RequestHandle *phandle);
|
||||||
|
|
||||||
#endif // CLIENT_INCLUDED//////////////////////////////////////////////////////////////////////
|
#endif // CLIENT_INCLUDED
|
||||||
// src/server.h
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// src/server.h
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/server.h"
|
||||||
#ifndef HTTP_SERVER_INCLUDED
|
#ifndef HTTP_SERVER_INCLUDED
|
||||||
#define HTTP_SERVER_INCLUDED
|
#define HTTP_SERVER_INCLUDED
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *data0;
|
void *data0;
|
||||||
@@ -450,40 +499,19 @@ void http_response_bodyack (HTTP_ResponseHandle res, int num);
|
|||||||
void http_response_undo (HTTP_ResponseHandle res);
|
void http_response_undo (HTTP_ResponseHandle res);
|
||||||
void http_response_done (HTTP_ResponseHandle res);
|
void http_response_done (HTTP_ResponseHandle res);
|
||||||
|
|
||||||
#endif // HTTP_SERVER_INCLUDED//////////////////////////////////////////////////////////////////////
|
#endif // HTTP_SERVER_INCLUDED
|
||||||
// src/cert.h
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef CERT_INCLUDED
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
#define CERT_INCLUDED
|
|
||||||
|
|
||||||
#include "basic.h"
|
|
||||||
|
|
||||||
// This is an utility to create self-signed certificates
|
|
||||||
// useful when testing HTTPS servers locally. This is only
|
|
||||||
// meant to be used by people starting out with a library
|
|
||||||
// and simplifying the zero to one phase.
|
|
||||||
//
|
|
||||||
// The C, O, and CN are respectively country name, organization name,
|
|
||||||
// and common name of the certificate. For instance:
|
|
||||||
//
|
|
||||||
// C="IT"
|
|
||||||
// O="My Organization"
|
|
||||||
// CN="my_website.com"
|
|
||||||
//
|
|
||||||
// The output is a certificate file in PEM format and a private
|
|
||||||
// key file with the key used to sign the certificate.
|
|
||||||
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|
||||||
HTTP_String cert_file, HTTP_String key_file);
|
|
||||||
|
|
||||||
#endif // CERT_INCLUDED//////////////////////////////////////////////////////////////////////
|
|
||||||
// src/router.h
|
// src/router.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#line 1 "src/router.h"
|
||||||
#ifndef HTTP_ROUTER_INCLUDED
|
#ifndef HTTP_ROUTER_INCLUDED
|
||||||
#define HTTP_ROUTER_INCLUDED
|
#define HTTP_ROUTER_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct HTTP_Router HTTP_Router;
|
typedef struct HTTP_Router HTTP_Router;
|
||||||
typedef void (*HTTP_RouterFunc)(HTTP_Request*, HTTP_ResponseHandle, void*);;
|
typedef void (*HTTP_RouterFunc)(HTTP_Request*, HTTP_ResponseHandle, void*);;
|
||||||
@@ -496,8 +524,4 @@ void http_router_func (HTTP_Router *router, HTTP_Method method, HTTP_
|
|||||||
int http_serve (char *addr, int port, HTTP_Router *router);
|
int http_serve (char *addr, int port, HTTP_Router *router);
|
||||||
|
|
||||||
#endif // HTTP_ROUTER_INCLUDED
|
#endif // HTTP_ROUTER_INCLUDED
|
||||||
#ifdef __cplusplus
|
#endif // HTTP_AMALGAMATION
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HTTP_AMALGAMATION_H */
|
|
||||||
|
|||||||
-276
@@ -1,276 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
AmalgamationBuilder - Implementation with improved #line support and conditional include preservation
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
from typing import Set
|
|
||||||
|
|
||||||
class AmalgamationBuilder:
|
|
||||||
def __init__(self):
|
|
||||||
self.body = ""
|
|
||||||
self.local_includes: Set[str] = set() # These should deduplicate items
|
|
||||||
self.global_includes: Set[str] = set()
|
|
||||||
|
|
||||||
def add(self, filepath: str):
|
|
||||||
"""Add a file to the amalgamation"""
|
|
||||||
try:
|
|
||||||
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"Warning: File '{filepath}' not found, skipping")
|
|
||||||
return
|
|
||||||
|
|
||||||
original_line_number = 1
|
|
||||||
skipped_lines = 0
|
|
||||||
first_content_line = True
|
|
||||||
in_conditional_block = False
|
|
||||||
conditional_depth = 0
|
|
||||||
|
|
||||||
self.body += "//////////////////////////////////////////////////////////////////////\n"
|
|
||||||
self.body += "// " + filepath + "\n"
|
|
||||||
self.body += "//////////////////////////////////////////////////////////////////////\n"
|
|
||||||
self.body += "\n"
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
# Check if we're entering a conditional block
|
|
||||||
if self._is_conditional_start(line):
|
|
||||||
if conditional_depth == 0:
|
|
||||||
in_conditional_block = True
|
|
||||||
conditional_depth += 1
|
|
||||||
# Keep conditional blocks in place
|
|
||||||
self.body += line
|
|
||||||
original_line_number += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Check if we're exiting a conditional block
|
|
||||||
if self._is_conditional_end(line):
|
|
||||||
conditional_depth -= 1
|
|
||||||
if conditional_depth == 0:
|
|
||||||
in_conditional_block = False
|
|
||||||
# Keep conditional blocks in place
|
|
||||||
self.body += line
|
|
||||||
original_line_number += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# If we're inside a conditional block, keep all lines as-is
|
|
||||||
if in_conditional_block:
|
|
||||||
self.body += line
|
|
||||||
original_line_number += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Check if the line is an include (outside conditional blocks only)
|
|
||||||
if self._is_include_line(line):
|
|
||||||
include_info = self._extract_include_info(line)
|
|
||||||
if include_info:
|
|
||||||
filename, uses_angular_brackets = include_info
|
|
||||||
if uses_angular_brackets:
|
|
||||||
self.global_includes.add(filename)
|
|
||||||
else:
|
|
||||||
self.local_includes.add(filename)
|
|
||||||
|
|
||||||
original_line_number += 1
|
|
||||||
skipped_lines += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Check if the line is part of a header guard
|
|
||||||
if self._is_header_guard_line(line):
|
|
||||||
original_line_number += 1
|
|
||||||
skipped_lines += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Skip empty lines at the beginning of files
|
|
||||||
if first_content_line and line.strip() == '':
|
|
||||||
original_line_number += 1
|
|
||||||
skipped_lines += 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Add #line directive when starting a new file or after skipping significant content
|
|
||||||
if first_content_line or skipped_lines > 0:
|
|
||||||
# Only add #line if we skipped lines or it's a new file
|
|
||||||
# self.body += f'#line {original_line_number} "{filepath}"\n'
|
|
||||||
first_content_line = False
|
|
||||||
skipped_lines = 0
|
|
||||||
|
|
||||||
# Append the current line to body
|
|
||||||
self.body += line
|
|
||||||
original_line_number += 1
|
|
||||||
|
|
||||||
def _is_conditional_start(self, line: str) -> bool:
|
|
||||||
"""Check if a line starts a conditional compilation block"""
|
|
||||||
stripped = line.strip()
|
|
||||||
return (stripped.startswith('#ifdef ') or
|
|
||||||
stripped.startswith('#ifndef ') or
|
|
||||||
stripped.startswith('#if '))
|
|
||||||
|
|
||||||
def _is_conditional_end(self, line: str) -> bool:
|
|
||||||
"""Check if a line ends a conditional compilation block"""
|
|
||||||
stripped = line.strip()
|
|
||||||
return stripped.startswith('#endif')
|
|
||||||
|
|
||||||
def _is_include_line(self, line: str) -> bool:
|
|
||||||
"""Check if a line is an #include directive"""
|
|
||||||
# Skip obviously non-include lines for performance
|
|
||||||
if '#include' not in line:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Check if this line is commented out
|
|
||||||
if self._is_line_commented(line):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Regex to match include pattern
|
|
||||||
include_pattern = re.compile(r'^\s*#\s*include\s*[<"][^>"]+[>"]')
|
|
||||||
return bool(include_pattern.match(line.strip()))
|
|
||||||
|
|
||||||
def _extract_include_info(self, line: str) -> tuple[str, bool] | None:
|
|
||||||
"""Extract filename and bracket type from include line"""
|
|
||||||
# Pattern to capture include details
|
|
||||||
include_pattern = re.compile(r'^\s*#\s*include\s*([<"])([^>"]+)([>"])')
|
|
||||||
match = include_pattern.match(line.strip())
|
|
||||||
|
|
||||||
if match:
|
|
||||||
open_delim = match.group(1)
|
|
||||||
filename = match.group(2)
|
|
||||||
close_delim = match.group(3)
|
|
||||||
|
|
||||||
# Validate matching delimiters
|
|
||||||
if (open_delim == '<' and close_delim == '>') or \
|
|
||||||
(open_delim == '"' and close_delim == '"'):
|
|
||||||
uses_angular_brackets = (open_delim == '<')
|
|
||||||
return filename, uses_angular_brackets
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _is_header_guard_line(self, line: str) -> bool:
|
|
||||||
"""Check if a line is part of a header guard (assumes _INCLUDED suffix)"""
|
|
||||||
stripped = line.strip()
|
|
||||||
|
|
||||||
# Simplified header guard patterns for _INCLUDED suffix
|
|
||||||
header_guard_patterns = [
|
|
||||||
re.compile(r'#ifndef\s+\w+_INCLUDED'),
|
|
||||||
re.compile(r'#define\s+\w+_INCLUDED'),
|
|
||||||
re.compile(r'#endif\s*//.*_INCLUDED'),
|
|
||||||
re.compile(r'#endif\s*/\*.*_INCLUDED.*\*/'),
|
|
||||||
]
|
|
||||||
|
|
||||||
return any(pattern.match(stripped) for pattern in header_guard_patterns)
|
|
||||||
|
|
||||||
def _is_line_commented(self, line: str) -> bool:
|
|
||||||
"""Basic check if line is commented out"""
|
|
||||||
include_pos = line.find('#include')
|
|
||||||
if include_pos == -1:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Check for // comment before #include
|
|
||||||
comment_pos = line.find('//')
|
|
||||||
if comment_pos != -1 and comment_pos < include_pos:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Check for /* comment before #include (basic case)
|
|
||||||
before_include = line[:include_pos]
|
|
||||||
if '/*' in before_include and '*/' not in before_include:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def result(self) -> str:
|
|
||||||
"""Generate the final amalgamated result"""
|
|
||||||
result = ""
|
|
||||||
|
|
||||||
# Write all global includes at the top
|
|
||||||
for item in sorted(self.global_includes):
|
|
||||||
result += f'#include <{item}>\n'
|
|
||||||
|
|
||||||
if self.global_includes:
|
|
||||||
result += "\n" # Add spacing after includes
|
|
||||||
|
|
||||||
# Add the body content
|
|
||||||
result += self.body
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Example usage of AmalgamationBuilder"""
|
|
||||||
|
|
||||||
# Build the header
|
|
||||||
print("Building header...")
|
|
||||||
header_builder = AmalgamationBuilder()
|
|
||||||
|
|
||||||
header_files = [
|
|
||||||
"src/basic.h",
|
|
||||||
"src/parse.h",
|
|
||||||
"src/engine.h",
|
|
||||||
"src/client.h",
|
|
||||||
"src/server.h",
|
|
||||||
"src/cert.h",
|
|
||||||
"src/router.h"
|
|
||||||
]
|
|
||||||
|
|
||||||
for file in header_files:
|
|
||||||
header_builder.add(file)
|
|
||||||
|
|
||||||
header = header_builder.result()
|
|
||||||
|
|
||||||
# Build the source
|
|
||||||
print("Building source...")
|
|
||||||
source_builder = AmalgamationBuilder()
|
|
||||||
|
|
||||||
source_files = [
|
|
||||||
"src/cert.h",
|
|
||||||
"src/socket.h",
|
|
||||||
"src/basic.c",
|
|
||||||
"src/parse.c",
|
|
||||||
"src/engine.c",
|
|
||||||
"src/socket.c",
|
|
||||||
"src/client.c",
|
|
||||||
"src/cert.c",
|
|
||||||
"src/server.c",
|
|
||||||
"src/router.c"
|
|
||||||
]
|
|
||||||
|
|
||||||
for file in source_files:
|
|
||||||
source_builder.add(file)
|
|
||||||
|
|
||||||
source = source_builder.result()
|
|
||||||
|
|
||||||
# Write results
|
|
||||||
print("Writing chttp.h...")
|
|
||||||
with open("chttp.h", 'w', encoding='utf-8') as f:
|
|
||||||
f.write('/*\n')
|
|
||||||
f.write(' * cHTTP Library - Amalgamated Header\n')
|
|
||||||
f.write(' * Generated automatically - do not edit manually\n')
|
|
||||||
f.write(' */\n\n')
|
|
||||||
f.write('#ifndef HTTP_AMALGAMATION_H\n')
|
|
||||||
f.write('#define HTTP_AMALGAMATION_H\n\n')
|
|
||||||
f.write('#ifdef __cplusplus\n')
|
|
||||||
f.write('extern "C" {\n')
|
|
||||||
f.write('#endif\n\n')
|
|
||||||
f.write(header)
|
|
||||||
f.write('\n#ifdef __cplusplus\n')
|
|
||||||
f.write('}\n')
|
|
||||||
f.write('#endif\n\n')
|
|
||||||
f.write('#endif /* HTTP_AMALGAMATION_H */\n')
|
|
||||||
|
|
||||||
print("Writing chttp.c...")
|
|
||||||
with open("chttp.c", 'w', encoding='utf-8') as f:
|
|
||||||
f.write('/*\n')
|
|
||||||
f.write(' * cHTTP Library - Amalgamated Source\n')
|
|
||||||
f.write(' * Generated automatically - do not edit manually\n')
|
|
||||||
f.write(' */\n\n')
|
|
||||||
f.write('#include "chttp.h"\n\n')
|
|
||||||
f.write(source)
|
|
||||||
|
|
||||||
print("Amalgamation complete!")
|
|
||||||
print(f"Header: {len(header.splitlines())} lines")
|
|
||||||
print(f"Source: {len(source.splitlines())} lines")
|
|
||||||
|
|
||||||
# Show some statistics
|
|
||||||
print(f"\nHeader global includes: {len(header_builder.global_includes)}")
|
|
||||||
print(f"Source global includes: {len(source_builder.global_includes)}")
|
|
||||||
print(f"Local includes found: {len(header_builder.local_includes | source_builder.local_includes)}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
+4
-1
@@ -1,7 +1,10 @@
|
|||||||
#include "basic.h"
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool http_streq(HTTP_String s1, HTTP_String s2)
|
bool http_streq(HTTP_String s1, HTTP_String s2)
|
||||||
{
|
{
|
||||||
if (s1.len != s2.len)
|
if (s1.len != s2.len)
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "cert.h"
|
#include "cert.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HTTPS_ENABLED
|
#ifdef HTTPS_ENABLED
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#ifndef CERT_INCLUDED
|
#ifndef CERT_INCLUDED
|
||||||
#define CERT_INCLUDED
|
#define CERT_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is an utility to create self-signed certificates
|
// This is an utility to create self-signed certificates
|
||||||
// useful when testing HTTPS servers locally. This is only
|
// useful when testing HTTPS servers locally. This is only
|
||||||
|
|||||||
@@ -14,9 +14,11 @@
|
|||||||
#define POLL poll
|
#define POLL poll
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CLIENT_MAX_CONNS 256
|
#define CLIENT_MAX_CONNS 256
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
#define CLIENT_INCLUDED
|
#define CLIENT_INCLUDED
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize the global state of cHTTP.
|
// Initialize the global state of cHTTP.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// This is the implementation of a byte queue useful
|
// This is the implementation of a byte queue useful
|
||||||
// for systems that need to process engs of bytes.
|
// for systems that need to process engs of bytes.
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#ifndef HTTP_ENGINE_INCLUDED
|
#ifndef HTTP_ENGINE_INCLUDED
|
||||||
#define HTTP_ENGINE_INCLUDED
|
#define HTTP_ENGINE_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HTTP_MEMFUNC_MALLOC,
|
HTTP_MEMFUNC_MALLOC,
|
||||||
|
|||||||
@@ -2,8 +2,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// From RFC 9112
|
// From RFC 9112
|
||||||
// request-target = origin-form
|
// request-target = origin-form
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#ifndef PARSE_INCLUDED
|
#ifndef PARSE_INCLUDED
|
||||||
#define PARSE_INCLUDED
|
#define PARSE_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HTTP_MAX_HEADERS 32
|
#define HTTP_MAX_HEADERS 32
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -13,17 +13,20 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
bool is_alpha(char c)
|
bool is_alpha(char c)
|
||||||
{
|
{
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_digit(char c)
|
bool is_digit(char c)
|
||||||
{
|
{
|
||||||
return c >= '0' && c <= '9';
|
return c >= '0' && c <= '9';
|
||||||
}
|
}
|
||||||
|
#endif // HTTP_AMALGAMATION
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ROUTE_STATIC_DIR,
|
ROUTE_STATIC_DIR,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#ifndef HTTP_ROUTER_INCLUDED
|
#ifndef HTTP_ROUTER_INCLUDED
|
||||||
#define HTTP_ROUTER_INCLUDED
|
#define HTTP_ROUTER_INCLUDED
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct HTTP_Router HTTP_Router;
|
typedef struct HTTP_Router HTTP_Router;
|
||||||
typedef void (*HTTP_RouterFunc)(HTTP_Request*, HTTP_ResponseHandle, void*);;
|
typedef void (*HTTP_RouterFunc)(HTTP_Request*, HTTP_ResponseHandle, void*);;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -10,14 +11,20 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#define POLL poll
|
||||||
#define CLOSE_SOCKET close
|
#define CLOSE_SOCKET close
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_CONNS (1<<10)
|
#define MAX_CONNS (1<<10)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
#define HTTP_SERVER_INCLUDED
|
#define HTTP_SERVER_INCLUDED
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *data0;
|
void *data0;
|
||||||
|
|||||||
+14
-12
@@ -1,20 +1,8 @@
|
|||||||
#include <poll.h>
|
|
||||||
#include <assert.h> // TODO: organize these includes
|
#include <assert.h> // TODO: organize these includes
|
||||||
#include "socket.h"
|
|
||||||
#ifdef HTTPS_ENABLED
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/conf.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -24,9 +12,23 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
#include <poll.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
|
#include "socket.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void socket_global_init(void)
|
void socket_global_init(void)
|
||||||
{
|
{
|
||||||
#ifdef HTTPS_ENABLED
|
#ifdef HTTPS_ENABLED
|
||||||
|
|||||||
@@ -61,7 +61,9 @@
|
|||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_AMALGAMATION
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int is_ipv6;
|
int is_ipv6;
|
||||||
|
|||||||
Reference in New Issue
Block a user