/* SPDX-License-Identifier: Apache-2.0 */ /* * Copyright (C) Andrew Clayton * Copyright (C) F5, Inc. */ #ifndef _UNIT_WASM_H_ #define _UNIT_WASM_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif #define LUW_VERSION_MAJOR 0 #define LUW_VERSION_MINOR 3 #define LUW_VERSION_PATCH 0 /* Version number in hex 0xMMmmpp00 */ #define LUW_VERSION_NUMBER \ ( (LUW_VERSION_MAJOR << 24) | \ (LUW_VERSION_MINOR << 16) | \ (LUW_VERSION_PATCH << 8) ) #define __luw_export_name(name) __attribute__((export_name(name))) #define __luw_unused __attribute__((unused)) #define __luw_maybe_unused __luw_unused typedef uint64_t u64; typedef int64_t s64; typedef uint32_t u32; typedef int32_t s32; typedef uint16_t u16; typedef int16_t s16; typedef uint8_t u8; typedef int8_t s8; typedef enum { LUW_HTTP_CONTINUE = 100, LUW_HTTP_SWITCHING_PROTOCOLS = 101, LUW_HTTP_OK = 200, LUW_HTTP_CREATED = 201, LUW_HTTP_ACCEPTED = 202, LUW_HTTP_NO_CONTENT = 204, LUW_HTTP_MULTIPLE_CHOICES = 300, LUW_HTTP_MOVED_PERMANENTLY = 301, LUW_HTTP_FOUND = 302, LUW_HTTP_SEE_OTHER = 303, LUW_HTTP_NOT_MODIFIED = 304, LUW_HTTP_TEMPORARY_REDIRECT = 307, LUW_HTTP_PERMANENT_REDIRECT = 308, LUW_HTTP_BAD_REQUEST = 400, LUW_HTTP_UNAUTHORIZED = 401, LUW_HTTP_FORBIDDEN = 403, LUW_HTTP_NOT_FOUND = 404, LUW_HTTP_METHOD_NOT_ALLOWED = 405, LUW_HTTP_NOT_ACCEPTABLE = 406, LUW_HTTP_REQUEST_TIMEOUT = 408, LUW_HTTP_CONFLICT = 409, LUW_HTTP_GONE = 410, LUW_HTTP_LENGTH_REQUIRED = 411, LUW_HTTP_PAYLOAD_TOO_LARGE = 413, LUW_HTTP_URI_TOO_LONG = 414, LUW_HTTP_UNSUPPORTED_MEDIA_TYPE = 415, LUW_HTTP_UPGRADE_REQUIRED = 426, LUW_HTTP_TOO_MANY_REQUESTS = 429, LUW_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, /* Proposed by RFC 7725 */ LUW_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451, LUW_HTTP_INTERNAL_SERVER_ERROR = 500, LUW_HTTP_NOT_IMPLEMENTED = 501, LUW_HTTP_BAD_GATEWAY = 502, LUW_HTTP_SERVICE_UNAVAILABLE = 503, LUW_HTTP_GATEWAY_TIMEOUT = 504, } luw_http_status_t; #if !defined(__DEFINED_ssize_t) /* * Match the typedef from wasm32-wasi/include/bits/alltypes.h * without requiring the wasi-sysroot for building the rust * stuff. */ typedef long ssize_t; #endif struct luw_hdr_field { u32 name_off; u32 name_len; u32 value_off; u32 value_len; }; struct luw_req { u32 method_off; u32 method_len; u32 version_off; u32 version_len; u32 path_off; u32 path_len; u32 query_off; u32 query_len; u32 remote_off; u32 remote_len; u32 local_addr_off; u32 local_addr_len; u32 local_port_off; u32 local_port_len; u32 server_name_off; u32 server_name_len; u64 content_len; u64 total_content_sent; u32 content_sent; u32 content_off; u32 request_size; u32 nr_fields; u32 tls; char __pad[4]; struct luw_hdr_field fields[]; }; struct luw_resp { u32 size; u8 data[]; }; struct luw_resp_hdr { u32 nr_fields; struct luw_hdr_field fields[]; }; typedef struct { /* pointer to the shared memory */ u8 *addr; /* points to the end of ctx->resp->data */ u8 *mem; /* struct luw_req representation of the shared memory */ struct luw_req *req; /* struct luw_resp representation of the shared memory */ struct luw_resp *resp; /* struct luw_resp_hdr represnetation of the shared memory */ struct luw_resp_hdr *resp_hdr; /* offset to where the struct resp starts in the shared memory */ size_t resp_offset; /* points to the external buffer used for a copy of the request */ u8 *req_buf; /* points to the end of the fields array in struct luw_resp_hdr */ u8 *hdrp; /* points to the end of ctx->req_buf */ u8 *reqp; /* tracks the response header index number */ s32 resp_hdr_idx; } luw_ctx_t; typedef enum { LUW_SRB_NONE = 0x00, LUW_SRB_APPEND = 0x01, LUW_SRB_ALLOC = 0x02, LUW_SRB_FULL_SIZE = 0x04, LUW_SRB_FLAGS_ALL = (LUW_SRB_NONE|LUW_SRB_APPEND|LUW_SRB_ALLOC| LUW_SRB_FULL_SIZE) } luw_srb_flags_t; typedef struct luw_hdr_field luw_http_hdr_iter_t; #define luw_foreach_http_hdr(ctx, iter, name, value) \ for (iter = ctx.req->fields, \ name = (const char *)ctx.req + iter->name_off; \ (iter < (ctx.req->fields + ctx.req->nr_fields)) && \ (value = (const char *)ctx.req + iter->value_off); \ iter++, name = (const char *)ctx.req + iter->name_off) /* Imported functions from the host/runtime */ __attribute__((import_module("env"), import_name("nxt_wasm_get_init_mem_size"))) u32 nxt_wasm_get_init_mem_size(void); __attribute__((import_module("env"), import_name("nxt_wasm_response_end"))) void nxt_wasm_response_end(void); __attribute__((import_module("env"), import_name("nxt_wasm_send_headers"))) void nxt_wasm_send_headers(u32 offset); __attribute__((import_module("env"), import_name("nxt_wasm_send_response"))) void nxt_wasm_send_response(u32 offset); __attribute__((import_module("env"), import_name("nxt_wasm_set_resp_status"))) void nxt_wasm_set_resp_status(u32 status); extern void luw_module_init_handler(void); extern void luw_module_end_handler(void); extern void luw_request_init_handler(void); extern void luw_request_end_handler(void); extern void luw_response_end_handler(void); extern int luw_request_handler(u8 *addr); extern void luw_free_handler(u32 addr); extern u32 luw_malloc_handler(size_t size); #pragma GCC visibility push(default) extern void luw_init_ctx(luw_ctx_t *ctx, u8 *addr, size_t offset); extern int luw_set_req_buf(luw_ctx_t *ctx, u8 **buf, unsigned int flags); extern const char *luw_get_http_path(const luw_ctx_t *ctx); extern const char *luw_get_http_method(const luw_ctx_t *ctx); extern const char *luw_get_http_version(const luw_ctx_t *ctx); extern const char *luw_get_http_query(const luw_ctx_t *ctx); extern const char *luw_get_http_remote(const luw_ctx_t *ctx); extern const char *luw_get_http_local_addr(const luw_ctx_t *ctx); extern const char *luw_get_http_local_port(const luw_ctx_t *ctx); extern const char *luw_get_http_server_name(const luw_ctx_t *ctx); extern const u8 *luw_get_http_content(const luw_ctx_t *ctx); extern u64 luw_get_http_content_len(const luw_ctx_t *ctx); extern size_t luw_get_http_content_sent(const luw_ctx_t *ctx); extern u64 luw_get_http_total_content_sent(const luw_ctx_t *ctx); extern bool luw_http_is_tls(const luw_ctx_t *ctx); extern void luw_http_hdr_iter(luw_ctx_t *ctx, bool (*luw_http_hdr_iter_func)(luw_ctx_t *ctx, const char *name, const char *value, void *data), void *user_data); extern const char *luw_http_hdr_get_value(const luw_ctx_t *ctx, const char *hdr); extern size_t luw_get_response_data_size(const luw_ctx_t *ctx); extern int luw_mem_writep(luw_ctx_t *ctx, const char *fmt, ...); extern size_t luw_mem_writep_data(luw_ctx_t *ctx, const u8 *src, size_t size); extern void luw_req_buf_append(luw_ctx_t *ctx, const u8 *src); extern void luw_req_buf_copy(luw_ctx_t *ctx, const u8 *src); extern ssize_t luw_mem_splice_file(const u8 *src, int fd); extern size_t luw_mem_fill_buf_from_req(luw_ctx_t *ctx, size_t from); extern void luw_mem_reset(luw_ctx_t *ctx); extern void luw_http_set_response_status(luw_http_status_t status); extern void luw_http_send_response(const luw_ctx_t *ctx); extern void luw_http_init_headers(luw_ctx_t *ctx, size_t nr, size_t offset); extern void luw_http_add_header(luw_ctx_t *ctx, const char *name, const char *value); extern void luw_http_send_headers(const luw_ctx_t *ctx); extern void luw_http_response_end(void); extern u32 luw_mem_get_init_size(void); /* * Convenience wrappers for the Rust bindings, not for general consumption. */ extern void *luw_malloc(size_t size); extern void luw_free(void *ptr); #pragma GCC visibility pop #ifdef __cplusplus } /* extern "C" */ #endif #endif /* _UNIT_WASM_H_ */