diff options
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c')
-rw-r--r-- | fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c new file mode 100644 index 000000000..03e86a699 --- /dev/null +++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/app-framework/app-native-shared/restful_utils.c @@ -0,0 +1,493 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <stdio.h> + +#include "bi-inc/shared_utils.h" + +/* Serialization of request and response message + * + * Choices: + * We considered a few options: + * 1. coap + * 2. flatbuffer + * 3. cbor + * 4. attr-containers of our own + * 5. customized serialization for request/response + * + * Now we choose the #5 mainly because we need to quickly get the URL for + * dispatching and sometimes we want to change the URL in the original packet. + * the request format: fixed part: version: (1 byte), code (1 byte), fmt(2 + * byte), mid (4 bytes), sender_id(4 bytes), url_len(2 bytes), + * payload_len(4bytes) dynamic part: url (bytes in url_len), payload + * + * response format: + * fixed part: (1 byte), code (1 byte), fmt(2 byte), mid (4 bytes), sender_id(4 + * bytes), payload_len(4bytes) dynamic part: payload + */ +#define REQUES_PACKET_VER 1 +#define REQUEST_PACKET_FIX_PART_LEN 18 +#define REQUEST_PACKET_URL_OFFSET REQUEST_PACKET_FIX_PART_LEN +#define REQUEST_PACKET_URL_LEN \ + *((uint16 *)((char *)buffer + 12)) /* to ensure little endian */ +#define REQUEST_PACKET_PAYLOAD_LEN \ + *((uint32 *)((char *)buffer + 14)) /* to ensure little endian */ +#define REQUEST_PACKET_URL(buffer) ((char *)buffer + REQUEST_PACKET_URL_OFFSET) +#define REQUEST_PACKET_PAYLOAD(buffer) \ + ((char *)buffer + REQUEST_PACKET_URL_OFFSET \ + + REQUEST_PACKET_URL_LEN(buffer)) + +#define RESPONSE_PACKET_FIX_PART_LEN 16 + +char * +pack_request(request_t *request, int *size) +{ + int url_len = strlen(request->url) + 1; + int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len; + uint16 u16; + uint32 u32; + char *packet; + + if ((packet = (char *)WA_MALLOC(len)) == NULL) + return NULL; + + /* TODO: ensure little endian for words and dwords */ + *packet = REQUES_PACKET_VER; + *((uint8 *)(packet + 1)) = request->action; + + u16 = htons(request->fmt); + memcpy(packet + 2, &u16, 2); + + u32 = htonl(request->mid); + memcpy(packet + 4, &u32, 4); + + u32 = htonl(request->sender); + memcpy(packet + 8, &u32, 4); + + u16 = htons(url_len); + memcpy(packet + 12, &u16, 2); + + u32 = htonl(request->payload_len); + memcpy(packet + 14, &u32, 4); + + strcpy(packet + REQUEST_PACKET_URL_OFFSET, request->url); + memcpy(packet + REQUEST_PACKET_URL_OFFSET + url_len, request->payload, + request->payload_len); + + *size = len; + return packet; +} + +void +free_req_resp_packet(char *packet) +{ + WA_FREE(packet); +} + +request_t * +unpack_request(char *packet, int size, request_t *request) +{ + uint16 url_len, u16; + uint32 payload_len, u32; + + if (*packet != REQUES_PACKET_VER) { + return NULL; + } + if (size < REQUEST_PACKET_FIX_PART_LEN) { + return NULL; + } + + memcpy(&u16, packet + 12, 2); + url_len = ntohs(u16); + + memcpy(&u32, packet + 14, 4); + payload_len = ntohl(u32); + + if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) { + return NULL; + } + + if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) { + return NULL; + } + + request->action = *((uint8 *)(packet + 1)); + + memcpy(&u16, packet + 2, 2); + request->fmt = ntohs(u16); + + memcpy(&u32, packet + 4, 4); + request->mid = ntohl(u32); + + memcpy(&u32, packet + 8, 4); + request->sender = ntohl(u32); + + request->payload_len = payload_len; + request->url = REQUEST_PACKET_URL(packet); + + if (payload_len > 0) + request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len; + else + request->payload = NULL; + + return request; +} + +char * +pack_response(response_t *response, int *size) +{ + int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len; + uint16 u16; + uint32 u32; + char *packet; + + if ((packet = (char *)WA_MALLOC(len)) == NULL) + return NULL; + + /* TODO: ensure little endian for words and dwords */ + *packet = REQUES_PACKET_VER; + *((uint8 *)(packet + 1)) = response->status; + + u16 = htons(response->fmt); + memcpy(packet + 2, &u16, 2); + + u32 = htonl(response->mid); + memcpy(packet + 4, &u32, 4); + + u32 = htonl(response->reciever); + memcpy(packet + 8, &u32, 4); + + u32 = htonl(response->payload_len); + memcpy(packet + 12, &u32, 4); + + memcpy(packet + RESPONSE_PACKET_FIX_PART_LEN, response->payload, + response->payload_len); + + *size = len; + return packet; +} + +response_t * +unpack_response(char *packet, int size, response_t *response) +{ + uint16 u16; + uint32 payload_len, u32; + + if (*packet != REQUES_PACKET_VER) + return NULL; + + if (size < RESPONSE_PACKET_FIX_PART_LEN) + return NULL; + + memcpy(&u32, packet + 12, 4); + payload_len = ntohl(u32); + if (size != (RESPONSE_PACKET_FIX_PART_LEN + payload_len)) + return NULL; + + response->status = *((uint8 *)(packet + 1)); + + memcpy(&u16, packet + 2, 2); + response->fmt = ntohs(u16); + + memcpy(&u32, packet + 4, 4); + response->mid = ntohl(u32); + + memcpy(&u32, packet + 8, 4); + response->reciever = ntohl(u32); + + response->payload_len = payload_len; + if (payload_len > 0) + response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN; + else + response->payload = NULL; + + return response; +} + +request_t * +clone_request(request_t *request) +{ + /* deep clone */ + request_t *req = (request_t *)WA_MALLOC(sizeof(request_t)); + if (req == NULL) + return NULL; + + memset(req, 0, sizeof(*req)); + req->action = request->action; + req->fmt = request->fmt; + req->url = wa_strdup(request->url); + req->sender = request->sender; + req->mid = request->mid; + + if (req->url == NULL) + goto fail; + + req->payload_len = request->payload_len; + + if (request->payload_len) { + req->payload = (char *)WA_MALLOC(request->payload_len); + if (!req->payload) + goto fail; + memcpy(req->payload, request->payload, request->payload_len); + } + else { + /* when payload_len is 0, the payload may be used for + carrying some handle or integer */ + req->payload = request->payload; + } + + return req; + +fail: + request_cleaner(req); + return NULL; +} + +void +request_cleaner(request_t *request) +{ + if (request->url != NULL) + WA_FREE(request->url); + if (request->payload != NULL && request->payload_len > 0) + WA_FREE(request->payload); + + WA_FREE(request); +} + +void +response_cleaner(response_t *response) +{ + if (response->payload != NULL && response->payload_len > 0) + WA_FREE(response->payload); + + WA_FREE(response); +} + +response_t * +clone_response(response_t *response) +{ + response_t *clone = (response_t *)WA_MALLOC(sizeof(response_t)); + + if (clone == NULL) + return NULL; + + memset(clone, 0, sizeof(*clone)); + clone->fmt = response->fmt; + clone->mid = response->mid; + clone->status = response->status; + clone->reciever = response->reciever; + clone->payload_len = response->payload_len; + if (clone->payload_len) { + clone->payload = (char *)WA_MALLOC(response->payload_len); + if (!clone->payload) + goto fail; + memcpy(clone->payload, response->payload, response->payload_len); + } + else { + /* when payload_len is 0, the payload may be used for + carrying some handle or integer */ + clone->payload = response->payload; + } + return clone; + +fail: + response_cleaner(clone); + return NULL; +} + +response_t * +set_response(response_t *response, int status, int fmt, const char *payload, + int payload_len) +{ + response->payload = (void *)payload; + response->payload_len = payload_len; + response->status = status; + response->fmt = fmt; + return response; +} + +response_t * +make_response_for_request(request_t *request, response_t *response) +{ + response->mid = request->mid; + response->reciever = request->sender; + + return response; +} + +static unsigned int mid = 0; + +request_t * +init_request(request_t *request, char *url, int action, int fmt, void *payload, + int payload_len) +{ + request->url = url; + request->action = action; + request->fmt = fmt; + request->payload = payload; + request->payload_len = payload_len; + request->mid = ++mid; + + return request; +} + +/* + check if the "url" is starting with "leading_str" + return: 0 - not match; >0 - the offset of matched url, include any "/" at the + end notes: + 1. it ensures the leading_str "/abc" can pass "/abc/cde" and "/abc/, but fail + "/ab" and "/abcd". leading_str "/abc/" can pass "/abc" + 2. it omit the '/' at the first char + 3. it ensure the leading_str "/abc" can pass "/abc?cde + */ + +int +check_url_start(const char *url, int url_len, const char *leading_str) +{ + int offset = 0; + if (*leading_str == '/') + leading_str++; + if (url_len > 0 && *url == '/') { + url_len--; + url++; + offset++; + } + + int len = strlen(leading_str); + if (len == 0) + return 0; + + /* ensure leading_str not end with "/" */ + if (leading_str[len - 1] == '/') { + len--; + if (len == 0) + return 0; + } + + /* equal length */ + if (url_len == len) { + if (memcmp(url, leading_str, url_len) == 0) { + return (offset + len); + } + else { + return 0; + } + } + + if (url_len < len) + return 0; + else if (memcmp(url, leading_str, len) != 0) + return 0; + else if (url[len] != '/' && url[len] != '?') + return 0; + else + return (offset + len + 1); +} + +// * @pattern: +// * sample 1: /abcd, match /abcd only +// * sample 2: /abcd/ match match "/abcd" and "/abcd/*" +// * sample 3: /abcd*, match any url started with "/abcd" +// * sample 4: /abcd/*, exclude "/abcd" + +bool +match_url(char *pattern, char *matched) +{ + if (*pattern == '/') + pattern++; + if (*matched == '/') + matched++; + + int matched_len = strlen(matched); + if (matched_len == 0) + return false; + + if (matched[matched_len - 1] == '/') { + matched_len--; + if (matched_len == 0) + return false; + } + + int len = strlen(pattern); + if (len == 0) + return false; + + if (pattern[len - 1] == '/') { + len--; + if (strncmp(pattern, matched, len) != 0) + return false; + + if (len == matched_len) + return true; + + if (matched_len > len && matched[len] == '/') + return true; + + return false; + } + else if (pattern[len - 1] == '*') { + if (pattern[len - 2] == '/') { + if (strncmp(pattern, matched, len - 1) == 0) + return true; + else + return false; + } + else { + return (strncmp(pattern, matched, len - 1) == 0); + } + } + else { + return (strcmp(pattern, matched) == 0); + } +} + +/* + * get the value of the key from following format buffer: + * key1=value1;key2=value2;key3=value3 + */ +char * +find_key_value(char *buffer, int buffer_len, char *key, char *value, + int value_len, char delimiter) +{ + char *p = buffer; + int remaining = buffer_len; + int key_len = strlen(key); + + while (*p != 0 && remaining > 0) { + while (*p == ' ' || *p == delimiter) { + p++; + remaining--; + } + + if (remaining <= key_len) + return NULL; + + /* find the key */ + if (0 == strncmp(p, key, key_len) && p[key_len] == '=') { + p += (key_len + 1); + remaining -= (key_len + 1); + char *v = value; + memset(value, 0, value_len); + value_len--; /* ensure last char is 0 */ + while (*p != delimiter && remaining > 0 && value_len > 0) { + *v++ = *p++; + remaining--; + value_len--; + } + return value; + } + + /* goto next key */ + while (*p != delimiter && remaining > 0) { + p++; + remaining--; + } + } + + return NULL; +} |