feat(lander): initial lnm integration test
	
		
			
	
		
	
	
		
			
				
	
				ci/woodpecker/push/build Pipeline was successful
				
					Details
				
			
		
	
				
					
				
			
				
	
				ci/woodpecker/push/build Pipeline was successful
				
					Details
				
			
		
	
							parent
							
								
									799821d9fc
								
							
						
					
					
						commit
						8ec667af3b
					
				
							
								
								
									
										8
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										8
									
								
								Makefile
								
								
								
								
							| 
						 | 
					@ -39,7 +39,11 @@ objs: $(OBJS)
 | 
				
			||||||
liblsm:
 | 
					liblsm:
 | 
				
			||||||
	$(MAKE) -C lsm
 | 
						$(MAKE) -C lsm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(BIN): liblsm $(OBJS)
 | 
					.PHONY: liblnm
 | 
				
			||||||
 | 
					liblnm:
 | 
				
			||||||
 | 
						$(MAKE) -C lnm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(BIN): liblsm liblnm $(OBJS)
 | 
				
			||||||
	$(CC) -o $@ $(OBJS) $(_LDFLAGS)
 | 
						$(CC) -o $@ $(OBJS) $(_LDFLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c
 | 
					$(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c
 | 
				
			||||||
| 
						 | 
					@ -68,7 +72,7 @@ run: $(BIN)
 | 
				
			||||||
valgrind: $(BIN)
 | 
					valgrind: $(BIN)
 | 
				
			||||||
	LANDER_API_KEY=test \
 | 
						LANDER_API_KEY=test \
 | 
				
			||||||
		LANDER_DATA_DIR=data \
 | 
							LANDER_DATA_DIR=data \
 | 
				
			||||||
		valgrind '$(BUILD_DIR)/$(BIN_FILENAME)'
 | 
							valgrind --track-origins=yes '$(BUILD_DIR)/$(BIN_FILENAME)'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: test
 | 
					.PHONY: test
 | 
				
			||||||
test: $(TARGETS_TEST)
 | 
					test: $(TARGETS_TEST)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,9 +7,9 @@ SRC_DIR        = src
 | 
				
			||||||
TEST_DIR       = test
 | 
					TEST_DIR       = test
 | 
				
			||||||
THIRDPARTY_DIR = thirdparty
 | 
					THIRDPARTY_DIR = thirdparty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INC_DIRS  = include $(THIRDPARTY_DIR)/include lsm/include
 | 
					INC_DIRS  = include $(THIRDPARTY_DIR)/include lsm/include lnm/include
 | 
				
			||||||
LIBS      = m lsm
 | 
					LIBS      = m lsm lnm
 | 
				
			||||||
LIB_DIRS  = ./lsm/build
 | 
					LIB_DIRS  = ./lsm/build ./lnm/build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# -MMD: generate a .d file for every source file. This file can be imported by
 | 
					# -MMD: generate a .d file for every source file. This file can be imported by
 | 
				
			||||||
#  make and makes make aware that a header file has been changed, ensuring an
 | 
					#  make and makes make aware that a header file has been changed, ensuring an
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,12 @@
 | 
				
			||||||
#ifndef LANDER
 | 
					#ifndef LANDER
 | 
				
			||||||
#define LANDER
 | 
					#define LANDER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "http_loop.h"
 | 
					#include "lnm/common.h"
 | 
				
			||||||
 | 
					#include "lnm/http/loop.h"
 | 
				
			||||||
#include "lsm/store.h"
 | 
					#include "lsm/store.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "http_loop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern http_route lander_routes[6];
 | 
					extern http_route lander_routes[6];
 | 
				
			||||||
extern const char lander_key_charset[];
 | 
					extern const char lander_key_charset[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,13 +34,13 @@ typedef enum lander_entry_type : uint8_t {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *lander_gctx_init();
 | 
					void *lander_gctx_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *lander_ctx_init();
 | 
					lnm_err lander_ctx_init(void **c_ctx, void *gctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lander_ctx_reset(lander_ctx *ctx);
 | 
					void lander_ctx_reset(lander_ctx *ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lander_ctx_free(lander_ctx *ctx);
 | 
					void lander_ctx_free(lander_ctx *ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool lander_get_index(event_loop_conn *conn);
 | 
					lnm_http_step_err lander_get_index(lnm_http_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool lander_get_entry(event_loop_conn *conn);
 | 
					bool lander_get_entry(event_loop_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,4 +79,11 @@ uint64_t lnm_ipow(uint64_t base, uint64_t power);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
uint64_t lnm_atoi(const char *s, size_t len);
 | 
					uint64_t lnm_atoi(const char *s, size_t len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Calculate how many base 10 digits the given number consists of.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param num number to use
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint64_t lnm_digits(uint64_t num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,11 +7,11 @@ extern const char *lnm_http_method_names[];
 | 
				
			||||||
extern const size_t lnm_http_method_names_len;
 | 
					extern const size_t lnm_http_method_names_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum lnm_http_method {
 | 
					typedef enum lnm_http_method {
 | 
				
			||||||
  http_method_get = 0,
 | 
					  lnm_http_method_get = 0,
 | 
				
			||||||
  http_method_post,
 | 
					  lnm_http_method_post,
 | 
				
			||||||
  http_method_put,
 | 
					  lnm_http_method_put,
 | 
				
			||||||
  http_method_patch,
 | 
					  lnm_http_method_patch,
 | 
				
			||||||
  http_method_delete
 | 
					  lnm_http_method_delete
 | 
				
			||||||
} lnm_http_method;
 | 
					} lnm_http_method;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const char *lnm_http_status_names[][32];
 | 
					extern const char *lnm_http_status_names[][32];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,12 +32,20 @@ lnm_err lnm_http_loop_init(lnm_http_loop **out, void *c_gctx,
 | 
				
			||||||
                           lnm_http_ctx_reset_fn ctx_reset,
 | 
					                           lnm_http_ctx_reset_fn ctx_reset,
 | 
				
			||||||
                           lnm_http_ctx_free_fn ctx_free);
 | 
					                           lnm_http_ctx_free_fn ctx_free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Initialize a new step.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param out where to store pointer to new `lnm_http_step`
 | 
				
			||||||
 | 
					 * @param fn step function
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					lnm_err lnm_http_step_init(lnm_http_step **out, lnm_http_step_fn fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Append the given step fn to the step.
 | 
					 * Append the given step fn to the step.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param out where to store pointer to new `lnm_http_step`
 | 
					 * @param out where to store pointer to new `lnm_http_step`
 | 
				
			||||||
 * @param step step to append new step to
 | 
					 * @param step step to append new step to
 | 
				
			||||||
 * @param fn step funcitonn
 | 
					 * @param fn step function
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
lnm_err lnm_http_step_append(lnm_http_step **out, lnm_http_step *step,
 | 
					lnm_err lnm_http_step_append(lnm_http_step **out, lnm_http_step *step,
 | 
				
			||||||
                             lnm_http_step_fn fn);
 | 
					                             lnm_http_step_fn fn);
 | 
				
			||||||
| 
						 | 
					@ -71,7 +79,9 @@ lnm_err lnm_http_route_init_regex(lnm_http_route **out, lnm_http_method method,
 | 
				
			||||||
 * @param hl HTTP loop to modify
 | 
					 * @param hl HTTP loop to modify
 | 
				
			||||||
 * @param route route to add
 | 
					 * @param route route to add
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route);
 | 
					lnm_err lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lnm_err lnm_http_loop_run(lnm_http_loop *hl, uint16_t port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents what state an HTTP loop request is currently in.
 | 
					 * Represents what state an HTTP loop request is currently in.
 | 
				
			||||||
| 
						 | 
					@ -85,6 +95,8 @@ typedef enum lnm_http_loop_state {
 | 
				
			||||||
  lnm_http_loop_state_parse_headers,
 | 
					  lnm_http_loop_state_parse_headers,
 | 
				
			||||||
  // Execute the various steps defined for the route
 | 
					  // Execute the various steps defined for the route
 | 
				
			||||||
  lnm_http_loop_state_steps,
 | 
					  lnm_http_loop_state_steps,
 | 
				
			||||||
 | 
					  // Add certain automatically added headers
 | 
				
			||||||
 | 
					  lnm_http_loop_state_add_headers,
 | 
				
			||||||
  // Write the response status line
 | 
					  // Write the response status line
 | 
				
			||||||
  lnm_http_loop_state_write_status_line,
 | 
					  lnm_http_loop_state_write_status_line,
 | 
				
			||||||
  // Write the various response headers
 | 
					  // Write the various response headers
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,12 +45,12 @@ typedef struct lnm_http_res {
 | 
				
			||||||
      FILE *f;
 | 
					      FILE *f;
 | 
				
			||||||
      data_fn fn;
 | 
					      data_fn fn;
 | 
				
			||||||
    } data;
 | 
					    } data;
 | 
				
			||||||
    size_t len;
 | 
					    uint64_t len;
 | 
				
			||||||
    bool owned;
 | 
					    bool owned;
 | 
				
			||||||
    lnm_http_res_body_type type;
 | 
					    lnm_http_res_body_type type;
 | 
				
			||||||
  } body;
 | 
					  } body;
 | 
				
			||||||
  // General-purpose; meaning depends on the current state
 | 
					  // General-purpose; meaning depends on the current state
 | 
				
			||||||
  size_t written;
 | 
					  uint64_t written;
 | 
				
			||||||
} lnm_http_res;
 | 
					} lnm_http_res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,9 @@ lnm_err lnm_http_loop_init(lnm_http_loop **out, void *c_gctx,
 | 
				
			||||||
           free(hl));
 | 
					           free(hl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  hl->data_read = lnm_http_loop_process;
 | 
					  hl->data_read = lnm_http_loop_process;
 | 
				
			||||||
 | 
					  hl->data_write = lnm_http_loop_process;
 | 
				
			||||||
 | 
					  hl->ctx_init = (lnm_err(*)(void **, void *))lnm_http_loop_ctx_init;
 | 
				
			||||||
 | 
					  hl->ctx_free = (void (*)(void *))lnm_http_loop_ctx_free;
 | 
				
			||||||
  *out = hl;
 | 
					  *out = hl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return lnm_err_ok;
 | 
					  return lnm_err_ok;
 | 
				
			||||||
| 
						 | 
					@ -42,7 +45,9 @@ lnm_err lnm_http_step_append(lnm_http_step **out, lnm_http_step *step,
 | 
				
			||||||
                             lnm_http_step_fn fn) {
 | 
					                             lnm_http_step_fn fn) {
 | 
				
			||||||
  LNM_RES(lnm_http_step_init(out, fn));
 | 
					  LNM_RES(lnm_http_step_init(out, fn));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (step != NULL) {
 | 
				
			||||||
    step->next = *out;
 | 
					    step->next = *out;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return lnm_err_ok;
 | 
					  return lnm_err_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -96,3 +101,28 @@ lnm_err lnm_http_route_init_regex(lnm_http_route **out, lnm_http_method method,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return lnm_err_ok;
 | 
					  return lnm_err_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lnm_err lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route) {
 | 
				
			||||||
 | 
					  lnm_http_loop_gctx *gctx = hl->gctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lnm_http_route **new_routes =
 | 
				
			||||||
 | 
					      gctx->routes.len > 0
 | 
				
			||||||
 | 
					          ? realloc(gctx->routes.arr,
 | 
				
			||||||
 | 
					                    (gctx->routes.len + 1) * sizeof(lnm_http_route *))
 | 
				
			||||||
 | 
					          : malloc(sizeof(lnm_http_route *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (new_routes == NULL) {
 | 
				
			||||||
 | 
					    return lnm_err_failed_alloc;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  new_routes[gctx->routes.len] = route;
 | 
				
			||||||
 | 
					  gctx->routes.arr = new_routes;
 | 
				
			||||||
 | 
					  gctx->routes.len++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lnm_err_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lnm_err lnm_http_loop_run(lnm_http_loop *hl, uint16_t port) {
 | 
				
			||||||
 | 
					  LNM_RES(lnm_loop_setup(hl, port));
 | 
				
			||||||
 | 
					  return lnm_loop_run(hl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
/* static const lnm_http_loop_state lnm_http_loop_state_first_req =
 | 
					/* static const lnm_http_loop_state lnm_http_loop_state_first_req =
 | 
				
			||||||
 * lnm_http_loop_state_parse_req; */
 | 
					 * lnm_http_loop_state_parse_req; */
 | 
				
			||||||
static const lnm_http_loop_state lnm_http_loop_state_first_res =
 | 
					static const lnm_http_loop_state lnm_http_loop_state_first_res =
 | 
				
			||||||
    lnm_http_loop_state_write_headers;
 | 
					    lnm_http_loop_state_write_status_line;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lnm_http_loop_process_parse_req(lnm_http_conn *conn) {
 | 
					void lnm_http_loop_process_parse_req(lnm_http_conn *conn) {
 | 
				
			||||||
  lnm_http_loop_ctx *ctx = conn->ctx;
 | 
					  lnm_http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
| 
						 | 
					@ -65,6 +65,7 @@ void lnm_http_loop_process_route(lnm_http_conn *conn) {
 | 
				
			||||||
      matched_path =
 | 
					      matched_path =
 | 
				
			||||||
          regexec(route->route.regex, ctx->req.path.s,
 | 
					          regexec(route->route.regex, ctx->req.path.s,
 | 
				
			||||||
                  LNM_HTTP_MAX_REGEX_GROUPS, ctx->req.path.groups, 0) == 0;
 | 
					                  LNM_HTTP_MAX_REGEX_GROUPS, ctx->req.path.groups, 0) == 0;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Remember the previous match levels
 | 
					    // Remember the previous match levels
 | 
				
			||||||
| 
						 | 
					@ -105,9 +106,12 @@ void lnm_http_loop_process_parse_headers(lnm_http_conn *conn) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lnm_http_loop_process_steps(lnm_http_conn *conn) {
 | 
					void lnm_http_loop_process_steps(lnm_http_conn *conn) {
 | 
				
			||||||
  lnm_http_loop_ctx *ctx = conn->ctx;
 | 
					  lnm_http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
  lnm_http_step *step;
 | 
					  lnm_http_step *step = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  do {
 | 
					  // Loop until we either:
 | 
				
			||||||
 | 
					  // - reach the end of the chain of steps, indicated by NULL
 | 
				
			||||||
 | 
					  // - have a step that's waiting for I/O
 | 
				
			||||||
 | 
					  while ((ctx->cur_step != NULL) && (step != ctx->cur_step)) {
 | 
				
			||||||
    step = ctx->cur_step;
 | 
					    step = ctx->cur_step;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (step->fn(conn)) {
 | 
					    switch (step->fn(conn)) {
 | 
				
			||||||
| 
						 | 
					@ -124,16 +128,34 @@ void lnm_http_loop_process_steps(lnm_http_conn *conn) {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // Loop until we either:
 | 
					 | 
				
			||||||
  // - reach the end of the chain of steps, indicated by NULL
 | 
					 | 
				
			||||||
  // - have a step that's waiting for I/O
 | 
					 | 
				
			||||||
  while ((ctx->cur_step != NULL) && (step != ctx->cur_step));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (ctx->cur_step == NULL) {
 | 
					  if (ctx->cur_step == NULL) {
 | 
				
			||||||
    ctx->state = lnm_http_loop_state_write_headers;
 | 
					    ctx->state = lnm_http_loop_state_add_headers;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void lnm_http_loop_state_process_add_headers(lnm_http_conn *conn) {
 | 
				
			||||||
 | 
					  lnm_http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
 | 
					  lnm_http_res *res = &ctx->res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (res->body.len > 0) {
 | 
				
			||||||
 | 
					    uint64_t digits = lnm_digits(res->body.len);
 | 
				
			||||||
 | 
					    char *buf = malloc(digits + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (buf == NULL) {
 | 
				
			||||||
 | 
					      conn->state = lnm_loop_state_end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(buf, "%lu", res->body.len);
 | 
				
			||||||
 | 
					    lnm_http_res_add_header_len(res, lnm_http_header_content_length, buf,
 | 
				
			||||||
 | 
					                                digits, true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ctx->state = lnm_http_loop_state_write_status_line;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This function is intentionally written inefficiently for now, as it will most
 | 
					// This function is intentionally written inefficiently for now, as it will most
 | 
				
			||||||
// likely only have to run once for each response
 | 
					// likely only have to run once for each response
 | 
				
			||||||
void lnm_http_loop_process_write_status_line(lnm_http_conn *conn) {
 | 
					void lnm_http_loop_process_write_status_line(lnm_http_conn *conn) {
 | 
				
			||||||
| 
						 | 
					@ -199,7 +221,13 @@ void lnm_http_loop_process_write_headers(lnm_http_conn *conn) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (res->headers.current == NULL) {
 | 
					  // The headers should end with an additional newline. If there's no space left
 | 
				
			||||||
 | 
					  // in the write buffer, we don't switch states so we can re-try this write
 | 
				
			||||||
 | 
					  // later
 | 
				
			||||||
 | 
					  if ((res->headers.current == NULL) && (conn->w.size < LNM_LOOP_BUF_SIZE)) {
 | 
				
			||||||
 | 
					    conn->w.buf[conn->w.size] = '\n';
 | 
				
			||||||
 | 
					    conn->w.size++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ctx->state = ctx->res.body.len > 0 ? lnm_http_loop_state_write_body
 | 
					    ctx->state = ctx->res.body.len > 0 ? lnm_http_loop_state_write_body
 | 
				
			||||||
                                       : lnm_http_loop_state_finish;
 | 
					                                       : lnm_http_loop_state_finish;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -258,6 +286,7 @@ void (*process_fns[])(lnm_http_conn *conn) = {
 | 
				
			||||||
    lnm_http_loop_process_route,
 | 
					    lnm_http_loop_process_route,
 | 
				
			||||||
    lnm_http_loop_process_parse_headers,
 | 
					    lnm_http_loop_process_parse_headers,
 | 
				
			||||||
    lnm_http_loop_process_steps,
 | 
					    lnm_http_loop_process_steps,
 | 
				
			||||||
 | 
					    lnm_http_loop_state_process_add_headers,
 | 
				
			||||||
    lnm_http_loop_process_write_status_line,
 | 
					    lnm_http_loop_process_write_status_line,
 | 
				
			||||||
    lnm_http_loop_process_write_headers,
 | 
					    lnm_http_loop_process_write_headers,
 | 
				
			||||||
    lnm_http_loop_process_write_body,
 | 
					    lnm_http_loop_process_write_body,
 | 
				
			||||||
| 
						 | 
					@ -273,6 +302,8 @@ lnm_loop_state state_map[] = {
 | 
				
			||||||
    lnm_loop_state_req,
 | 
					    lnm_loop_state_req,
 | 
				
			||||||
    // steps
 | 
					    // steps
 | 
				
			||||||
    lnm_loop_state_req,
 | 
					    lnm_loop_state_req,
 | 
				
			||||||
 | 
					    // add_headers
 | 
				
			||||||
 | 
					    lnm_loop_state_req,
 | 
				
			||||||
    // write_status_line
 | 
					    // write_status_line
 | 
				
			||||||
    lnm_loop_state_res,
 | 
					    lnm_loop_state_res,
 | 
				
			||||||
    // write_headers
 | 
					    // write_headers
 | 
				
			||||||
| 
						 | 
					@ -301,9 +332,10 @@ void lnm_http_loop_process(lnm_http_conn *conn) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    process_fns[http_loop_state](conn);
 | 
					    process_fns[http_loop_state](conn);
 | 
				
			||||||
  } while ((conn->state == loop_state) &&
 | 
					  } while ((conn->state == loop_state) &&
 | 
				
			||||||
           (conn->state == state_map[loop_state]) &&
 | 
					           (conn->state == state_map[http_loop_state]) &&
 | 
				
			||||||
           (http_loop_state != ctx->state));
 | 
					           (http_loop_state != ctx->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Check required to prevent overwriting manually set event loop state
 | 
					  // Check required to prevent overwriting manually set event loop state
 | 
				
			||||||
  conn->state = conn->state == loop_state ? state_map[loop_state] : conn->state;
 | 
					  conn->state =
 | 
				
			||||||
 | 
					      conn->state == loop_state ? state_map[http_loop_state] : conn->state;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,8 @@ lnm_http_parse_err lnm_http_req_parse(lnm_http_req *req, char *buf,
 | 
				
			||||||
    return lnm_http_parse_err_unknown_method;
 | 
					    return lnm_http_parse_err_unknown_method;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Path will always end with a newline, which we can safely set to nul
 | 
				
			||||||
 | 
					  path[path_len] = '\0';
 | 
				
			||||||
  char *question_mark = strchr(path, '?');
 | 
					  char *question_mark = strchr(path, '?');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Only store query if the path doesn't simply end with a question mark
 | 
					  // Only store query if the path doesn't simply end with a question mark
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,3 +43,15 @@ uint64_t lnm_atoi(const char *s, size_t len) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return res;
 | 
					  return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t lnm_digits(uint64_t num) {
 | 
				
			||||||
 | 
					  int digits = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (num > 9) {
 | 
				
			||||||
 | 
					    digits++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    num /= 10;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return digits;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <netinet/in.h>
 | 
					#include <netinet/in.h>
 | 
				
			||||||
#include <poll.h>
 | 
					#include <poll.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "lnm/common.h"
 | 
					#include "lnm/common.h"
 | 
				
			||||||
| 
						 | 
					@ -43,7 +44,9 @@ lnm_err lnm_loop_accept(lnm_loop *l) {
 | 
				
			||||||
  // Append connection to list of connections
 | 
					  // Append connection to list of connections
 | 
				
			||||||
  if ((size_t)conn_fd >= l->conns.len) {
 | 
					  if ((size_t)conn_fd >= l->conns.len) {
 | 
				
			||||||
    lnm_loop_conn **new =
 | 
					    lnm_loop_conn **new =
 | 
				
			||||||
        realloc(l->conns.arr, sizeof(lnm_loop_conn *) * (conn_fd + 1));
 | 
					        l->conns.len == 0
 | 
				
			||||||
 | 
					            ? calloc(sizeof(lnm_loop_conn *), conn_fd + 1)
 | 
				
			||||||
 | 
					            : realloc(l->conns.arr, sizeof(lnm_loop_conn *) * (conn_fd + 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (new == NULL) {
 | 
					    if (new == NULL) {
 | 
				
			||||||
      close(conn_fd);
 | 
					      close(conn_fd);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,12 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lnm/common.h"
 | 
				
			||||||
 | 
					#include "lsm/store.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "http/types.h"
 | 
					#include "http/types.h"
 | 
				
			||||||
#include "http_loop.h"
 | 
					#include "http_loop.h"
 | 
				
			||||||
#include "lander.h"
 | 
					#include "lander.h"
 | 
				
			||||||
#include "lsm/store.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char lander_key_charset[] =
 | 
					const char lander_key_charset[] =
 | 
				
			||||||
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 | 
					    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 | 
				
			||||||
| 
						 | 
					@ -60,7 +62,17 @@ http_route lander_routes[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *lander_gctx_init() { return calloc(1, sizeof(lander_gctx)); }
 | 
					void *lander_gctx_init() { return calloc(1, sizeof(lander_gctx)); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *lander_ctx_init() { return calloc(1, sizeof(lander_ctx)); }
 | 
					lnm_err lander_ctx_init(void **c_ctx, void *gctx) {
 | 
				
			||||||
 | 
					  lander_ctx *ctx = calloc(1, sizeof(lander_ctx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ctx == NULL) {
 | 
				
			||||||
 | 
					    return lnm_err_failed_alloc;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *c_ctx = ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return lnm_err_ok;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lander_ctx_reset(lander_ctx *ctx) {
 | 
					void lander_ctx_reset(lander_ctx *ctx) {
 | 
				
			||||||
  if (ctx->entry != NULL) {
 | 
					  if (ctx->entry != NULL) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lnm/loop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "event_loop.h"
 | 
					#include "event_loop.h"
 | 
				
			||||||
#include "http/res.h"
 | 
					#include "http/res.h"
 | 
				
			||||||
#include "http/types.h"
 | 
					#include "http/types.h"
 | 
				
			||||||
| 
						 | 
					@ -17,14 +19,18 @@ static const char index_page[] =
 | 
				
			||||||
    "  </body>\n"
 | 
					    "  </body>\n"
 | 
				
			||||||
    "</html>\n";
 | 
					    "</html>\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool lander_get_index(event_loop_conn *conn) {
 | 
					lnm_http_step_err lander_get_index(lnm_http_conn *conn) {
 | 
				
			||||||
  http_loop_ctx *ctx = conn->ctx;
 | 
					  lnm_http_loop_ctx *ctx = conn->ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  http_res_set_body_buf(&ctx->res, index_page, sizeof(index_page) - 1, false);
 | 
					  lnm_http_res_body_set_buf(&ctx->res, (char *)index_page,
 | 
				
			||||||
  http_res_set_mime_type(&ctx->res, http_mime_html);
 | 
					                            sizeof(index_page) - 1, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  conn->state = event_loop_conn_state_res;
 | 
					  /* http_res_set_body_buf(&ctx->res, index_page, sizeof(index_page) - 1,
 | 
				
			||||||
  return true;
 | 
					   * false); */
 | 
				
			||||||
 | 
					  /* http_res_set_mime_type(&ctx->res, http_mime_html); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* conn->state = event_loop_conn_state_res; */
 | 
				
			||||||
 | 
					  return lnm_http_step_err_done;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lander_get_redirect(event_loop_conn *conn) {
 | 
					void lander_get_redirect(event_loop_conn *conn) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										32
									
								
								src/main.c
								
								
								
								
							| 
						 | 
					@ -2,9 +2,26 @@
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lnm/http/loop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "lander.h"
 | 
					#include "lander.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lnm_http_loop *loop_init(lander_gctx *gctx) {
 | 
				
			||||||
 | 
					  lnm_http_loop *hl;
 | 
				
			||||||
 | 
					  lnm_http_step *step = NULL;
 | 
				
			||||||
 | 
					  lnm_http_route *route;
 | 
				
			||||||
 | 
					  lnm_http_loop_init(&hl, gctx, lander_ctx_init,
 | 
				
			||||||
 | 
					                     (lnm_http_ctx_reset_fn)lander_ctx_reset,
 | 
				
			||||||
 | 
					                     (lnm_http_ctx_free_fn)lander_ctx_free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lnm_http_step_init(&step, lander_get_index);
 | 
				
			||||||
 | 
					  lnm_http_route_init_literal(&route, lnm_http_method_get, "/", step);
 | 
				
			||||||
 | 
					  lnm_http_loop_route_add(hl, route);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return hl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ENV(var, env_var)                                                      \
 | 
					#define ENV(var, env_var)                                                      \
 | 
				
			||||||
  const char *var = getenv(env_var);                                           \
 | 
					  const char *var = getenv(env_var);                                           \
 | 
				
			||||||
  if (var == NULL) {                                                           \
 | 
					  if (var == NULL) {                                                           \
 | 
				
			||||||
| 
						 | 
					@ -44,12 +61,15 @@ int main() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  info("Store loaded containing %lu entries", lsm_store_size(c_gctx->store));
 | 
					  info("Store loaded containing %lu entries", lsm_store_size(c_gctx->store));
 | 
				
			||||||
 | 
					  lnm_http_loop *hl = loop_init(c_gctx);
 | 
				
			||||||
 | 
					  lnm_http_loop_run(hl, port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  http_loop *hl = http_loop_init(
 | 
					  /* http_loop *hl = http_loop_init( */
 | 
				
			||||||
      lander_routes, sizeof(lander_routes) / sizeof(lander_routes[0]), c_gctx,
 | 
					  /*     lander_routes, sizeof(lander_routes) / sizeof(lander_routes[0]),
 | 
				
			||||||
      lander_ctx_init, (void (*)(void *))lander_ctx_reset,
 | 
					   * c_gctx, */
 | 
				
			||||||
      (void (*)(void *))lander_ctx_free);
 | 
					  /*     lander_ctx_init, (void (*)(void *))lander_ctx_reset, */
 | 
				
			||||||
  http_loop_set_api_key(hl, api_key);
 | 
					  /*     (void (*)(void *))lander_ctx_free); */
 | 
				
			||||||
 | 
					  /* http_loop_set_api_key(hl, api_key); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  http_loop_run(hl, port);
 | 
					  /* http_loop_run(hl, port); */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue