diff options
| author | lijia <[email protected]> | 2024-04-08 09:48:13 +0800 |
|---|---|---|
| committer | lijia <[email protected]> | 2024-04-08 09:48:13 +0800 |
| commit | 215e383be1f47cd18c235855d0cee0485f6cb423 (patch) | |
| tree | 34668fd59622c37826c3a786ba0e196a7d65147b /test/http_decoder_gtest.cpp | |
| parent | ea795e9c6940281bf8557bfd79f13f319f947c58 (diff) | |
Separate from stellar-on-sapp project.
Diffstat (limited to 'test/http_decoder_gtest.cpp')
| -rw-r--r-- | test/http_decoder_gtest.cpp | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/test/http_decoder_gtest.cpp b/test/http_decoder_gtest.cpp new file mode 100644 index 0000000..aa81df2 --- /dev/null +++ b/test/http_decoder_gtest.cpp @@ -0,0 +1,370 @@ +/* +********************************************************************************************** +* File: http_decoder_gtest.cpp +* Description: +* Authors: Liu WenTan <[email protected]> +* Date: 2023-12-15 +* Copyright: (c) Since 2023 Geedge Networks, Ltd. All rights reserved. +*********************************************************************************************** +*/ + +#include <stdio.h> +#include <time.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> + +#include "../include/http_decoder.h" + +#ifdef __cplusplus +extern "C" +{ + +#include "cJSON.h" +#include "http_decoder_gtest.h" +#include "stellar/utils.h" +#include "stellar/stellar.h" +#include "stellar/session_exdata.h" +#include "stellar/session_mq.h" + + int commit_test_result_json(cJSON *node, const char *name); +} +#endif + +#define MAX_KEY_STR_LEN 2048 + +enum http_transaction_type +{ + HTTP_TRANSACTION_REQ = 0, + HTTP_TRANSACTION_RES, + HTTP_TRANSACTION_SESSION, + HTTP_TRANSACTION_MAX +}; + +struct gtest_plug_exdata_t +{ + cJSON *result_jnode[HTTP_TRANSACTION_MAX]; +}; + +static int g_result_count = 0; +static int g_header_count = 1; +static int g_exdata_idx = 0; +static int g_topic_id = 0; + +#if 1 +void output_http_req_line(struct http_request_line *req_line) +{ + char tmp_str[MAX_KEY_STR_LEN] = {0}; + memcpy(tmp_str, req_line->method.str, req_line->method.str_len); + printf("req_method:%s\n", tmp_str); + + memset(tmp_str, 0, sizeof(tmp_str)); + memcpy(tmp_str, req_line->uri.str, req_line->uri.str_len); + printf("req_uri:%s\n", tmp_str); + + memset(tmp_str, 0, sizeof(tmp_str)); + memcpy(tmp_str, req_line->version.str, req_line->version.str_len); + printf("req_version:%s\n", tmp_str); +} + +void output_http_res_line(struct http_response_line *res_line) +{ + char tmp_str[MAX_KEY_STR_LEN] = {0}; + memcpy(tmp_str, res_line->version.str, res_line->version.str_len); + printf("res_version:%s\n", tmp_str); + + memset(tmp_str, 0, sizeof(tmp_str)); + memcpy(tmp_str, res_line->status.str, res_line->status.str_len); + printf("res_status:%s\n", tmp_str); +} + +void output_http_header(struct http_header *header) +{ + char tmp_key[MAX_KEY_STR_LEN] = {0}; + char tmp_val[MAX_KEY_STR_LEN] = {0}; + + memcpy(tmp_key, header->key.str, header->key.str_len); + memcpy(tmp_val, header->val.str, header->val.str_len); + printf("<%s:%s>\n", tmp_key, tmp_val); +} +#endif + +void output_http_body(struct hstring *body, int decompress_flag) +{ + int counter = 0; + + if (1 == decompress_flag) + { + printf("\n\n----------------decompress body len:%zu---------------\n", + body->str_len); + } + else + { + printf("\n\n----------------raw body len:%zu---------------\n", + body->str_len); + } + + for (size_t i = 0; i < body->str_len; i++) + { + if (counter % 16 == 0) + { + printf("\n"); + } + printf("%02x ", (unsigned char)body->str[i]); + counter++; + } + printf("\n"); +} + +int http_field_to_json(cJSON *object, const char *key, char *val, size_t val_len) +{ + if (NULL == object || NULL == key || NULL == val || 0 == val_len) + { + return -1; + } + + char *tmp = CALLOC(char, val_len + 1); + memcpy(tmp, val, val_len); + cJSON_AddStringToObject(object, key, tmp); + FREE(tmp); + + return 0; +} + +void req_line_to_json(cJSON *ctx, struct http_request_line *req_line) +{ + http_field_to_json(ctx, "method", req_line->method.str, + req_line->method.str_len); + http_field_to_json(ctx, "uri", req_line->uri.str, req_line->uri.str_len); + http_field_to_json(ctx, "req_version", req_line->version.str, + req_line->version.str_len); + + cJSON_AddNumberToObject(ctx, "major_version", req_line->major_version); + cJSON_AddNumberToObject(ctx, "minor_version", req_line->minor_version); +} + +void res_line_to_json(cJSON *ctx, struct http_response_line *res_line) +{ + http_field_to_json(ctx, "res_version", res_line->version.str, + res_line->version.str_len); + http_field_to_json(ctx, "res_status", res_line->status.str, + res_line->status.str_len); + + cJSON_AddNumberToObject(ctx, "major_version", res_line->major_version); + cJSON_AddNumberToObject(ctx, "minor_version", res_line->minor_version); + cJSON_AddNumberToObject(ctx, "status_code", res_line->status_code); +} + +void http_header_to_json(cJSON *ctx, struct http_header *header) +{ + char key[MAX_KEY_STR_LEN] = {0}; + + memcpy(key, header->key.str, header->key.str_len); + + if (cJSON_HasObjectItem(ctx, key) == FALSE) + { + http_field_to_json(ctx, key, header->val.str, header->val.str_len); + } + else + { + // ctx already has the key, so rename key by key%d + char new_key[MAX_KEY_STR_LEN] = {0}; + sprintf(new_key, "%s%d", key, g_header_count++); + http_field_to_json(ctx, new_key, header->val.str, header->val.str_len); + } +} + +void http_url_add_to_json(cJSON *ctx, struct http_message *msg) +{ + struct hstring url_result = {}; + + if (cJSON_GetObjectItem(ctx, GTEST_HTTP_URL_NAME)) + { + return; + } + + if (http_message_get_url(msg, &url_result) < 0) + { + // printf("url:%s\n", url_result.str); + return; + } + + struct http_header url_header_result = {}; + + url_header_result.key.str = (char *)GTEST_HTTP_URL_NAME; + url_header_result.key.str_len = strlen(GTEST_HTTP_URL_NAME); + url_header_result.val = url_result; + + http_header_to_json(ctx, &url_header_result); +} + +// Full duplex +static void commit_last_half_flow_data(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata, enum http_transaction_type type) +{ + char result_name[MAX_KEY_STR_LEN] = {0}; + + cJSON *last_jnode = gtest_plug_exdata->result_jnode[type]; + if (last_jnode) + { + sprintf(result_name, "%d", g_result_count); + commit_test_result_json(last_jnode, result_name); + gtest_plug_exdata->result_jnode[type] = NULL; + g_result_count++; + } + + gtest_plug_exdata->result_jnode[type] = cJSON_CreateObject(); + if (HTTP_TRANSACTION_REQ == type) + { + cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[type], GTEST_HTTP_TRANS_NAME, "request"); + } + else if (HTTP_TRANSACTION_RES == type) + { + cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[type], GTEST_HTTP_TRANS_NAME, "response"); + } +} + +static void http_decoder_test_update_session_tuple4(struct session *sess, struct gtest_plug_exdata_t *gtest_plug_exdata) +{ + if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] == NULL) + { + char result_name[MAX_KEY_STR_LEN] = {0}; + gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION] = cJSON_CreateObject(); + cJSON_AddStringToObject(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], GTEST_HTTP_TUPLE4_NAME, session_get0_readable_addr(sess)); + sprintf(result_name, "%d", g_result_count++); + commit_test_result_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_SESSION], result_name); + } +} + +extern "C" int +http_decoder_test_entry(struct session *sess, int topic_id, const void *data, + void *cb_arg) +{ + struct http_request_line req_line = {0}; + struct http_response_line res_line = {0}; + struct http_header header = {0}; + struct hstring body = {0}; + struct http_message *msg = (struct http_message *)data; + enum http_message_type msg_type = http_message_type(msg); + + struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)session_get_ex_data(sess, g_exdata_idx); + if (NULL == gtest_plug_exdata) + { + gtest_plug_exdata = (struct gtest_plug_exdata_t *)calloc(1, sizeof(struct gtest_plug_exdata_t)); + session_set_ex_data(sess, g_exdata_idx, gtest_plug_exdata); + } + + if (msg_type == HTTP_MESSAGE_REQ_LINE || msg_type == HTTP_MESSAGE_REQ_HEADER || msg_type == HTTP_MESSAGE_REQ_BODY) + { + cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ]; + } + else + { + cJSON *json = gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES]; + } + + http_decoder_test_update_session_tuple4(sess, gtest_plug_exdata); + + switch (msg_type) + { + case HTTP_MESSAGE_REQ_LINE: + commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_REQ); + http_message_get_request_line(msg, &req_line); + req_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &req_line); + break; + case HTTP_MESSAGE_REQ_HEADER: + while (http_message_request_header_next(msg, &header) > 0) + { + http_header_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], &header); + } + g_header_count = 1; + http_url_add_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ], msg); + break; + case HTTP_MESSAGE_REQ_BODY: + http_message_get_request_raw_body(msg, &body); + // output_http_body(&body, 0); + + http_message_get_request_decompress_body(msg, &body); + // output_http_body(&body, 1); + break; + case HTTP_MESSAGE_RES_LINE: + commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_RES); + http_message_get_response_line(msg, &res_line); + res_line_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &res_line); + break; + case HTTP_MESSAGE_RES_HEADER: + while (http_message_response_header_next(msg, &header) > 0) + { + http_header_to_json(gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES], &header); + } + g_header_count = 1; + break; + case HTTP_MESSAGE_RES_BODY: + http_message_get_response_raw_body(msg, &body); + // output_http_body(&body, 0); + + http_message_get_response_decompress_body(msg, &body); + // output_http_body(&body, 1); + break; + + // to do: check payload + default: + break; + } + + return 0; +} + +void http_decoder_test_exdata_free(struct session *sess, int idx, void *ex_ptr, + void *arg) +{ + if (ex_ptr != NULL) + { + struct gtest_plug_exdata_t *gtest_plug_exdata = (struct gtest_plug_exdata_t *)ex_ptr; + if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_REQ]) + { + commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_REQ); + } + if (gtest_plug_exdata->result_jnode[HTTP_TRANSACTION_RES]) + { + commit_last_half_flow_data(sess, gtest_plug_exdata, HTTP_TRANSACTION_RES); + } + free(ex_ptr); + } +} + +extern "C" void *http_decoder_test_init(struct stellar *st) +{ + g_exdata_idx = + stellar_session_get_ex_new_index(st, "HTTP_DECODER_REQ_TEST", + http_decoder_test_exdata_free, + NULL); + if (g_exdata_idx < 0) + { + printf("[%s:%d]: can't get http_decoder exdata index !!!\n", + __FUNCTION__, __LINE__); + exit(-1); + } + + g_topic_id = session_mq_get_topic_id(st, "HTTP_DECODER_MESSAGE"); + if (g_topic_id < 0) + { + printf("[%s:%d]: can't get http_decoder topic id !!!\n", + __FUNCTION__, __LINE__); + exit(-1); + } + + session_mq_subscribe_topic(st, g_topic_id, http_decoder_test_entry, NULL); + printf("http_decoder_test_init OK!\n"); + + return NULL; +} + +extern "C" void http_decoder_test_exit(void *test_ctx) +{ + if (test_ctx != NULL) + { + FREE(test_ctx); + } + + printf("http_decoder_test_exit OK!\n"); +}
\ No newline at end of file |
