src/x_builtins.c
raw ยท 2501 bytes
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "klog.h"
#include "x_builtins.h"
int x_builtin_parse(const char *s, enum x_builtin_upstream *out)
{
if (s == NULL || out == NULL) {
return -EINVAL;
}
if (strcmp(s, "client_addr") == 0) {
*out = X_BUILTIN_CLIENT_ADDR;
return 0;
}
if (strcmp(s, "discard") == 0) {
*out = X_BUILTIN_DISCARD;
return 0;
}
if (strcmp(s, "hang") == 0) {
*out = X_BUILTIN_HANG;
return 0;
}
if (strcmp(s, "http_ok") == 0) {
*out = X_BUILTIN_HTTP_OK;
return 0;
}
if (strcmp(s, "log_conn") == 0) {
*out = X_BUILTIN_LOG_CONN;
return 0;
}
if (strcmp(s, "close") == 0) {
*out = X_BUILTIN_CLOSE;
return 0;
}
if (strcmp(s, "close") == 0) {
*out = X_BUILTIN_CLOSE;
return 0;
}
return -EINVAL;
}
const char *x_builtin_name(enum x_builtin_upstream builtin)
{
switch (builtin) {
case X_BUILTIN_CLIENT_ADDR:
return "client_addr";
case X_BUILTIN_DISCARD:
return "discard";
case X_BUILTIN_HANG:
return "hang";
case X_BUILTIN_HTTP_OK:
return "http_ok";
case X_BUILTIN_LOG_CONN:
return "log_conn";
case X_BUILTIN_CLOSE:
return "close";
case X_BUILTIN_NONE:
default:
return "none";
}
}
int x_builtin_handle(
const struct x_builtin_request *req,
struct x_builtin_response *res
) {
int n;
if (req == NULL || res == NULL) {
return -EINVAL;
}
memset(res, 0, sizeof(*res));
switch (req->builtin) {
case X_BUILTIN_CLIENT_ADDR:
if (req->client_addr == NULL) {
return -EINVAL;
}
n = snprintf(res->data, sizeof(res->data), "%s\n", req->client_addr);
if (n < 0 || (size_t)n >= sizeof(res->data)) {
return -ENOSPC;
}
res->data_len = (size_t)n;
res->action = X_BUILTIN_ACTION_CLOSE;
return 0;
case X_BUILTIN_HTTP_OK: {
static const char http_ok[] =
"HTTP/1.1 200 OK\r\n"
"Content-Length: 2\r\n"
"Connection: close\r\n"
"\r\n"
"OK";
memcpy(res->data, http_ok, sizeof(http_ok) - 1);
res->data_len = sizeof(http_ok) - 1;
res->action = X_BUILTIN_ACTION_CLOSE;
return 0;
}
case X_BUILTIN_DISCARD:
res->action = X_BUILTIN_ACTION_DISCARD;
return 0;
case X_BUILTIN_LOG_CONN:
LOG_INFO("log_conn", "client_addr", _LOGV(req->client_addr));
res->data_len = 0;
res->action = X_BUILTIN_ACTION_CLOSE;
return 0;
case X_BUILTIN_CLOSE:
res->data_len = 0;
res->action = X_BUILTIN_ACTION_CLOSE;
return 0;
case X_BUILTIN_HANG:
res->action = X_BUILTIN_ACTION_HANG;
return 0;
case X_BUILTIN_NONE:
default:
return -EINVAL;
}
}