diff --git a/README.md b/README.md index 22984d8cfe1ae818c39605463c82dbf6f5b29e05..522fc0ebc1277684b77589c5c62d061f7b33ce32 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![Build status](https://ci.appveyor.com/api/projects/status/kf3pwh2or5afsgl9/branch/master?svg=true)](https://ci.appveyor.com/project/sangshuduo/tdengine-2n8ge/branch/master) [![Coverage Status](https://coveralls.io/repos/github/taosdata/TDengine/badge.svg?branch=develop)](https://coveralls.io/github/taosdata/TDengine?branch=develop) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/4201/badge)](https://bestpractices.coreinfrastructure.org/projects/4201) -[![Docker Pulls](https://img.shields.io/docker/pulls/tdengine/tdengine)](https://hub.docker.com/repository/docker/tdengine/tdengine) [![tdengine](https://snapcraft.io//tdengine/badge.svg)](https://snapcraft.io/tdengine) [![TDengine](TDenginelogo.png)](https://www.taosdata.com) @@ -92,6 +91,8 @@ cd TDengine ## Build TDengine +### On Linux platform + ```bash mkdir debug && cd debug cmake .. && cmake --build . @@ -109,6 +110,34 @@ aarch32: cmake .. -DCPUTYPE=aarch32 && cmake --build . ``` +### On Windows platform + +If you use the Visual Studio 2013, please open a command window by executing "cmd.exe". +Please specify "x86_amd64" for 64 bits Windows or specify "x86" is for 32 bits Windows when you execute vcvarsall.bat. +``` +mkdir debug && cd debug +"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" < x86_amd64 | x86 > +cmake .. -G "NMake Makefiles" +nmake +``` + +If you use the Visual Studio 2019, please open a command window by executing "cmd.exe". +Please specify "x64" for 64 bits Windows or specify "x86" is for 32 bits Windows when you execute vcvarsall.bat. +``` +mkdir debug && cd debug +"c:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" < x64 | x86 > +cmake .. -G "NMake Makefiles" +nmake +``` + +Or, you can open a command window by clicking Visual Studio 2019 menu "Tools -> Command Line -> Developer Command Prompt" or "Tools -> Command Line -> Developer PowerShell" then execute commands as follows: +``` +mkdir debug && cd debug +cmake .. -G "NMake Makefiles" +nmake +``` + +# Quick Run # Quick Run To quickly start a TDengine server after building, run the command below in terminal: ```cmd diff --git a/cmake/install.inc b/cmake/install.inc index 7a92a396e32bdd60a7fb07f5466f243c73816a16..0531d4004839b6f61115d0551414f91fb13f2db6 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -13,7 +13,7 @@ ELSEIF (TD_WINDOWS) IF (NOT TD_GODLL) #INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector) #INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/grafana DESTINATION connector) - #INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector) + INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/tests/examples DESTINATION .) INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/packaging/cfg DESTINATION .) INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taos.h DESTINATION include) diff --git a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md index ae42582687aa08f43f101e2c099180f7afa88258..cb7a01741164059998fd3579012cdb2467b08bd1 100644 --- a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md +++ b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md @@ -110,6 +110,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。 + - **显示系统所有数据库** ```mysql SHOW DATABASES; diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index 09eb8f167eb97f829cbcce2db7185956dd329ebf..18926a84b9b7f185ebdc7935220eac486032d36e 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -526,7 +526,7 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, STableMeta *pTableMe int32_t index = 0; SStrToken sToken; - int16_t numOfRows = 0; + int32_t numOfRows = 0; SSchema *pSchema = tscGetTableSchema(pTableMeta); STableComInfo tinfo = tscGetTableInfo(pTableMeta); diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 3198d6d97ecaae896fd3109e4b49a2885abb7785..67e2d43c98c11a24e348b5102377367024fa0286 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -97,8 +97,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_APP_ERROR, 0, 0x0211, "Applicatio TAOS_DEFINE_ERROR(TSDB_CODE_TSC_ACTION_IN_PROGRESS, 0, 0x0212, "Action in progress") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DISCONNECTED, 0, 0x0213, "Disconnected from service") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_WRITE_AUTH, 0, 0x0214, "No write permission") -TAOS_DEFINE_ERROR(TSDB_CODE_TSC_CONN_KILLED, 0, 0x0215, "Connection killed") -TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, 0, 0x0216, "Syntax error in SQL") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_CONN_KILLED, 0, 0x0215, "Connection killed") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, 0, 0x0216, "Syntax errr in SQL") // mnode TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, 0, 0x0300, "Message not processed") @@ -247,6 +247,106 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_ENABLED, 0, 0x0901, "Sync modul // wal TAOS_DEFINE_ERROR(TSDB_CODE_WAL_APP_ERROR, 0, 0x1000, "Unexpected generic error in wal") +// http +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_SERVER_OFFLINE, 0, 0x1100, "http server is not onlin") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_UNSUPPORT_URL, 0, 0x1101, "url is not support") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVLALID_URL, 0, 0x1102, "invalid url format") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_ENOUGH_MEMORY, 0, 0x1103, "no enough memory") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_REQUSET_TOO_BIG, 0, 0x1104, "request size is too big") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_AUTH_INFO, 0, 0x1105, "no auth info input") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_MSG_INPUT, 0, 0x1106, "request is empty") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_SQL_INPUT, 0, 0x1107, "no sql input") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_EXEC_USEDB, 0, 0x1108, "no need to execute use db cmd") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_SESSION_FULL, 0, 0x1109, "session list was full") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GEN_TAOSD_TOKEN_ERR, 0, 0x110A, "generate taosd token error") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_MULTI_REQUEST, 0, 0x110B, "size of multi request is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_CREATE_GZIP_FAILED, 0, 0x110C, "failed to create gzip") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_FINISH_GZIP_FAILED, 0, 0x110D, "failed to finish gzip") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_LOGIN_FAILED, 0, 0x110E, "failed to login") + +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_VERSION, 0, 0x1120, "invalid http version") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_CONTENT_LENGTH, 0, 0x1121, "invalid content length") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_AUTH_TYPE, 0, 0x1122, "invalid type of Authorization") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_AUTH_FORMAT, 0, 0x1123, "invalid format of Authorization") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_BASIC_AUTH, 0, 0x1124, "invalid basic Authorization") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_TAOSD_AUTH, 0, 0x1125, "invalid taosd Authorization") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_METHOD_FAILED, 0, 0x1126, "failed to parse method") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_TARGET_FAILED, 0, 0x1127, "failed to parse target") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_VERSION_FAILED, 0, 0x1128, "failed to parse http version") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_SP_FAILED, 0, 0x1129, "failed to parse sp") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_STATUS_FAILED, 0, 0x112A, "failed to parse status") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_PHRASE_FAILED, 0, 0x112B, "failed to parse phrase") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_CRLF_FAILED, 0, 0x112C, "failed to parse crlf") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_HEADER_FAILED, 0, 0x112D, "failed to parse header") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_HEADER_KEY_FAILED, 0, 0x112E, "failed to parse header key") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_HEADER_VAL_FAILED, 0, 0x112F, "failed to parse header val") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_CHUNK_SIZE_FAILED, 0, 0x1130, "failed to parse chunk size") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_CHUNK_FAILED, 0, 0x1131, "failed to parse chunk") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_END_FAILED, 0, 0x1132, "failed to parse end section") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_INVALID_STATE, 0, 0x1134, "invalid parse state") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_ERROR_STATE, 0, 0x1135, "failed to parse error section") + +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GC_QUERY_NULL, 0, 0x1150, "query size is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GC_QUERY_SIZE, 0, 0x1151, "query size can not more than 100") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GC_REQ_PARSE_ERROR, 0, 0x1152, "parse grafana json error") + +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_DB_NOT_INPUT, 0, 0x1160, "database name can not be null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_DB_TOO_LONG, 0, 0x1161, "database name too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_INVALID_JSON, 0, 0x1162, "invalid telegraf json fromat") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRICS_NULL, 0, 0x1163, "metrics size is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRICS_SIZE, 0, 0x1164, "metrics size can not more than 1K") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_NULL, 0, 0x1165, "metric name not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_TYPE, 0, 0x1166, "metric name type should be string") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_NAME_NULL, 0, 0x1167, "metric name length is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_NAME_LONG, 0, 0x1168, "metric name length too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TIMESTAMP_NULL, 0, 0x1169, "timestamp not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TIMESTAMP_TYPE, 0, 0x116A, "timestamp type should be integer") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TIMESTAMP_VAL_NULL, 0, 0x116B, "timestamp value smaller than 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAGS_NULL, 0, 0x116C, "tags not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAGS_SIZE_0, 0, 0x116D, "tags size is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAGS_SIZE_LONG, 0, 0x116E, "tags size too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_NULL, 0, 0x116F, "tag is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_NAME_NULL, 0, 0x1170, "tag name is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_NAME_SIZE, 0, 0x1171, "tag name length too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_VALUE_TYPE, 0, 0x1172, "tag value type should be number or string") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_VALUE_NULL, 0, 0x1173, "tag value is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TABLE_NULL, 0, 0x1174, "table is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TABLE_SIZE, 0, 0x1175, "table name length too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELDS_NULL, 0, 0x1176, "fields not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELDS_SIZE_0, 0, 0x1177, "fields size is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELDS_SIZE_LONG, 0, 0x1178, "fields size too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_NULL, 0, 0x1179, "field is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_NAME_NULL, 0, 0x117A, "field name is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_NAME_SIZE, 0, 0x117B, "field name length too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_VALUE_TYPE, 0, 0x117C, "field value type should be number or string") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_VALUE_NULL, 0, 0x117D, "field value is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_HOST_NOT_STRING, 0, 0x117E, "host type should be string") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_STABLE_NOT_EXIST, 0, 0x117F, "stable not exist") + +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_DB_NOT_INPUT, 0, 0x1190, "database name can not be null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_DB_TOO_LONG, 0, 0x1191, "database name too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_INVALID_JSON, 0, 0x1192, "invalid opentsdb json fromat") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRICS_NULL, 0, 0x1193, "metrics size is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRICS_SIZE, 0, 0x1194, "metrics size can not more than 10K") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_NULL, 0, 0x1195, "metric name not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_TYPE, 0, 0x1196, "metric name type should be string") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_NAME_NULL, 0, 0x1197, "metric name length is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_NAME_LONG, 0, 0x1198, "metric name length can not more than 22") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TIMESTAMP_NULL, 0, 0x1199, "timestamp not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TIMESTAMP_TYPE, 0, 0x119A, "timestamp type should be integer") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TIMESTAMP_VAL_NULL, 0, 0x119B, "timestamp value smaller than 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAGS_NULL, 0, 0x119C, "tags not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAGS_SIZE_0, 0, 0x119D, "tags size is 0") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAGS_SIZE_LONG, 0, 0x119E, "tags size too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_NULL, 0, 0x119F, "tag is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_NAME_NULL, 0, 0x11A0, "tag name is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_NAME_SIZE, 0, 0x11A1, "tag name length too long") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_TYPE, 0, 0x11A2, "tag value type should be boolean, number or string") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_NULL, 0, 0x11A3, "tag value is null") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_TOO_LONG, 0, 0x11A4, "tag value can not more than 64") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, 0, 0x11A5, "value not find") +TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, 0, 0x11A6, "value type should be boolean, number or string") + #ifdef TAOS_ERROR_C }; #endif diff --git a/src/plugins/http/inc/httpAuth.h b/src/plugins/http/inc/httpAuth.h index b8fabbe1ec28698cd35bf343af092eeb2d840716..2ce9725d4bb57c9d24e3eddffb54707b0129b1cf 100644 --- a/src/plugins/http/inc/httpAuth.h +++ b/src/plugins/http/inc/httpAuth.h @@ -16,8 +16,8 @@ #ifndef TDENGINE_HTTP_TOKEN_H #define TDENGINE_HTTP_TOKEN_H -bool httpParseBasicAuthToken(HttpContext *pContext, char *token, int len); -bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len); -bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen); +int32_t httpParseBasicAuthToken(HttpContext *pContext, char *token, int32_t len); +int32_t httpParseTaosdAuthToken(HttpContext *pContext, char *token, int32_t len); +int32_t httpGenTaosdAuthToken(HttpContext *pContext, char *token, int32_t maxLen); #endif \ No newline at end of file diff --git a/src/plugins/http/inc/httpCode.h b/src/plugins/http/inc/httpCode.h deleted file mode 100644 index 08111260e95e0cdc3dc417e4442528c5aa1eee3c..0000000000000000000000000000000000000000 --- a/src/plugins/http/inc/httpCode.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef TDENGINE_HTTP_CODE_H -#define TDENGINE_HTTP_CODE_H - -//for fixed msg info -#define HTTP_SUCCESS 0 -#define HTTP_SERVER_OFFLINE 1 -#define HTTP_UNSUPPORT_URL 2 -#define HTTP_PARSE_HTTP_METHOD_ERROR 3 -#define HTTP_PARSE_HTTP_VERSION_ERROR 4 -#define HTTP_PARSE_HEAD_ERROR 5 -#define HTTP_REQUSET_TOO_BIG 6 -#define HTTP_PARSE_BODY_ERROR 7 -#define HTTP_PARSE_CHUNKED_BODY_ERROR 8 -#define HTTP_PARSE_URL_ERROR 9 -#define HTTP_INVALID_AUTH_TOKEN 10 -#define HTTP_PARSE_USR_ERROR 11 -#define HTTP_NO_SQL_INPUT 12 -#define HTTP_SESSION_FULL 13 -#define HTTP_NO_ENOUGH_MEMORY 14 -#define HTTP_GEN_TAOSD_TOKEN_ERR 15 -#define HTTP_INVALID_DB_TABLE 16 -#define HTTP_NO_EXEC_USEDB 17 -#define HTTP_PARSE_GC_REQ_ERROR 18 -#define HTTP_INVALID_MULTI_REQUEST 19 -#define HTTP_NO_MSG_INPUT 20 -#define HTTP_NO_ENOUGH_SESSIONS 21 - -//telegraf -#define HTTP_TG_DB_NOT_INPUT 22 -#define HTTP_TG_DB_TOO_LONG 23 -#define HTTP_TG_INVALID_JSON 24 -#define HTTP_TG_METRICS_NULL 25 -#define HTTP_TG_METRICS_SIZE 26 -#define HTTP_TG_METRIC_NULL 27 -#define HTTP_TG_METRIC_TYPE 28 -#define HTTP_TG_METRIC_NAME_NULL 29 -#define HTTP_TG_METRIC_NAME_LONG 30 -#define HTTP_TG_TIMESTAMP_NULL 31 -#define HTTP_TG_TIMESTAMP_TYPE 32 -#define HTTP_TG_TIMESTAMP_VAL_NULL 33 -#define HTTP_TG_TAGS_NULL 34 -#define HTTP_TG_TAGS_SIZE_0 35 -#define HTTP_TG_TAGS_SIZE_LONG 36 -#define HTTP_TG_TAG_NULL 37 -#define HTTP_TG_TAG_NAME_NULL 38 -#define HTTP_TG_TAG_NAME_SIZE 39 -#define HTTP_TG_TAG_VALUE_TYPE 40 -#define HTTP_TG_TAG_VALUE_NULL 41 -#define HTTP_TG_TABLE_NULL 42 -#define HTTP_TG_TABLE_SIZE 43 -#define HTTP_TG_FIELDS_NULL 44 -#define HTTP_TG_FIELDS_SIZE_0 45 -#define HTTP_TG_FIELDS_SIZE_LONG 46 -#define HTTP_TG_FIELD_NULL 47 -#define HTTP_TG_FIELD_NAME_NULL 48 -#define HTTP_TG_FIELD_NAME_SIZE 49 -#define HTTP_TG_FIELD_VALUE_TYPE 50 -#define HTTP_TG_FIELD_VALUE_NULL 51 -#define HTTP_INVALID_BASIC_AUTH_TOKEN 52 -#define HTTP_INVALID_TAOSD_AUTH_TOKEN 53 -#define HTTP_TG_HOST_NOT_STRING 54 - -//grafana -#define HTTP_GC_QUERY_NULL 55 -#define HTTP_GC_QUERY_SIZE 56 - -//opentsdb -#define HTTP_OP_DB_NOT_INPUT 57 -#define HTTP_OP_DB_TOO_LONG 58 -#define HTTP_OP_INVALID_JSON 59 -#define HTTP_OP_METRICS_NULL 60 -#define HTTP_OP_METRICS_SIZE 61 -#define HTTP_OP_METRIC_NULL 62 -#define HTTP_OP_METRIC_TYPE 63 -#define HTTP_OP_METRIC_NAME_NULL 64 -#define HTTP_OP_METRIC_NAME_LONG 65 -#define HTTP_OP_TIMESTAMP_NULL 66 -#define HTTP_OP_TIMESTAMP_TYPE 67 -#define HTTP_OP_TIMESTAMP_VAL_NULL 68 -#define HTTP_OP_TAGS_NULL 69 -#define HTTP_OP_TAGS_SIZE_0 70 -#define HTTP_OP_TAGS_SIZE_LONG 71 -#define HTTP_OP_TAG_NULL 72 -#define HTTP_OP_TAG_NAME_NULL 73 -#define HTTP_OP_TAG_NAME_SIZE 74 -#define HTTP_OP_TAG_VALUE_TYPE 75 -#define HTTP_OP_TAG_VALUE_NULL 76 -#define HTTP_OP_TAG_VALUE_TOO_LONG 77 -#define HTTP_OP_VALUE_NULL 78 -#define HTTP_OP_VALUE_TYPE 79 - -//tgf -#define HTTP_TG_STABLE_NOT_EXIST 80 - -extern char *httpMsg[]; - -#endif \ No newline at end of file diff --git a/src/plugins/http/inc/httpContext.h b/src/plugins/http/inc/httpContext.h index a2d50d6b7fdfba3bc80c918abd7999247636b6ee..260858c5cc22aa10dc49a61743879d768907c8fe 100644 --- a/src/plugins/http/inc/httpContext.h +++ b/src/plugins/http/inc/httpContext.h @@ -25,7 +25,7 @@ const char *httpContextStateStr(HttpContextState state); HttpContext *httpCreateContext(int32_t fd); bool httpInitContext(HttpContext *pContext); HttpContext *httpGetContext(void * pContext); -void httpReleaseContext(HttpContext *pContext); +void httpReleaseContext(HttpContext *pContext, bool clearRes); void httpCloseContextByServer(HttpContext *pContext); void httpCloseContextByApp(HttpContext *pContext); void httpNotifyContextClose(HttpContext *pContext); diff --git a/src/plugins/http/inc/gcHandle.h b/src/plugins/http/inc/httpGcHandle.h similarity index 100% rename from src/plugins/http/inc/gcHandle.h rename to src/plugins/http/inc/httpGcHandle.h diff --git a/src/plugins/http/inc/gcJson.h b/src/plugins/http/inc/httpGcJson.h similarity index 96% rename from src/plugins/http/inc/gcJson.h rename to src/plugins/http/inc/httpGcJson.h index 609bb9b95e6255a6fdf215320b24bbc9292e87e2..0ba860687dfe370d5b418a7c6d7aa28d128d7a5d 100644 --- a/src/plugins/http/inc/gcJson.h +++ b/src/plugins/http/inc/httpGcJson.h @@ -24,7 +24,7 @@ void gcCleanQueryJson(HttpContext *pContext); void gcStartQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result); void gcStopQueryJson(HttpContext *pContext, HttpSqlCmd *cmd); -bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows); +bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows); void gcSendHeartBeatResp(HttpContext *pContext, HttpSqlCmd *cmd); diff --git a/src/plugins/http/inc/httpGzip.h b/src/plugins/http/inc/httpGzip.h new file mode 100644 index 0000000000000000000000000000000000000000..aeac79c9759078efb64669037c54122b2900d132 --- /dev/null +++ b/src/plugins/http/inc/httpGzip.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef HTTP_GZIP_H +#define HTTP_GZIP_H + +#define EHTTP_GZIP_CHUNK_SIZE_DEFAULT (1024*16) + +typedef struct ehttp_gzip_s ehttp_gzip_t; + +typedef struct ehttp_gzip_callbacks_s ehttp_gzip_callbacks_t; +typedef struct ehttp_gzip_conf_s ehttp_gzip_conf_t; + +struct ehttp_gzip_callbacks_s { + void (*on_data)(ehttp_gzip_t *gzip, void *arg, const char *buf, int32_t len); +}; + +struct ehttp_gzip_conf_s { + int32_t get_header:2; // 0: not fetching header info + int32_t chunk_size; // 0: fallback to default: EHTTP_GZIP_CHUNK_SIZE_DEFAULT +}; + +ehttp_gzip_t* ehttp_gzip_create_decompressor(ehttp_gzip_conf_t conf, ehttp_gzip_callbacks_t callbacks, void *arg); +ehttp_gzip_t* ehttp_gzip_create_compressor(ehttp_gzip_conf_t conf, ehttp_gzip_callbacks_t callbacks, void *arg); +void ehttp_gzip_destroy(ehttp_gzip_t *gzip); + +int32_t ehttp_gzip_write(ehttp_gzip_t *gzip, const char *buf, int32_t len); +int32_t ehttp_gzip_finish(ehttp_gzip_t *gzip); + +#endif // _ehttp_gzip_h_9196791b_ac2a_4d73_9979_f4b41abbc4c0_ + diff --git a/src/plugins/http/inc/httpInt.h b/src/plugins/http/inc/httpInt.h index ffd621be7acf223bc002c7b49d87bad595211d2b..36a022159f4e8b58ca4179e9ae73d5ad7dd793d2 100644 --- a/src/plugins/http/inc/httpInt.h +++ b/src/plugins/http/inc/httpInt.h @@ -24,56 +24,31 @@ #include "tutil.h" #include "zlib.h" #include "http.h" -#include "httpCode.h" #include "httpLog.h" #include "httpJson.h" +#include "httpParser.h" #define HTTP_MAX_CMD_SIZE 1024 -#define HTTP_MAX_BUFFER_SIZE 1024*1024 - +#define HTTP_MAX_BUFFER_SIZE 1024*1024*8 #define HTTP_LABEL_SIZE 8 #define HTTP_MAX_EVENTS 10 -#define HTTP_BUFFER_SIZE 1024*65 //65k -#define HTTP_DECOMPRESS_BUF_SIZE 1024*64 -#define HTTP_STEP_SIZE 1024 //http message get process step by step -#define HTTP_MAX_URL 5 //http url stack size +#define HTTP_BUFFER_INIT 4096 +#define HTTP_BUFFER_SIZE 8388608 +#define HTTP_STEP_SIZE 4096 //http message get process step by step #define HTTP_METHOD_SCANNER_SIZE 7 //http method fp size #define HTTP_GC_TARGET_SIZE 512 - -#define HTTP_VERSION_10 0 -#define HTTP_VERSION_11 1 -//#define HTTP_VERSION_12 2 - -#define HTTP_UNCUNKED 0 -#define HTTP_CHUNKED 1 - -#define HTTP_KEEPALIVE_NO_INPUT 0 -#define HTTP_KEEPALIVE_ENABLE 1 -#define HTTP_KEEPALIVE_DISABLE 2 - -#define HTTP_REQTYPE_OTHERS 0 -#define HTTP_REQTYPE_LOGIN 1 -#define HTTP_REQTYPE_HEARTBEAT 2 -#define HTTP_REQTYPE_SINGLE_SQL 3 -#define HTTP_REQTYPE_MULTI_SQL 4 - -#define HTTP_CHECK_BODY_ERROR -1 -#define HTTP_CHECK_BODY_CONTINUE 0 -#define HTTP_CHECK_BODY_SUCCESS 1 - -#define HTTP_READ_DATA_SUCCESS 0 -#define HTTP_READ_DATA_FAILED 1 - #define HTTP_WRITE_RETRY_TIMES 500 #define HTTP_WRITE_WAIT_TIME_MS 5 -#define HTTP_EXPIRED_TIME 60000 -#define HTTP_DELAY_CLOSE_TIME_MS 500 - -#define HTTP_COMPRESS_IDENTITY 0 -#define HTTP_COMPRESS_GZIP 2 - #define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + TSDB_PASSWORD_LEN) +typedef enum HttpReqType { + HTTP_REQTYPE_OTHERS = 0, + HTTP_REQTYPE_LOGIN = 1, + HTTP_REQTYPE_HEARTBEAT = 2, + HTTP_REQTYPE_SINGLE_SQL = 3, + HTTP_REQTYPE_MULTI_SQL = 4 +} HttpReqType; + typedef enum { HTTP_SERVER_INIT, HTTP_SERVER_RUNNING, @@ -82,21 +57,12 @@ typedef enum { } HttpServerStatus; typedef enum { - HTTP_CONTEXT_STATE_READY, - HTTP_CONTEXT_STATE_HANDLING, - HTTP_CONTEXT_STATE_DROPPING, - HTTP_CONTEXT_STATE_CLOSED + HTTP_CONTEXT_STATE_READY, + HTTP_CONTEXT_STATE_HANDLING, + HTTP_CONTEXT_STATE_DROPPING, + HTTP_CONTEXT_STATE_CLOSED } HttpContextState; -struct HttpContext; -struct HttpThread; - -typedef struct { - char id[HTTP_SESSION_ID_LEN]; - int refCount; - void *taos; -} HttpSession; - typedef enum { HTTP_CMD_TYPE_UN_SPECIFIED, HTTP_CMD_TYPE_CREATE_DB, @@ -108,6 +74,15 @@ typedef enum { HTTP_CMD_STATE_NOT_RUN_YET, HTTP_CMD_STATE_RUN_FINISHED } HttpSql typedef enum { HTTP_CMD_RETURN_TYPE_WITH_RETURN, HTTP_CMD_RETURN_TYPE_NO_RETURN } HttpSqlCmdReturnType; +struct HttpContext; +struct HttpThread; + +typedef struct { + char id[HTTP_SESSION_ID_LEN]; + int32_t refCount; + void * taos; +} HttpSession; + typedef struct { // used by single cmd char *nativSql; @@ -157,34 +132,17 @@ typedef struct { void (*setNextCmdFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); } HttpEncodeMethod; -typedef struct { - char *pos; - int32_t len; -} HttpBuf; - -typedef struct { - char buffer[HTTP_BUFFER_SIZE]; - int bufsize; - char *pLast; - char *pCur; - HttpBuf method; - HttpBuf path[HTTP_MAX_URL]; // url: dbname/meter/query - HttpBuf data; // body content - HttpBuf token; // auth token - HttpDecodeMethod *pMethod; -} HttpParser; +typedef enum { + EHTTP_CONTEXT_PROCESS_FAILED = 0x01, + EHTTP_CONTEXT_PARSER_FAILED = 0x02 +} EHTTP_CONTEXT_FAILED_CAUSE; typedef struct HttpContext { int32_t refCount; - int fd; + int32_t fd; uint32_t accessTimes; uint32_t lastAccessTime; int32_t state; - uint8_t httpVersion; - uint8_t httpChunked; - uint8_t httpKeepAlive; // http1.0 and not keep-alive, close connection immediately - uint8_t acceptEncoding; - uint8_t contentEncoding; uint8_t reqType; uint8_t parsed; char ipstr[22]; @@ -194,12 +152,12 @@ typedef struct HttpContext { void * ppContext; HttpSession *session; z_stream gzipStream; - HttpParser parser; + HttpParser *parser; HttpSqlCmd singleCmd; HttpSqlCmds *multiCmds; JsonBuf * jsonBuf; - void * timer; - HttpEncodeMethod * encodeMethod; + HttpEncodeMethod *encodeMethod; + HttpDecodeMethod *decodeMethod; struct HttpThread *pThread; } HttpContext; @@ -208,9 +166,9 @@ typedef struct HttpThread { HttpContext * pHead; pthread_mutex_t threadMutex; bool stop; - int pollFd; - int numOfContexts; - int threadId; + int32_t pollFd; + int32_t numOfContexts; + int32_t threadId; char label[HTTP_LABEL_SIZE]; bool (*processData)(HttpContext *pContext); } HttpThread; @@ -219,9 +177,9 @@ typedef struct HttpServer { char label[HTTP_LABEL_SIZE]; uint32_t serverIp; uint16_t serverPort; - int fd; - int numOfThreads; - int methodScannerLen; + int32_t fd; + int32_t numOfThreads; + int32_t methodScannerLen; int32_t requestNum; int32_t status; pthread_t thread; diff --git a/src/plugins/http/inc/httpJson.h b/src/plugins/http/inc/httpJson.h index 905460c67b14b4d3305f4071ae5370edb0336ff0..ac0a632137256af96de8503775e5a34fc81b1f1c 100644 --- a/src/plugins/http/inc/httpJson.h +++ b/src/plugins/http/inc/httpJson.h @@ -37,65 +37,65 @@ extern char JsonTrueTkn[]; extern char JsonFalseTkn[]; typedef struct { - int size; - int total; - char* lst; - char buf[JSON_BUFFER_SIZE]; - struct HttpContext* pContext; + int32_t size; + int32_t total; + char* lst; + char buf[JSON_BUFFER_SIZE]; + struct HttpContext* pContext; } JsonBuf; // http response -int httpWriteBuf(struct HttpContext* pContext, const char* buf, int sz); -int httpWriteBufNoTrace(struct HttpContext* pContext, const char* buf, int sz); -int httpWriteBufByFd(struct HttpContext* pContext, const char* buf, int sz); +int32_t httpWriteBuf(struct HttpContext* pContext, const char* buf, int32_t sz); +int32_t httpWriteBufNoTrace(struct HttpContext* pContext, const char* buf, int32_t sz); +int32_t httpWriteBufByFd(struct HttpContext* pContext, const char* buf, int32_t sz); // builder callback typedef void (*httpJsonBuilder)(JsonBuf* buf, void* jsnHandle); // buffer -void httpInitJsonBuf(JsonBuf* buf, struct HttpContext* pContext); -void httpWriteJsonBufHead(JsonBuf* buf); -int httpWriteJsonBufBody(JsonBuf* buf, bool isTheLast); -void httpWriteJsonBufEnd(JsonBuf* buf); +void httpInitJsonBuf(JsonBuf* buf, struct HttpContext* pContext); +void httpWriteJsonBufHead(JsonBuf* buf); +int32_t httpWriteJsonBufBody(JsonBuf* buf, bool isTheLast); +void httpWriteJsonBufEnd(JsonBuf* buf); // value -void httpJsonString(JsonBuf* buf, char* sVal, int len); -void httpJsonOriginString(JsonBuf* buf, char* sVal, int len); -void httpJsonStringForTransMean(JsonBuf* buf, char* SVal, int maxLen); +void httpJsonString(JsonBuf* buf, char* sVal, int32_t len); +void httpJsonOriginString(JsonBuf* buf, char* sVal, int32_t len); +void httpJsonStringForTransMean(JsonBuf* buf, char* SVal, int32_t maxLen); void httpJsonInt64(JsonBuf* buf, int64_t num); void httpJsonTimestamp(JsonBuf* buf, int64_t t, bool us); void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, bool us); -void httpJsonInt(JsonBuf* buf, int num); +void httpJsonInt(JsonBuf* buf, int32_t num); void httpJsonFloat(JsonBuf* buf, float num); void httpJsonDouble(JsonBuf* buf, double num); void httpJsonNull(JsonBuf* buf); -void httpJsonBool(JsonBuf* buf, int val); +void httpJsonBool(JsonBuf* buf, int32_t val); // pair -void httpJsonPair(JsonBuf* buf, char* name, int nameLen, char* sVal, int valLen); -void httpJsonPairOriginString(JsonBuf* buf, char* name, int nameLen, char* sVal, int valLen); -void httpJsonPairHead(JsonBuf* buf, char* name, int len); -void httpJsonPairIntVal(JsonBuf* buf, char* name, int nNameLen, int num); -void httpJsonPairInt64Val(JsonBuf* buf, char* name, int nNameLen, int64_t num); -void httpJsonPairBoolVal(JsonBuf* buf, char* name, int nNameLen, int num); -void httpJsonPairFloatVal(JsonBuf* buf, char* name, int nNameLen, float num); -void httpJsonPairDoubleVal(JsonBuf* buf, char* name, int nNameLen, double num); -void httpJsonPairNullVal(JsonBuf* buf, char* name, int nNameLen); +void httpJsonPair(JsonBuf* buf, char* name, int32_t nameLen, char* sVal, int32_t valLen); +void httpJsonPairOriginString(JsonBuf* buf, char* name, int32_t nameLen, char* sVal, int32_t valLen); +void httpJsonPairHead(JsonBuf* buf, char* name, int32_t len); +void httpJsonPairIntVal(JsonBuf* buf, char* name, int32_t nNameLen, int32_t num); +void httpJsonPairInt64Val(JsonBuf* buf, char* name, int32_t nNameLen, int64_t num); +void httpJsonPairBoolVal(JsonBuf* buf, char* name, int32_t nNameLen, int32_t num); +void httpJsonPairFloatVal(JsonBuf* buf, char* name, int32_t nNameLen, float num); +void httpJsonPairDoubleVal(JsonBuf* buf, char* name, int32_t nNameLen, double num); +void httpJsonPairNullVal(JsonBuf* buf, char* name, int32_t nNameLen); // object -void httpJsonPairArray(JsonBuf* buf, char* name, int nLen, httpJsonBuilder builder, void* dsHandle); -void httpJsonPairObject(JsonBuf* buf, char* name, int nLen, httpJsonBuilder builder, void* dsHandle); +void httpJsonPairArray(JsonBuf* buf, char* name, int32_t nLen, httpJsonBuilder builder, void* dsHandle); +void httpJsonPairObject(JsonBuf* buf, char* name, int32_t nLen, httpJsonBuilder builder, void* dsHandle); void httpJsonObject(JsonBuf* buf, httpJsonBuilder fnBuilder, void* dsHandle); void httpJsonArray(JsonBuf* buf, httpJsonBuilder fnBuidler, void* jsonHandle); // print -void httpJsonTestBuf(JsonBuf* buf, int safety); +void httpJsonTestBuf(JsonBuf* buf, int32_t safety); void httpJsonToken(JsonBuf* buf, char c); void httpJsonItemToken(JsonBuf* buf); -void httpJsonPrint(JsonBuf* buf, const char* json, int len); +void httpJsonPrint(JsonBuf* buf, const char* json, int32_t len); // quick -void httpJsonPairStatus(JsonBuf* buf, int code); +void httpJsonPairStatus(JsonBuf* buf, int32_t code); // http json printer JsonBuf* httpMallocJsonBuf(struct HttpContext* pContext); diff --git a/src/plugins/http/inc/httpParser.h b/src/plugins/http/inc/httpParser.h new file mode 100644 index 0000000000000000000000000000000000000000..85ba843716cbfbdf2d87457456464d2b49869457 --- /dev/null +++ b/src/plugins/http/inc/httpParser.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef HTTP_PARSER_H +#define HTTP_PARSER_H +#include "httpGzip.h" + +#define HTTP_MAX_URL 5 // http url stack size + +typedef enum HTTP_PARSER_STATE { + HTTP_PARSER_BEGIN, + HTTP_PARSER_REQUEST_OR_RESPONSE, + HTTP_PARSER_METHOD, + HTTP_PARSER_TARGET, + HTTP_PARSER_HTTP_VERSION, + HTTP_PARSER_SP, + HTTP_PARSER_STATUS_CODE, + HTTP_PARSER_REASON_PHRASE, + HTTP_PARSER_CRLF, + HTTP_PARSER_HEADER, + HTTP_PARSER_HEADER_KEY, + HTTP_PARSER_HEADER_VAL, + HTTP_PARSER_CHUNK_SIZE, + HTTP_PARSER_CHUNK, + HTTP_PARSER_END, + HTTP_PARSER_ERROR, +} HTTP_PARSER_STATE; + +typedef enum HTTP_AUTH_TYPE { + HTTP_INVALID_AUTH, + HTTP_BASIC_AUTH, + HTTP_TAOSD_AUTH +} HTTP_AUTH_TYPE; + +typedef enum HTTP_VERSION { + HTTP_VERSION_10 = 0, + HTTP_VERSION_11 = 1, + HTTP_VERSION_12 = 2, + HTTP_INVALID_VERSION +} HTTP_VERSION; + +typedef enum HTTP_KEEPALIVE { + HTTP_KEEPALIVE_NO_INPUT = 0, + HTTP_KEEPALIVE_ENABLE = 1, + HTTP_KEEPALIVE_DISABLE = 2 +} HTTP_KEEPALIVE; + +typedef struct HttpString { + char * str; + int32_t pos; + int32_t size; +} HttpString; + +typedef struct HttpStatus { + int32_t code; + char * desc; +} HttpStatus; + +typedef struct HttpStack{ + int8_t *stacks; + int32_t pos; + int32_t size; +} HttpStack; + +struct HttpContext; +typedef struct HttpParser { + struct HttpContext *pContext; + ehttp_gzip_t *gzip; + HttpStack stacks; + HttpString str; + HttpString body; + HttpString path[HTTP_MAX_URL]; + char * method; + char * target; + char * version; + char * reasonPhrase; + char * key; + char * val; + char * authContent; + int8_t httpVersion; + int8_t acceptEncodingGzip; + int8_t acceptEncodingChunked; + int8_t contentLengthSpecified; + int8_t contentChunked; + int8_t transferGzip; + int8_t transferChunked; + int8_t keepAlive; + int8_t authType; + int32_t contentLength; + int32_t chunkSize; + int32_t receivedChunkSize; + int32_t receivedSize; + int32_t statusCode; + int8_t inited; + int8_t parsed; + int16_t httpCode; + int32_t parseCode; +} HttpParser; + +void httpInitParser(HttpParser *parser); +HttpParser *httpCreateParser(struct HttpContext *pContext); +void httpClearParser(HttpParser *parser); +void httpDestroyParser(HttpParser *parser); +int32_t httpParseBuf(HttpParser *parser, const char *buf, int32_t len); +char * httpGetStatusDesc(int32_t statusCode); + +#endif diff --git a/src/plugins/http/inc/httpResp.h b/src/plugins/http/inc/httpResp.h index 5eaaa2a0378552d466a7d201981387f018c0614c..a528bcc39e6e23f47ecc9bc2557a3e12d7cf335f 100644 --- a/src/plugins/http/inc/httpResp.h +++ b/src/plugins/http/inc/httpResp.h @@ -32,9 +32,7 @@ enum _httpRespTempl { extern const char *httpRespTemplate[]; -void httpSendErrorResp(HttpContext *pContext, int errNo); -void httpSendErrorRespWithDesc(HttpContext *pContext, int errNo, char *desc); -void httpSendTaosdErrorResp(HttpContext *pContext, int errCode); +void httpSendErrorResp(HttpContext *pContext, int32_t errNo); void httpSendTaosdInvalidSqlErrorResp(HttpContext *pContext, char* errMsg); void httpSendSuccResp(HttpContext *pContext, char *desc); void httpSendOptionResp(HttpContext *pContext, char *desc); diff --git a/src/plugins/http/inc/restHandle.h b/src/plugins/http/inc/httpRestHandle.h similarity index 100% rename from src/plugins/http/inc/restHandle.h rename to src/plugins/http/inc/httpRestHandle.h diff --git a/src/plugins/http/inc/restJson.h b/src/plugins/http/inc/httpRestJson.h similarity index 91% rename from src/plugins/http/inc/restJson.h rename to src/plugins/http/inc/httpRestJson.h index 7cff21d190b389361887582c9422bd9e59da35bc..112e845f369c6ae3f0df76d880f84de5aeff5d8d 100644 --- a/src/plugins/http/inc/restJson.h +++ b/src/plugins/http/inc/httpRestJson.h @@ -43,12 +43,12 @@ #define REST_TIMESTAMP_FMT_TIMESTAMP 1 #define REST_TIMESTAMP_FMT_UTC_STRING 2 -void restBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int affect_rows); +void restBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int32_t affect_rows); void restStartSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result); -bool restBuildSqlTimestampJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows); -bool restBuildSqlLocalTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows); -bool restBuildSqlUtcTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows); +bool restBuildSqlTimestampJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows); +bool restBuildSqlLocalTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows); +bool restBuildSqlUtcTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows); void restStopSqlJson(HttpContext *pContext, HttpSqlCmd *cmd); #endif \ No newline at end of file diff --git a/src/plugins/http/inc/httpServer.h b/src/plugins/http/inc/httpServer.h index 508baa6112a5e9d81e0864637b66f3aa1c21b79d..58ed3545f35e9d832a330c142d398f2316291aa6 100644 --- a/src/plugins/http/inc/httpServer.h +++ b/src/plugins/http/inc/httpServer.h @@ -21,8 +21,7 @@ bool httpInitConnect(); void httpCleanUpConnect(); -void *httpInitServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle); -void httpCleanUpServer(HttpServer *pServer); -int httpReadDataImp(HttpContext *pContext); +void *httpInitServer(char *ip, uint16_t port, char *label, int32_t numOfThreads, void *fp, void *shandle); +void httpCleanUpServer(HttpServer *pServer); #endif diff --git a/src/plugins/http/inc/httpSql.h b/src/plugins/http/inc/httpSql.h index 09f5b142fb63081cc6d4432e1089a446432d056c..db3e3a3b163a249aa675839f30db4d14411eb6d6 100644 --- a/src/plugins/http/inc/httpSql.h +++ b/src/plugins/http/inc/httpSql.h @@ -19,20 +19,20 @@ int32_t httpAddToSqlCmdBuffer(HttpContext *pContext, const char *const format, ...); int32_t httpAddToSqlCmdBufferNoTerminal(HttpContext *pContext, const char *const format, ...); -int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize); +int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int32_t mallocSize); int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext); -bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize); -bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize); -bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int bufferSize); +bool httpMallocMultiCmds(HttpContext *pContext, int32_t cmdSize, int32_t bufferSize); +bool httpReMallocMultiCmdsSize(HttpContext *pContext, int32_t cmdSize); +bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int32_t bufferSize); void httpFreeMultiCmds(HttpContext *pContext); HttpSqlCmd *httpNewSqlCmd(HttpContext *pContext); HttpSqlCmd *httpCurrSqlCmd(HttpContext *pContext); -int httpCurSqlCmdPos(HttpContext *pContext); +int32_t httpCurSqlCmdPos(HttpContext *pContext); -void httpTrimTableName(char *name); -int httpShrinkTableName(HttpContext *pContext, int pos, char *name); -char *httpGetCmdsString(HttpContext *pContext, int pos); +void httpTrimTableName(char *name); +int32_t httpShrinkTableName(HttpContext *pContext, int32_t pos, char *name); +char * httpGetCmdsString(HttpContext *pContext, int32_t pos); #endif diff --git a/src/plugins/http/inc/tgHandle.h b/src/plugins/http/inc/httpTgHandle.h similarity index 100% rename from src/plugins/http/inc/tgHandle.h rename to src/plugins/http/inc/httpTgHandle.h diff --git a/src/plugins/http/inc/tgJson.h b/src/plugins/http/inc/httpTgJson.h similarity index 94% rename from src/plugins/http/inc/tgJson.h rename to src/plugins/http/inc/httpTgJson.h index bf3aa093ae9132bba67ea2dff7b233c7457ccccd..6b7d0681b601fea07aa6d15c8a8a4dbd675b9b34 100644 --- a/src/plugins/http/inc/tgJson.h +++ b/src/plugins/http/inc/httpTgJson.h @@ -24,8 +24,8 @@ void tgInitQueryJson(HttpContext *pContext); void tgCleanQueryJson(HttpContext *pContext); void tgStartQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result); void tgStopQueryJson(HttpContext *pContext, HttpSqlCmd *cmd); -void tgBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int affect_rows); -bool tgCheckFinished(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); -void tgSetNextCmd(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); +void tgBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int32_t affect_rows); +bool tgCheckFinished(struct HttpContext *pContext, HttpSqlCmd *cmd, int32_t code); +void tgSetNextCmd(struct HttpContext *pContext, HttpSqlCmd *cmd, int32_t code); #endif \ No newline at end of file diff --git a/src/plugins/http/inc/httpUtil.h b/src/plugins/http/inc/httpUtil.h index c82f702ebc081da3e1c7821151c38923c605095c..61cd50a77a29ad8b9a2058f4ad569493b18618ac 100644 --- a/src/plugins/http/inc/httpUtil.h +++ b/src/plugins/http/inc/httpUtil.h @@ -17,21 +17,19 @@ #define TDENGINE_HTTP_UTIL_H bool httpCheckUsedbSql(char *sql); -void httpTimeToString(time_t t, char *buf, int buflen); +void httpTimeToString(time_t t, char *buf, int32_t buflen); -bool httpUrlMatch(HttpContext *pContext, int pos, char *cmp); -bool httpParseRequest(HttpContext *pContext); -int httpCheckReadCompleted(HttpContext *pContext); -void httpReadDirtyData(HttpContext *pContext); +bool httpUrlMatch(HttpContext *pContext, int32_t pos, char *cmp); +bool httpParseRequest(HttpContext *pContext); +int32_t httpCheckReadCompleted(HttpContext *pContext); +void httpReadDirtyData(HttpContext *pContext); -int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData); -int httpGzipCompressInit(HttpContext *pContext); -int httpGzipCompress(HttpContext *pContext, char *inSrcData, int32_t inSrcDataLen, +int32_t httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData); +int32_t httpGzipCompressInit(HttpContext *pContext); +int32_t httpGzipCompress(HttpContext *pContext, char *inSrcData, int32_t inSrcDataLen, char *outDestData, int32_t *outDestDataLen, bool isTheLast); // http request parser void httpAddMethod(HttpServer *pServer, HttpDecodeMethod *pMethod); - - #endif diff --git a/src/plugins/http/src/httpAuth.c b/src/plugins/http/src/httpAuth.c index ea7024fad66ea639148d3004189ba1f5feac6c7b..8beef7c042ba6f0194d814753e15387e3d2b4a2b 100644 --- a/src/plugins/http/src/httpAuth.c +++ b/src/plugins/http/src/httpAuth.c @@ -23,85 +23,80 @@ #define KEY_DES_4 4971256377704625728L -bool httpParseBasicAuthToken(HttpContext *pContext, char *token, int len) { +int32_t httpParseBasicAuthToken(HttpContext *pContext, char *token, int32_t len) { token[len] = '\0'; - int outlen = 0; + int32_t outlen = 0; char *base64 = (char *)base64_decode(token, len, &outlen); if (base64 == NULL || outlen == 0) { - httpError("context:%p, fd:%d, ip:%s, basic token:%s parsed error", pContext, pContext->fd, pContext->ipstr, token); + httpError("context:%p, fd:%d, basic token:%s parsed error", pContext, pContext->fd, token); free(base64); - return false; + return -1; } char *user = strstr(base64, ":"); if (user == NULL) { - httpError("context:%p, fd:%d, ip:%s, basic token:%s invalid format", pContext, pContext->fd, pContext->ipstr, - token); + httpError("context:%p, fd:%d, basic token:%s invalid format", pContext, pContext->fd, token); free(base64); - return false; + return -1; } - int user_len = (int)(user - base64); + int32_t user_len = (int32_t)(user - base64); if (user_len < 1 || user_len >= TSDB_USER_LEN) { - httpError("context:%p, fd:%d, ip:%s, basic token:%s parse user error", pContext, pContext->fd, pContext->ipstr, - token); + httpError("context:%p, fd:%d, basic token:%s parse user error", pContext, pContext->fd, token); free(base64); - return false; + return -1; } strncpy(pContext->user, base64, (size_t)user_len); pContext->user[user_len] = 0; char *password = user + 1; - int pass_len = (int)((base64 + outlen) - password); + int32_t pass_len = (int32_t)((base64 + outlen) - password); if (pass_len < 1 || pass_len >= TSDB_PASSWORD_LEN) { - httpError("context:%p, fd:%d, ip:%s, basic token:%s parse password error", pContext, pContext->fd, pContext->ipstr, - token); + httpError("context:%p, fd:%d, basic token:%s parse password error", pContext, pContext->fd, token); free(base64); - return false; + return -1; } strncpy(pContext->pass, password, (size_t)pass_len); pContext->pass[pass_len] = 0; free(base64); - httpDebug("context:%p, fd:%d, ip:%s, basic token parsed success, user:%s", pContext, pContext->fd, pContext->ipstr, - pContext->user); - return true; + httpDebug("context:%p, fd:%d, basic token parsed success, user:%s", pContext, pContext->fd, pContext->user); + return 0; } -bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len) { +int32_t httpParseTaosdAuthToken(HttpContext *pContext, char *token, int32_t len) { token[len] = '\0'; - int outlen = 0; + int32_t outlen = 0; unsigned char *base64 = base64_decode(token, len, &outlen); if (base64 == NULL || outlen == 0) { - httpError("context:%p, fd:%d, ip:%s, taosd token:%s parsed error", pContext, pContext->fd, pContext->ipstr, token); + httpError("context:%p, fd:%d, taosd token:%s parsed error", pContext, pContext->fd, token); if (base64) free(base64); - return false; + return 01; } if (outlen != (TSDB_USER_LEN + TSDB_PASSWORD_LEN)) { - httpError("context:%p, fd:%d, ip:%s, taosd token:%s length error", pContext, pContext->fd, pContext->ipstr, token); + httpError("context:%p, fd:%d, taosd token:%s length error", pContext, pContext->fd, token); free(base64); - return false; + return -1; } char *descrypt = taosDesDecode(KEY_DES_4, (char *)base64, outlen); if (descrypt == NULL) { - httpError("context:%p, fd:%d, ip:%s, taosd token:%s descrypt error", pContext, pContext->fd, pContext->ipstr, - token); + httpError("context:%p, fd:%d, taosd token:%s descrypt error", pContext, pContext->fd, token); free(base64); - return false; + return -1; } else { tstrncpy(pContext->user, descrypt, sizeof(pContext->user)); tstrncpy(pContext->pass, descrypt + TSDB_USER_LEN, sizeof(pContext->pass)); - httpDebug("context:%p, fd:%d, ip:%s, taosd token:%s parsed success, user:%s", pContext, pContext->fd, - pContext->ipstr, token, pContext->user); + httpDebug("context:%p, fd:%d, taosd token:%s parsed success, user:%s", pContext, pContext->fd, token, + pContext->user); free(base64); free(descrypt); - return true; + return 0; } } -bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen) { +int32_t httpGenTaosdAuthToken(HttpContext *pContext, char *token, int32_t maxLen) { char buffer[sizeof(pContext->user) + sizeof(pContext->pass)] = {0}; size_t size = sizeof(pContext->user); tstrncpy(buffer, pContext->user, size); @@ -116,7 +111,7 @@ bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen) { free(encrypt); free(base64); - httpDebug("context:%p, fd:%d, ip:%s, gen taosd token:%s", pContext, pContext->fd, pContext->ipstr, token); + httpDebug("context:%p, fd:%d, generate taosd token:%s", pContext, pContext->fd, token); - return true; + return 0; } diff --git a/src/plugins/http/src/httpCode.c b/src/plugins/http/src/httpCode.c deleted file mode 100644 index 9ec07fd8511a5a240ff4cc7faa7d7b19e2081073..0000000000000000000000000000000000000000 --- a/src/plugins/http/src/httpCode.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#define _DEFAULT_SOURCE - - -char* httpMsg[] = { - "success", // 0 - "http server is not online", // 1 - "http url is not support", // 2 - "http method parse error", // 3 - "http version should be 1.0, 1.1 or 1.2", // 4 - "http head parse error", // 5 - "request size is too big", - "http body size invalid", - "http chunked body parse error", // 8 - "http url parse error", // 9 - "invalid type of Authorization", - "no auth info input", - "no sql input", - "session list was full", - "no enough memory to alloc sqls", - "generate taosd token error", - "db and table can not be null", - "no need to execute use db cmd", - "parse grafana json error", - "size of multi request is 0", // 19 - "request is empty", // 20 - "no enough connections for http", // 21 - - // telegraf - "database name can not be null", // 22 - "database name too long", - "invalid telegraf json fromat", - "metrics size is 0", - "metrics size can not more than 1K", // 26 - "metric name not find", - "metric name type should be string", - "metric name length is 0", - "metric name length too long", - "timestamp not find", // 31 - "timestamp type should be integer", - "timestamp value smaller than 0", - "tags not find", - "tags size is 0", - "tags size too long", // 36 - "tag is null", - "tag name is null", - "tag name length too long", // 39 - "tag value type should be number or string", - "tag value is null", - "table is null", // 42 - "table name length too long", - "fields not find", // 44 - "fields size is 0", - "fields size too long", - "field is null", // 47 - "field name is null", - "field name length too long", // 49 - "field value type should be number or string", - "field value is null", // 51 - "parse basic auth token error", - "parse http auth token error", - "host type should be string", - - // grafana - "query size is 0", // 55 - "query size can not more than 100", - - // opentsdb - "database name can not be null", // 57 - "database name too long", - "invalid opentsdb json fromat", // 59 - "metrics size is 0", - "metrics size can not more than 10K", // 61 - "metric name not find", - "metric name type should be string", - "metric name length is 0", - "metric name length can not more than 22", - "timestamp not find", - "timestamp type should be integer", - "timestamp value smaller than 0", - "tags not find", - "tags size is 0", - "tags size too long", // 71 - "tag is null", - "tag name is null", - "tag name length too long", // 74 - "tag value type should be boolean, number or string", - "tag value is null", - "tag value can not more than 64", // 77 - "value not find", - "value type should be boolean, number or string", - "stable not exist", - -}; diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c index 5ef3c9a66efd35ce37eca96d52022f3a9cceeaa9..c0c0c494de192b09ea3ffd6620ce1c8a655723fa 100644 --- a/src/plugins/http/src/httpContext.c +++ b/src/plugins/http/src/httpContext.c @@ -26,6 +26,10 @@ #include "httpResp.h" #include "httpSql.h" #include "httpSession.h" +#include "httpContext.h" +#include "httpParser.h" + +static void httpDestroyContext(void *data); static void httpRemoveContextFromEpoll(HttpContext *pContext) { HttpThread *pThread = pContext->pThread; @@ -54,6 +58,11 @@ static void httpDestroyContext(void *data) { httpFreeJsonBuf(pContext); httpFreeMultiCmds(pContext); + if (pContext->parser) { + httpDestroyParser(pContext->parser); + pContext->parser = NULL; + } + taosTFree(pContext); } @@ -104,9 +113,9 @@ HttpContext *httpCreateContext(int32_t fd) { if (pContext == NULL) return NULL; pContext->fd = fd; - pContext->httpVersion = HTTP_VERSION_10; pContext->lastAccessTime = taosGetTimestampSec(); pContext->state = HTTP_CONTEXT_STATE_READY; + pContext->parser = httpCreateParser(pContext); uint64_t handleVal = (uint64_t)pContext; HttpContext **ppContext = taosCachePut(tsHttpServer.contextCache, &handleVal, sizeof(int64_t), &pContext, sizeof(int64_t), 3000); @@ -122,27 +131,33 @@ HttpContext *httpCreateContext(int32_t fd) { HttpContext *httpGetContext(void *ptr) { uint64_t handleVal = (uint64_t)ptr; HttpContext **ppContext = taosCacheAcquireByKey(tsHttpServer.contextCache, &handleVal, sizeof(HttpContext *)); + ASSERT(ppContext); + ASSERT(*ppContext); if (ppContext) { HttpContext *pContext = *ppContext; if (pContext) { int32_t refCount = atomic_add_fetch_32(&pContext->refCount, 1); - httpDebug("context:%p, fd:%d, is accquired, data:%p refCount:%d", pContext, pContext->fd, ppContext, refCount); + httpTrace("context:%p, fd:%d, is accquired, data:%p refCount:%d", pContext, pContext->fd, ppContext, refCount); return pContext; } } return NULL; } -void httpReleaseContext(HttpContext *pContext) { +void httpReleaseContext(HttpContext *pContext, bool clearRes) { int32_t refCount = atomic_sub_fetch_32(&pContext->refCount, 1); if (refCount < 0) { httpError("context:%p, is already released, refCount:%d", pContext, refCount); return; } + if (clearRes) { + httpClearParser(pContext->parser); + } + HttpContext **ppContext = pContext->ppContext; - httpDebug("context:%p, is released, data:%p refCount:%d", pContext, ppContext, refCount); + httpTrace("context:%p, is released, data:%p refCount:%d", pContext, ppContext, refCount); if (tsHttpServer.contextCache != NULL) { taosCacheRelease(tsHttpServer.contextCache, (void **)(&ppContext), false); @@ -155,79 +170,66 @@ void httpReleaseContext(HttpContext *pContext) { bool httpInitContext(HttpContext *pContext) { pContext->accessTimes++; pContext->lastAccessTime = taosGetTimestampSec(); - pContext->httpVersion = HTTP_VERSION_10; - pContext->httpKeepAlive = HTTP_KEEPALIVE_NO_INPUT; - pContext->httpChunked = HTTP_UNCUNKED; - pContext->acceptEncoding = HTTP_COMPRESS_IDENTITY; - pContext->contentEncoding = HTTP_COMPRESS_IDENTITY; + pContext->reqType = HTTP_REQTYPE_OTHERS; pContext->encodeMethod = NULL; - pContext->timer = NULL; memset(&pContext->singleCmd, 0, sizeof(HttpSqlCmd)); - HttpParser *pParser = &pContext->parser; - memset(pParser, 0, sizeof(HttpParser)); - pParser->pCur = pParser->pLast = pParser->buffer; - httpDebug("context:%p, fd:%d, ip:%s, accessTimes:%d, parsed:%d", pContext, pContext->fd, pContext->ipstr, - pContext->accessTimes, pContext->parsed); + httpTrace("context:%p, fd:%d, parsed:%d", pContext, pContext->fd, pContext->parsed); return true; } void httpCloseContextByApp(HttpContext *pContext) { + HttpParser *parser = pContext->parser; pContext->parsed = false; bool keepAlive = true; - if (pContext->httpVersion == HTTP_VERSION_10 && pContext->httpKeepAlive != HTTP_KEEPALIVE_ENABLE) { + if (parser->httpVersion == HTTP_VERSION_10 && parser->keepAlive != HTTP_KEEPALIVE_ENABLE) { keepAlive = false; - } else if (pContext->httpVersion != HTTP_VERSION_10 && pContext->httpKeepAlive == HTTP_KEEPALIVE_DISABLE) { + } else if (parser->httpVersion != HTTP_VERSION_10 && parser->keepAlive == HTTP_KEEPALIVE_DISABLE) { keepAlive = false; } else { } if (keepAlive) { if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_READY)) { - httpDebug("context:%p, fd:%d, ip:%s, last state:handling, keepAlive:true, reuse context", pContext, pContext->fd, - pContext->ipstr); + httpTrace("context:%p, fd:%d, last state:handling, keepAlive:true, reuse context", pContext, pContext->fd); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_CLOSED)) { httpRemoveContextFromEpoll(pContext); - httpDebug("context:%p, fd:%d, ip:%s, last state:dropping, keepAlive:true, close connect", pContext, pContext->fd, - pContext->ipstr); + httpTrace("context:%p, fd:%d, ast state:dropping, keepAlive:true, close connect", pContext, pContext->fd); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) { - httpDebug("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, reuse context", pContext, pContext->fd, - pContext->ipstr); + httpTrace("context:%p, fd:%d, last state:ready, keepAlive:true, reuse context", pContext, pContext->fd); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) { httpRemoveContextFromEpoll(pContext); - httpDebug("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, close connect", pContext, pContext->fd, - pContext->ipstr); + httpTrace("context:%p, fd:%d, last state:ready, keepAlive:true, close connect", pContext, pContext->fd); } else { httpRemoveContextFromEpoll(pContext); - httpError("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:true, close connect", pContext, pContext->fd, - pContext->ipstr, httpContextStateStr(pContext->state), pContext->state); + httpError("context:%p, fd:%d, last state:%s:%d, keepAlive:true, close connect", pContext, pContext->fd, + httpContextStateStr(pContext->state), pContext->state); } } else { httpRemoveContextFromEpoll(pContext); - httpDebug("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:false, close context", pContext, pContext->fd, - pContext->ipstr, httpContextStateStr(pContext->state), pContext->state); + httpTrace("context:%p, fd:%d, ilast state:%s:%d, keepAlive:false, close context", pContext, pContext->fd, + httpContextStateStr(pContext->state), pContext->state); } - httpReleaseContext(pContext); + httpReleaseContext(pContext, true); } void httpCloseContextByServer(HttpContext *pContext) { if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_DROPPING)) { - httpDebug("context:%p, fd:%d, ip:%s, epoll finished, still used by app", pContext, pContext->fd, pContext->ipstr); + httpTrace("context:%p, fd:%d, epoll finished, still used by app", pContext, pContext->fd); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_DROPPING)) { - httpDebug("context:%p, fd:%d, ip:%s, epoll already finished, wait app finished", pContext, pContext->fd, pContext->ipstr); + httpTrace("context:%p, fd:%d, epoll already finished, wait app finished", pContext, pContext->fd); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_CLOSED)) { - httpDebug("context:%p, fd:%d, ip:%s, epoll finished, close connect", pContext, pContext->fd, pContext->ipstr); + httpTrace("context:%p, fd:%d, epoll finished, close connect", pContext, pContext->fd); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) { - httpDebug("context:%p, fd:%d, ip:%s, epoll finished, will be closed soon", pContext, pContext->fd, pContext->ipstr); + httpTrace("context:%p, fd:%d, epoll finished, will be closed soon", pContext, pContext->fd); } else { - httpError("context:%p, fd:%d, ip:%s, unknown state:%d", pContext, pContext->fd, pContext->ipstr, pContext->state); + httpError("context:%p, fd:%d, unknown state:%d", pContext, pContext->fd, pContext->state); } pContext->parsed = false; httpRemoveContextFromEpoll(pContext); - httpReleaseContext(pContext); } diff --git a/src/plugins/http/src/gcHandle.c b/src/plugins/http/src/httpGcHandle.c similarity index 72% rename from src/plugins/http/src/gcHandle.c rename to src/plugins/http/src/httpGcHandle.c index 72b73b4bad65069e2b3dfb0fdcd633675a50be04..5d4cb0c6809d063107cb37ccaac1200f2c87ee9d 100644 --- a/src/plugins/http/src/gcHandle.c +++ b/src/plugins/http/src/httpGcHandle.c @@ -15,11 +15,12 @@ #define _DEFAULT_SOURCE #include "os.h" +#include "taosdef.h" +#include "taoserror.h" #include "cJSON.h" #include "httpLog.h" -#include "gcHandle.h" -#include "gcJson.h" -#include "taosdef.h" +#include "httpGcHandle.h" +#include "httpGcJson.h" static HttpDecodeMethod gcDecodeMethod = {"grafana", gcProcessRequest}; static HttpEncodeMethod gcHeartBeatMethod = { @@ -47,28 +48,27 @@ static HttpEncodeMethod gcQueryMethod = { void gcInitHandle(HttpServer* pServer) { httpAddMethod(pServer, &gcDecodeMethod); } bool gcGetUserFromUrl(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - if (pParser->path[GC_USER_URL_POS].len >= TSDB_USER_LEN || pParser->path[GC_USER_URL_POS].len <= 0) { + HttpParser* pParser = pContext->parser; + if (pParser->path[GC_USER_URL_POS].pos >= TSDB_USER_LEN || pParser->path[GC_USER_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->user, pParser->path[GC_USER_URL_POS].pos, TSDB_USER_LEN); + tstrncpy(pContext->user, pParser->path[GC_USER_URL_POS].str, TSDB_USER_LEN); return true; } bool gcGetPassFromUrl(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - if (pParser->path[GC_PASS_URL_POS].len >= TSDB_PASSWORD_LEN || pParser->path[GC_PASS_URL_POS].len <= 0) { + HttpParser* pParser = pContext->parser; + if (pParser->path[GC_PASS_URL_POS].pos >= TSDB_PASSWORD_LEN || pParser->path[GC_PASS_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->pass, pParser->path[GC_PASS_URL_POS].pos, TSDB_PASSWORD_LEN); + tstrncpy(pContext->pass, pParser->path[GC_PASS_URL_POS].str, TSDB_PASSWORD_LEN); return true; } bool gcProcessLoginRequest(HttpContext* pContext) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process grafana login msg", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpDebug("context:%p, fd:%d, user:%s, process grafana login msg", pContext, pContext->fd, pContext->user); pContext->reqType = HTTP_REQTYPE_LOGIN; return true; } @@ -143,65 +143,61 @@ bool gcProcessLoginRequest(HttpContext* pContext) { //}] bool gcProcessQueryRequest(HttpContext* pContext) { - httpDebug("context:%p, fd:%d, ip:%s, process grafana query msg", pContext, pContext->fd, pContext->ipstr); + httpDebug("context:%p, fd:%d, process grafana query msg", pContext, pContext->fd); - HttpParser* pParser = &pContext->parser; - char* filter = pParser->data.pos; + char* filter = pContext->parser->body.str; if (filter == NULL) { - httpSendErrorResp(pContext, HTTP_NO_MSG_INPUT); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_MSG_INPUT); return false; } cJSON* root = cJSON_Parse(filter); if (root == NULL) { - httpSendErrorResp(pContext, HTTP_PARSE_GC_REQ_ERROR); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_GC_REQ_PARSE_ERROR); return false; } - int size = cJSON_GetArraySize(root); + int32_t size = cJSON_GetArraySize(root); if (size <= 0) { - httpSendErrorResp(pContext, HTTP_GC_QUERY_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_GC_QUERY_NULL); cJSON_Delete(root); return false; } if (size > 100) { - httpSendErrorResp(pContext, HTTP_GC_QUERY_SIZE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_GC_QUERY_SIZE); cJSON_Delete(root); return false; } if (!httpMallocMultiCmds(pContext, size, HTTP_BUFFER_SIZE)) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); cJSON_Delete(root); return false; } - for (int i = 0; i < size; ++i) { + for (int32_t i = 0; i < size; ++i) { cJSON* query = cJSON_GetArrayItem(root, i); if (query == NULL) continue; cJSON* refId = cJSON_GetObjectItem(query, "refId"); if (refId == NULL || refId->valuestring == NULL || strlen(refId->valuestring) == 0) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, refId is null", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpDebug("context:%p, fd:%d, user:%s, refId is null", pContext, pContext->fd, pContext->user); continue; } - int refIdBuffer = httpAddToSqlCmdBuffer(pContext, refId->valuestring); + int32_t refIdBuffer = httpAddToSqlCmdBuffer(pContext, refId->valuestring); if (refIdBuffer == -1) { - httpWarn("context:%p, fd:%d, ip:%s, user:%s, refId buffer is full", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpWarn("context:%p, fd:%d, user:%s, refId buffer is full", pContext, pContext->fd, pContext->user); break; } cJSON* alias = cJSON_GetObjectItem(query, "alias"); - int aliasBuffer = -1; + int32_t aliasBuffer = -1; if (!(alias == NULL || alias->valuestring == NULL || strlen(alias->valuestring) == 0)) { aliasBuffer = httpAddToSqlCmdBuffer(pContext, alias->valuestring); if (aliasBuffer == -1) { - httpWarn("context:%p, fd:%d, ip:%s, user:%s, alias buffer is full", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpWarn("context:%p, fd:%d, user:%s, alias buffer is full", pContext, pContext->fd, pContext->user); break; } } @@ -211,21 +207,19 @@ bool gcProcessQueryRequest(HttpContext* pContext) { cJSON* sql = cJSON_GetObjectItem(query, "sql"); if (sql == NULL || sql->valuestring == NULL || strlen(sql->valuestring) == 0) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, sql is null", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpDebug("context:%p, fd:%d, user:%s, sql is null", pContext, pContext->fd, pContext->user); continue; } - int sqlBuffer = httpAddToSqlCmdBuffer(pContext, sql->valuestring); + int32_t sqlBuffer = httpAddToSqlCmdBuffer(pContext, sql->valuestring); if (sqlBuffer == -1) { - httpWarn("context:%p, fd:%d, ip:%s, user:%s, sql buffer is full", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpWarn("context:%p, fd:%d, user:%s, sql buffer is full", pContext, pContext->fd, pContext->user); break; } HttpSqlCmd* cmd = httpNewSqlCmd(pContext); if (cmd == NULL) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); cJSON_Delete(root); return false; } @@ -237,8 +231,8 @@ bool gcProcessQueryRequest(HttpContext* pContext) { cmd->timestamp = httpAddToSqlCmdBufferWithSize(pContext, HTTP_GC_TARGET_SIZE + 1); // hack way if (cmd->timestamp == -1) { - httpWarn("context:%p, fd:%d, ip:%s, user:%s, cant't malloc target size, sql buffer is full", - pContext, pContext->fd, pContext->ipstr, pContext->user); + httpWarn("context:%p, fd:%d, user:%s, cant't malloc target size, sql buffer is full", pContext, pContext->fd, + pContext->user); break; } } @@ -251,7 +245,7 @@ bool gcProcessQueryRequest(HttpContext* pContext) { } bool gcProcessHeartbeatRequest(HttpContext* pContext) { - httpDebug("context:%p, fd:%d, ip:%s, process grafana heartbeat msg", pContext, pContext->fd, pContext->ipstr); + httpDebug("context:%p, fd:%d, process grafana heartbeat msg", pContext, pContext->fd); pContext->reqType = HTTP_REQTYPE_HEARTBEAT; pContext->encodeMethod = &gcHeartBeatMethod; return true; @@ -267,7 +261,7 @@ bool gcProcessRequest(struct HttpContext* pContext) { } if (strlen(pContext->user) == 0 || strlen(pContext->pass) == 0) { - httpSendErrorResp(pContext, HTTP_PARSE_USR_ERROR); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_AUTH_INFO); return false; } diff --git a/src/plugins/http/src/gcJson.c b/src/plugins/http/src/httpGcJson.c similarity index 89% rename from src/plugins/http/src/gcJson.c rename to src/plugins/http/src/httpGcJson.c index 94d53db6ef0200265aa67710794c60f1fec0cfac..a291641dc376c6d581a137403a1ac623ce9dd5ec 100644 --- a/src/plugins/http/src/gcJson.c +++ b/src/plugins/http/src/httpGcJson.c @@ -15,8 +15,8 @@ #define _DEFAULT_SOURCE #include "os.h" -#include "gcHandle.h" -#include "gcJson.h" +#include "httpGcHandle.h" +#include "httpGcJson.h" #include "httpJson.h" #include "httpResp.h" @@ -54,8 +54,8 @@ void gcWriteTargetStartJson(JsonBuf *jsonBuf, char *refId, char *target) { httpJsonToken(jsonBuf, JsonObjStt); // target section - httpJsonPair(jsonBuf, "refId", 5, refId, (int)strlen(refId)); - httpJsonPair(jsonBuf, "target", 6, target, (int)strlen(target)); + httpJsonPair(jsonBuf, "refId", 5, refId, (int32_t)strlen(refId)); + httpJsonPair(jsonBuf, "target", 6, target, (int32_t)strlen(target)); // data begin httpJsonPairHead(jsonBuf, "datapoints", 10); @@ -82,25 +82,25 @@ void gcStopQueryJson(HttpContext *pContext, HttpSqlCmd *cmd) { } } -bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows) { +bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows) { JsonBuf *jsonBuf = httpMallocJsonBuf(pContext); if (jsonBuf == NULL) return false; - int num_fields = taos_num_fields(result); + int32_t num_fields = taos_num_fields(result); TAOS_FIELD *fields = taos_fetch_fields(result); if (num_fields == 0) { return false; } - int precision = taos_result_precision(result); + int32_t precision = taos_result_precision(result); // such as select count(*) from sys.cpu // such as select count(*) from sys.cpu group by ipaddr // such as select count(*) from sys.cpu interval(1d) // such as select count(*) from sys.cpu interval(1d) group by ipaddr // such as select count(*) count(*) from sys.cpu group by ipaddr interval(1d) - int dataFields = -1; - int groupFields = -1; + int32_t dataFields = -1; + int32_t groupFields = -1; bool hasTimestamp = fields[0].type == TSDB_DATA_TYPE_TIMESTAMP; if (hasTimestamp) { dataFields = 1; @@ -119,7 +119,7 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, } cmd->numOfRows += numOfRows; - for (int k = 0; k < numOfRows; ++k) { + for (int32_t k = 0; k < numOfRows; ++k) { TAOS_ROW row = taos_fetch_row(result); if (row == NULL) { cmd->numOfRows--; @@ -130,9 +130,9 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, // for group by if (groupFields != -1) { char target[HTTP_GC_TARGET_SIZE] = {0}; - int len; + int32_t len; len = snprintf(target,HTTP_GC_TARGET_SIZE,"%s{",aliasBuffer); - for (int i = dataFields + 1; i= 0; i--) { + for (int32_t i = dataFields; i >= 0; i--) { httpJsonItemToken(jsonBuf); if (row[i] == NULL) { httpJsonOriginString(jsonBuf, "null", 4); @@ -253,13 +253,13 @@ void gcSendHeartBeatResp(HttpContext *pContext, HttpSqlCmd *cmd) { httpInitJsonBuf(jsonBuf, pContext); httpJsonToken(jsonBuf, JsonObjStt); - httpJsonPair(jsonBuf, "message", (int)strlen("message"), desc, (int)strlen(desc)); + httpJsonPair(jsonBuf, "message", (int32_t)strlen("message"), desc, (int32_t)strlen(desc)); httpJsonToken(jsonBuf, JsonObjEnd); char head[1024]; - int hLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_GRAFANA], httpVersionStr[pContext->httpVersion], - httpKeepAliveStr[pContext->httpKeepAlive], (jsonBuf->lst - jsonBuf->buf)); + int32_t hLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_GRAFANA], httpVersionStr[pContext->parser->httpVersion], + httpKeepAliveStr[pContext->parser->keepAlive], (jsonBuf->lst - jsonBuf->buf)); httpWriteBuf(pContext, head, hLen); - httpWriteBuf(pContext, jsonBuf->buf, (int)(jsonBuf->lst - jsonBuf->buf)); + httpWriteBuf(pContext, jsonBuf->buf, (int32_t)(jsonBuf->lst - jsonBuf->buf)); } diff --git a/src/plugins/http/src/httpGzip.c b/src/plugins/http/src/httpGzip.c new file mode 100644 index 0000000000000000000000000000000000000000..54f900c7551d225c4c1c0b72bfa661969af14afa --- /dev/null +++ b/src/plugins/http/src/httpGzip.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "zlib.h" +#include "httpGzip.h" + +typedef enum { + EHTTP_GZIP_INITING, + EHTTP_GZIP_READY, + EHTTP_GZIP_CLOSED, +} EHTTP_GZIP_STATE; + +struct ehttp_gzip_s { + ehttp_gzip_conf_t conf; + ehttp_gzip_callbacks_t callbacks; + void *arg; + z_stream *gzip; + gz_header *header; + char *chunk; + + int32_t state; +}; + +static void dummy_on_data(ehttp_gzip_t *gzip, void *arg, const char *buf, int32_t len) { +} + +static void ehttp_gzip_cleanup(ehttp_gzip_t *gzip) { + switch(gzip->state) { + case EHTTP_GZIP_READY: { + inflateEnd(gzip->gzip); + } break; + default: break; + } + if (gzip->gzip) { + free(gzip->gzip); + gzip->gzip = NULL; + } + if (gzip->header) { + free(gzip->header); + gzip->header = NULL; + } + if (gzip->chunk) { + free(gzip->chunk); + gzip->chunk = NULL; + } + gzip->state = EHTTP_GZIP_CLOSED; +} + +ehttp_gzip_t* ehttp_gzip_create_decompressor(ehttp_gzip_conf_t conf, ehttp_gzip_callbacks_t callbacks, void *arg) { + ehttp_gzip_t *gzip = (ehttp_gzip_t*)calloc(1, sizeof(*gzip)); + if (!gzip) return NULL; + + do { + gzip->conf = conf; + gzip->callbacks = callbacks; + gzip->arg = arg; + if (gzip->callbacks.on_data == NULL) gzip->callbacks.on_data = dummy_on_data; + gzip->gzip = (z_stream*)calloc(1, sizeof(*gzip->gzip)); + if (gzip->conf.get_header) { + gzip->header = (gz_header*)calloc(1, sizeof(*gzip->header)); + } + if (gzip->conf.chunk_size<=0) gzip->conf.chunk_size = EHTTP_GZIP_CHUNK_SIZE_DEFAULT; + gzip->chunk = (char*)malloc(gzip->conf.chunk_size); + if (!gzip->gzip || (gzip->conf.get_header && !gzip->header) || !gzip->chunk) break; + gzip->gzip->zalloc = Z_NULL; + gzip->gzip->zfree = Z_NULL; + gzip->gzip->opaque = Z_NULL; + + // 863 windowBits can also be greater than 15 for optional gzip decoding. Add + // 864 32 to windowBits to enable zlib and gzip decoding with automatic header + // 865 detection, or add 16 to decode only the gzip format (the zlib format will + // 866 return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + // 867 CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + // 868 below), inflate() will not automatically decode concatenated gzip streams. + // 869 inflate() will return Z_STREAM_END at the end of the gzip stream. The state + // 870 would need to be reset to continue decoding a subsequent gzip stream. + int32_t ret = inflateInit2(gzip->gzip, 32); // 32/16? 32/16 + MAX_WBITS + if (ret != Z_OK) break; + if (gzip->header) { + ret = inflateGetHeader(gzip->gzip, gzip->header); + } + if (ret != Z_OK) break; + + gzip->gzip->next_out = (z_const Bytef*)gzip->chunk; + gzip->gzip->avail_out = gzip->conf.chunk_size; + gzip->state = EHTTP_GZIP_READY; + return gzip; + } while (0); + + ehttp_gzip_destroy(gzip); + return NULL; +} + +ehttp_gzip_t* ehttp_gzip_create_compressor(ehttp_gzip_conf_t conf, ehttp_gzip_callbacks_t callbacks, void *arg); + +void ehttp_gzip_destroy(ehttp_gzip_t *gzip) { + ehttp_gzip_cleanup(gzip); + + free(gzip); +} + +int32_t ehttp_gzip_write(ehttp_gzip_t *gzip, const char *buf, int32_t len) { + if (gzip->state != EHTTP_GZIP_READY) return -1; + if (len <= 0) return 0; + + gzip->gzip->next_in = (z_const Bytef*)buf; + gzip->gzip->avail_in = len; + + while (gzip->gzip->avail_in) { + int32_t ret; + if (gzip->header) { + ret = inflate(gzip->gzip, Z_BLOCK); + } else { + ret = inflate(gzip->gzip, Z_SYNC_FLUSH); + } + if (ret != Z_OK && ret != Z_STREAM_END) return -1; + + if (gzip->gzip->avail_out>0) { + if (ret!=Z_STREAM_END) continue; + } + + int32_t len = gzip->gzip->next_out - (z_const Bytef*)gzip->chunk; + + gzip->gzip->next_out[0] = '\0'; + gzip->callbacks.on_data(gzip, gzip->arg, gzip->chunk, len); + gzip->gzip->next_out = (z_const Bytef*)gzip->chunk; + gzip->gzip->avail_out = gzip->conf.chunk_size; + } + + return 0; +} + +int32_t ehttp_gzip_finish(ehttp_gzip_t *gzip) { + if (gzip->state != EHTTP_GZIP_READY) return -1; + + gzip->gzip->next_in = NULL; + gzip->gzip->avail_in = 0; + + int32_t ret; + ret = inflate(gzip->gzip, Z_FINISH); + + if (ret != Z_STREAM_END) return -1; + + int32_t len = gzip->gzip->next_out - (z_const Bytef*)gzip->chunk; + + gzip->gzip->next_out[0] = '\0'; + gzip->callbacks.on_data(gzip, gzip->arg, gzip->chunk, len); + gzip->gzip->next_out = NULL; + gzip->gzip->avail_out = 0; + + return 0; +} + diff --git a/src/plugins/http/src/httpHandle.c b/src/plugins/http/src/httpHandle.c index 407d19b307e522c5c6a51b1c199d77425831481a..b50217cfc4bffe0835de8a744a78997426db6d3b 100644 --- a/src/plugins/http/src/httpHandle.c +++ b/src/plugins/http/src/httpHandle.c @@ -15,382 +15,33 @@ #define _DEFAULT_SOURCE #include "os.h" -#include "taos.h" -#include "tglobal.h" -#include "tsocket.h" -#include "ttimer.h" #include "httpInt.h" #include "httpResp.h" -#include "httpAuth.h" -#include "httpServer.h" #include "httpContext.h" #include "httpHandle.h" -void httpToLowerUrl(char* url) { - /*ignore case */ - while (*url) { - if (*url >= 'A' && *url <= 'Z') { - *url = *url | 0x20; - } - url++; - } -} - -bool httpUrlMatch(HttpContext* pContext, int pos, char* cmp) { - HttpParser* pParser = &pContext->parser; - - if (pos < 0 || pos >= HTTP_MAX_URL) { - return false; - } - - if (pParser->path[pos].len <= 0) { - return false; - } - - if (strcmp(pParser->path[pos].pos, cmp) != 0) { - return false; - } - - return true; -} - -// /account/db/meter HTTP/1.1\r\nHost -bool httpParseURL(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - char* pSeek; - char* pEnd = strchr(pParser->pLast, ' '); - if (pEnd == NULL) { - httpSendErrorResp(pContext, HTTP_UNSUPPORT_URL); - return false; - } - - if (*pParser->pLast != '/') { - httpSendErrorResp(pContext, HTTP_UNSUPPORT_URL); - return false; - } - pParser->pLast++; - - for (int i = 0; i < HTTP_MAX_URL; i++) { - pSeek = strchr(pParser->pLast, '/'); - if (pSeek == NULL) { - break; - } - pParser->path[i].pos = pParser->pLast; - if (pSeek <= pEnd) { - pParser->path[i].len = (int16_t)(pSeek - pParser->pLast); - pParser->path[i].pos[pParser->path[i].len] = 0; - httpToLowerUrl(pParser->path[i].pos); - pParser->pLast = pSeek + 1; - } else { - pParser->path[i].len = (int16_t)(pEnd - pParser->pLast); - pParser->path[i].pos[pParser->path[i].len] = 0; - httpToLowerUrl(pParser->path[i].pos); - pParser->pLast = pEnd + 1; - break; - } - } - pParser->pLast = pEnd + 1; - - if (pParser->path[0].len == 0) { - httpSendErrorResp(pContext, HTTP_UNSUPPORT_URL); - return false; - } - - return true; -} - -bool httpParseHttpVersion(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - char* pEnd = strchr(pParser->pLast, '1'); - if (pEnd == NULL) { - httpError("context:%p, fd:%d, ip:%s, can't find http version at position:%s", pContext, pContext->fd, - pContext->ipstr, pParser->pLast); - httpSendErrorResp(pContext, HTTP_PARSE_HTTP_VERSION_ERROR); - return false; - } - - if (*(pEnd + 1) != '.') { - httpError("context:%p, fd:%d, ip:%s, can't find http version at position:%s", pContext, pContext->fd, - pContext->ipstr, pParser->pLast); - httpSendErrorResp(pContext, HTTP_PARSE_HTTP_VERSION_ERROR); - return false; - } - - if (*(pEnd + 2) == '0') - pContext->httpVersion = HTTP_VERSION_10; - else if (*(pEnd + 2) == '1') - pContext->httpVersion = HTTP_VERSION_11; - else if (*(pEnd + 2) == '2') - pContext->httpVersion = HTTP_VERSION_11; - else - pContext->httpVersion = HTTP_VERSION_10; - - httpDebug("context:%p, fd:%d, ip:%s, httpVersion:1.%d", pContext, pContext->fd, pContext->ipstr, - pContext->httpVersion); - return true; -} - -bool httpGetNextLine(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - while (pParser->buffer + pParser->bufsize - pParser->pCur++ > 0) { - if (*(pParser->pCur) == '\n' && *(pParser->pCur - 1) == '\r') { - // cut the string - *pParser->pCur = 0; - return true; - } - } - - httpSendErrorResp(pContext, HTTP_PARSE_HEAD_ERROR); - - return false; -} - -bool httpGetHttpMethod(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - - char* pSeek = strchr(pParser->pLast, ' '); - if (pSeek == NULL) { - httpSendErrorResp(pContext, HTTP_PARSE_HTTP_METHOD_ERROR); - return false; - } - pParser->method.pos = pParser->pLast; - pParser->method.len = (int16_t)(pSeek - pParser->pLast); - pParser->method.pos[pParser->method.len] = 0; - pParser->pLast = pSeek + 1; - - httpTrace("context:%p, fd:%d, ip:%s, httpMethod:%s", pContext, pContext->fd, pContext->ipstr, pParser->method.pos); - return true; -} - -bool httpGetDecodeMethod(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - - HttpServer* pServer = &tsHttpServer; - int methodLen = pServer->methodScannerLen; - for (int i = 0; i < methodLen; i++) { - HttpDecodeMethod* method = pServer->methodScanner[i]; - if (strcmp(method->module, pParser->path[0].pos) != 0) { - continue; - } - pParser->pMethod = method; - return true; - } - - httpError("context:%p, fd:%d, ip:%s, error:the url is not support, method:%s, path:%s", - pContext, pContext->fd, pContext->ipstr, pParser->method.pos, pParser->path[0].pos); - httpSendErrorResp(pContext, HTTP_UNSUPPORT_URL); - - return false; -} - -bool httpParseHead(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - if (strncasecmp(pParser->pLast, "Content-Length: ", 16) == 0) { - pParser->data.len = (int32_t)atoi(pParser->pLast + 16); - httpTrace("context:%p, fd:%d, ip:%s, Content-Length:%d", pContext, pContext->fd, pContext->ipstr, - pParser->data.len); - } else if (strncasecmp(pParser->pLast, "Accept-Encoding: ", 17) == 0) { - if (tsHttpEnableCompress && strstr(pParser->pLast + 17, "gzip") != NULL) { - pContext->acceptEncoding = HTTP_COMPRESS_GZIP; - httpTrace("context:%p, fd:%d, ip:%s, Accept-Encoding:gzip", pContext, pContext->fd, pContext->ipstr); - } else { - pContext->acceptEncoding = HTTP_COMPRESS_IDENTITY; - httpTrace("context:%p, fd:%d, ip:%s, Accept-Encoding:identity", pContext, pContext->fd, pContext->ipstr); - } - } else if (strncasecmp(pParser->pLast, "Content-Encoding: ", 18) == 0) { - if (strstr(pParser->pLast + 18, "gzip") != NULL) { - pContext->contentEncoding = HTTP_COMPRESS_GZIP; - httpTrace("context:%p, fd:%d, ip:%s, Content-Encoding:gzip", pContext, pContext->fd, pContext->ipstr); - } else { - pContext->contentEncoding = HTTP_COMPRESS_IDENTITY; - httpTrace("context:%p, fd:%d, ip:%s, Content-Encoding:identity", pContext, pContext->fd, pContext->ipstr); - } - } else if (strncasecmp(pParser->pLast, "Connection: ", 12) == 0) { - if (strncasecmp(pParser->pLast + 12, "Keep-Alive", 10) == 0) { - pContext->httpKeepAlive = HTTP_KEEPALIVE_ENABLE; - } else { - pContext->httpKeepAlive = HTTP_KEEPALIVE_DISABLE; - } - httpTrace("context:%p, fd:%d, ip:%s, keepAlive:%d", pContext, pContext->fd, pContext->ipstr, - pContext->httpKeepAlive); - } else if (strncasecmp(pParser->pLast, "Transfer-Encoding: ", 19) == 0) { - if (strncasecmp(pParser->pLast + 19, "chunked", 7) == 0) { - pContext->httpChunked = HTTP_CHUNKED; - } - } else if (strncasecmp(pParser->pLast, "Authorization: ", 15) == 0) { - if (strncasecmp(pParser->pLast + 15, "Basic ", 6) == 0) { - pParser->token.pos = pParser->pLast + 21; - pParser->token.len = (int16_t)(pParser->pCur - pParser->token.pos - 1); - bool parsed = httpParseBasicAuthToken(pContext, pParser->token.pos, pParser->token.len); - if (!parsed) { - httpSendErrorResp(pContext, HTTP_INVALID_BASIC_AUTH_TOKEN); - return false; - } - } else if (strncasecmp(pParser->pLast + 15, "Taosd ", 6) == 0) { - pParser->token.pos = pParser->pLast + 21; - pParser->token.len = (int16_t)(pParser->pCur - pParser->token.pos - 1); - bool parsed = httpParseTaosdAuthToken(pContext, pParser->token.pos, pParser->token.len); - if (!parsed) { - httpSendErrorResp(pContext, HTTP_INVALID_TAOSD_AUTH_TOKEN); - return false; - } - } else { - httpSendErrorResp(pContext, HTTP_INVALID_AUTH_TOKEN); - return false; - } - } else { - } - - return true; -} - -bool httpParseChunkedBody(HttpContext* pContext, HttpParser* pParser, bool test) { - char* pEnd = pParser->buffer + pParser->bufsize; - char* pRet = pParser->data.pos; - char* pSize = pParser->data.pos; - size_t size = strtoul(pSize, NULL, 16); - if (size <= 0) return false; - - while (size > 0) { - char* pData = strstr(pSize, "\r\n"); - if (pData == NULL || pData >= pEnd) return false; - pData += 2; - - pSize = strstr(pData, "\r\n"); - if (pSize == NULL || pSize >= pEnd) return false; - if ((size_t)(pSize - pData) != size) return false; - pSize += 2; - - if (!test) { - memmove(pRet, pData, size); - pRet += size; - } - - size = strtoul(pSize, NULL, 16); - } - - if (!test) { - *pRet = '\0'; - } - - return true; -} - -int httpReadChunkedBody(HttpContext* pContext, HttpParser* pParser) { - bool parsedOk = httpParseChunkedBody(pContext, pParser, true); - if (parsedOk) { - httpParseChunkedBody(pContext, pParser, false); - return HTTP_CHECK_BODY_SUCCESS; - } else { - httpTrace("context:%p, fd:%d, ip:%s, chunked body not finished, continue read", pContext, pContext->fd, pContext->ipstr); - if (httpReadDataImp(pContext) != HTTP_READ_DATA_SUCCESS) { - httpError("context:%p, fd:%d, ip:%s, read chunked request error", pContext, pContext->fd, pContext->ipstr); - return HTTP_CHECK_BODY_ERROR; - } else { - return HTTP_CHECK_BODY_CONTINUE; - } - } -} - -int httpReadUnChunkedBody(HttpContext* pContext, HttpParser* pParser) { - int dataReadLen = pParser->bufsize - (int)(pParser->data.pos - pParser->buffer); - if (dataReadLen > pParser->data.len) { - httpError("context:%p, fd:%d, ip:%s, un-chunked body length invalid, read size:%d dataReadLen:%d > pContext->data.len:%d", - pContext, pContext->fd, pContext->ipstr, pContext->parser.bufsize, dataReadLen, pParser->data.len); - return HTTP_CHECK_BODY_ERROR; - } else if (dataReadLen < pParser->data.len) { - httpTrace("context:%p, fd:%d, ip:%s, un-chunked body not finished, read size:%d dataReadLen:%d < pContext->data.len:%d, continue read", - pContext, pContext->fd, pContext->ipstr, pContext->parser.bufsize, dataReadLen, pParser->data.len); - return HTTP_CHECK_BODY_CONTINUE; - } else { - return HTTP_CHECK_BODY_SUCCESS; - } -} - -bool httpParseRequest(HttpContext* pContext) { - HttpParser *pParser = &pContext->parser; - if (pContext->parsed) { - return true; - } - - httpTraceL("context:%p, fd:%d, ip:%s, thread:%s, numOfContexts:%d, read size:%d, raw data:\n%s", pContext, - pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->pThread->numOfContexts, - pContext->parser.bufsize, pContext->parser.buffer); - - if (!httpGetHttpMethod(pContext)) { - return false; - } - - if (!httpParseURL(pContext)) { - return false; - } - - if (!httpParseHttpVersion(pContext)) { - return false; - } - - if (!httpGetDecodeMethod(pContext)) { - return false; - } - - do { - if (!httpGetNextLine(pContext)) { - return false; - } - - // Empty line, end of the HTTP HEAD - if (pParser->pCur - pParser->pLast == 1) { - pParser->data.pos = ++pParser->pCur; - break; - } - - if (!httpParseHead(pContext)) { - return false; - } - - pParser->pLast = ++pParser->pCur; - } while (1); - - httpDebug("context:%p, fd:%d, ip:%s, parse http head ok", pContext, pContext->fd, pContext->ipstr); - - pContext->parsed = true; - return true; -} - -int httpCheckReadCompleted(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - - if (pContext->httpChunked == HTTP_UNCUNKED) { - return httpReadUnChunkedBody(pContext, pParser); - } else { - return httpReadChunkedBody(pContext, pParser); - } -} - bool httpDecodeRequest(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - if (pParser->pMethod->decodeFp == NULL) { + if (pContext->decodeMethod->decodeFp == NULL) { return false; } - return (*pParser->pMethod->decodeFp)(pContext); + return (*pContext->decodeMethod->decodeFp)(pContext); } /** * Process the request from http pServer */ bool httpProcessData(HttpContext* pContext) { - if (!httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_HANDLING)) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s not in ready state, stop process request", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state)); + httpTrace("context:%p, fd:%d, state:%s not in ready state, stop process request", pContext, pContext->fd, + httpContextStateStr(pContext->state)); httpCloseContextByApp(pContext); return false; } // handle Cross-domain request - if (strcmp(pContext->parser.method.pos, "OPTIONS") == 0) { - httpDebug("context:%p, fd:%d, ip:%s, process options request", pContext, pContext->fd, pContext->ipstr); + if (strcmp(pContext->parser->method, "OPTIONS") == 0) { + httpTrace("context:%p, fd:%d, process options request", pContext, pContext->fd); httpSendOptionResp(pContext, "process options request success"); } else { if (!httpDecodeRequest(pContext)) { diff --git a/src/plugins/http/src/httpJson.c b/src/plugins/http/src/httpJson.c index 4748f03b662479db9f5dcdbc64b5294e9d6a9094..e9a8947df2650a590bc7c7cd0f12c5d6c8a4dd20 100644 --- a/src/plugins/http/src/httpJson.c +++ b/src/plugins/http/src/httpJson.c @@ -17,9 +17,9 @@ #include "os.h" #include "taosmsg.h" #include "taoserror.h" +#include "tglobal.h" #include "http.h" #include "httpLog.h" -#include "httpCode.h" #include "httpJson.h" #include "httpResp.h" #include "httpUtil.h" @@ -38,28 +38,26 @@ char JsonNulTkn[] = "null"; char JsonTrueTkn[] = "true"; char JsonFalseTkn[] = "false"; -int httpWriteBufByFd(struct HttpContext* pContext, const char* buf, int sz) { - int len; - int countWait = 0; - int writeLen = 0; +int32_t httpWriteBufByFd(struct HttpContext* pContext, const char* buf, int32_t sz) { + int32_t len; + int32_t countWait = 0; + int32_t writeLen = 0; do { if (pContext->fd > 2){ - len = (int)taosSend(pContext->fd, buf + writeLen, (size_t)(sz - writeLen), MSG_NOSIGNAL); + len = (int32_t)taosSend(pContext->fd, buf + writeLen, (size_t)(sz - writeLen), MSG_NOSIGNAL); } else { return sz; } if (len < 0) { - httpDebug("context:%p, fd:%d, ip:%s, socket write errno:%d, times:%d", - pContext, pContext->fd, pContext->ipstr, errno, countWait); + httpDebug("context:%p, fd:%d, socket write errno:%d, times:%d", pContext, pContext->fd, errno, countWait); if (++countWait > HTTP_WRITE_RETRY_TIMES) break; taosMsleep(HTTP_WRITE_WAIT_TIME_MS); continue; } else if (len == 0) { - httpDebug("context:%p, fd:%d, ip:%s, socket write errno:%d, connect already closed", - pContext, pContext->fd, pContext->ipstr, errno); + httpDebug("context:%p, fd:%d, socket write errno:%d, connect already closed", pContext, pContext->fd, errno); break; } else { countWait = 0; @@ -70,36 +68,35 @@ int httpWriteBufByFd(struct HttpContext* pContext, const char* buf, int sz) { return writeLen; } -int httpWriteBuf(struct HttpContext *pContext, const char *buf, int sz) { - int writeSz = httpWriteBufByFd(pContext, buf, sz); +int32_t httpWriteBuf(struct HttpContext* pContext, const char* buf, int32_t sz) { + int32_t writeSz = httpWriteBufByFd(pContext, buf, sz); if (writeSz != sz) { - httpError("context:%p, fd:%d, ip:%s, dataSize:%d, writeSize:%d, failed to send response:\n%s", - pContext, pContext->fd, pContext->ipstr, sz, writeSz, buf); + httpError("context:%p, fd:%d, dataSize:%d, writeSize:%d, failed to send response:\n%s", pContext, pContext->fd, sz, + writeSz, buf); } else { - httpTrace("context:%p, fd:%d, ip:%s, dataSize:%d, writeSize:%d, response:\n%s", pContext, pContext->fd, - pContext->ipstr, sz, writeSz, buf); + httpTrace("context:%p, fd:%d, dataSize:%d, writeSize:%d, response:\n%s", pContext, pContext->fd, sz, writeSz, buf); } return writeSz; } -int httpWriteBufNoTrace(struct HttpContext *pContext, const char *buf, int sz) { - int writeSz = httpWriteBufByFd(pContext, buf, sz); +int32_t httpWriteBufNoTrace(struct HttpContext *pContext, const char *buf, int32_t sz) { + int32_t writeSz = httpWriteBufByFd(pContext, buf, sz); if (writeSz != sz) { - httpError("context:%p, fd:%d, ip:%s, dataSize:%d, writeSize:%d, failed to send response", - pContext, pContext->fd, pContext->ipstr, sz, writeSz); + httpError("context:%p, fd:%d, dataSize:%d, writeSize:%d, failed to send response", pContext, pContext->fd, sz, + writeSz); } return writeSz; } -int httpWriteJsonBufBody(JsonBuf* buf, bool isTheLast) { - int remain = 0; +int32_t httpWriteJsonBufBody(JsonBuf* buf, bool isTheLast) { + int32_t remain = 0; char sLen[24]; uint64_t srcLen = (uint64_t) (buf->lst - buf->buf); if (buf->pContext->fd <= 0) { - httpTrace("context:%p, fd:%d, ip:%s, write json body error", buf->pContext, buf->pContext->fd, buf->pContext->ipstr); + httpTrace("context:%p, fd:%d, write json body error", buf->pContext, buf->pContext->fd); buf->pContext->fd = -1; } @@ -111,44 +108,44 @@ int httpWriteJsonBufBody(JsonBuf* buf, bool isTheLast) { * The remote endpoint then decodes the stream by concatenating the chunks and uncompressing the result. */ - if (buf->pContext->acceptEncoding == HTTP_COMPRESS_IDENTITY) { + if (buf->pContext->parser->acceptEncodingGzip == 0 || !tsHttpEnableCompress) { if (buf->lst == buf->buf) { - httpTrace("context:%p, fd:%d, ip:%s, no data need dump", buf->pContext, buf->pContext->fd, buf->pContext->ipstr); + httpTrace("context:%p, fd:%d, no data need dump", buf->pContext, buf->pContext->fd); return 0; // there is no data to dump. } else { - int len = sprintf(sLen, "%lx\r\n", srcLen); - httpTrace("context:%p, fd:%d, ip:%s, write body, chunkSize:%" PRIu64 ", response:\n%s", - buf->pContext, buf->pContext->fd, buf->pContext->ipstr, srcLen, buf->buf); + int32_t len = sprintf(sLen, "%lx\r\n", srcLen); + httpTrace("context:%p, fd:%d, write body, chunkSize:%" PRIu64 ", response:\n%s", buf->pContext, buf->pContext->fd, + srcLen, buf->buf); httpWriteBufNoTrace(buf->pContext, sLen, len); - remain = httpWriteBufNoTrace(buf->pContext, buf->buf, (int) srcLen); + remain = httpWriteBufNoTrace(buf->pContext, buf->buf, (int32_t)srcLen); } } else { char compressBuf[JSON_BUFFER_SIZE] = {0}; int32_t compressBufLen = JSON_BUFFER_SIZE; - int ret = httpGzipCompress(buf->pContext, buf->buf, srcLen, compressBuf, &compressBufLen, isTheLast); + int32_t ret = httpGzipCompress(buf->pContext, buf->buf, srcLen, compressBuf, &compressBufLen, isTheLast); if (ret == 0) { if (compressBufLen > 0) { - int len = sprintf(sLen, "%x\r\n", compressBufLen); - httpTrace("context:%p, fd:%d, ip:%s, write body, chunkSize:%" PRIu64 ", compressSize:%d, last:%d, response:\n%s", - buf->pContext, buf->pContext->fd, buf->pContext->ipstr, srcLen, compressBufLen, isTheLast, buf->buf); + int32_t len = sprintf(sLen, "%x\r\n", compressBufLen); + httpTrace("context:%p, fd:%d, write body, chunkSize:%" PRIu64 ", compressSize:%d, last:%d, response:\n%s", + buf->pContext, buf->pContext->fd, srcLen, compressBufLen, isTheLast, buf->buf); httpWriteBufNoTrace(buf->pContext, sLen, len); - remain = httpWriteBufNoTrace(buf->pContext, (const char *) compressBuf, (int) compressBufLen); + remain = httpWriteBufNoTrace(buf->pContext, (const char*)compressBuf, compressBufLen); } else { - httpTrace("context:%p, fd:%d, ip:%s, last:%d, compress already dumped, response:\n%s", - buf->pContext, buf->pContext->fd, buf->pContext->ipstr, isTheLast, buf->buf); + httpTrace("context:%p, fd:%d, last:%d, compress already dumped, response:\n%s", buf->pContext, + buf->pContext->fd, isTheLast, buf->buf); return 0; // there is no data to dump. } } else { - httpError("context:%p, fd:%d, ip:%s, failed to compress data, chunkSize:%" PRIu64 ", last:%d, error:%d, response:\n%s", - buf->pContext, buf->pContext->fd, buf->pContext->ipstr, srcLen, isTheLast, ret, buf->buf); + httpError("context:%p, fd:%d, failed to compress data, chunkSize:%" PRIu64 ", last:%d, error:%d, response:\n%s", + buf->pContext, buf->pContext->fd, srcLen, isTheLast, ret, buf->buf); return 0; } } httpWriteBufNoTrace(buf->pContext, "\r\n", 2); - buf->total += (int) (buf->lst - buf->buf); + buf->total += (int32_t)(buf->lst - buf->buf); buf->lst = buf->buf; - memset(buf->buf, 0, (size_t) buf->size); + memset(buf->buf, 0, (size_t)buf->size); return remain; } @@ -158,14 +155,14 @@ void httpWriteJsonBufHead(JsonBuf* buf) { } char msg[1024] = {0}; - int len = -1; + int32_t len = -1; - if (buf->pContext->acceptEncoding == HTTP_COMPRESS_IDENTITY) { - len = sprintf(msg, httpRespTemplate[HTTP_RESPONSE_CHUNKED_UN_COMPRESS], httpVersionStr[buf->pContext->httpVersion], - httpKeepAliveStr[buf->pContext->httpKeepAlive]); + if (buf->pContext->parser->acceptEncodingGzip == 0 || !tsHttpEnableCompress) { + len = sprintf(msg, httpRespTemplate[HTTP_RESPONSE_CHUNKED_UN_COMPRESS], httpVersionStr[buf->pContext->parser->httpVersion], + httpKeepAliveStr[buf->pContext->parser->keepAlive]); } else { - len = sprintf(msg, httpRespTemplate[HTTP_RESPONSE_CHUNKED_COMPRESS], httpVersionStr[buf->pContext->httpVersion], - httpKeepAliveStr[buf->pContext->httpKeepAlive]); + len = sprintf(msg, httpRespTemplate[HTTP_RESPONSE_CHUNKED_COMPRESS], httpVersionStr[buf->pContext->parser->httpVersion], + httpKeepAliveStr[buf->pContext->parser->keepAlive]); } httpWriteBuf(buf->pContext, (const char*)msg, len); @@ -173,7 +170,7 @@ void httpWriteJsonBufHead(JsonBuf* buf) { void httpWriteJsonBufEnd(JsonBuf* buf) { if (buf->pContext->fd <= 0) { - httpTrace("context:%p, fd:%d, ip:%s, json buf fd is 0", buf->pContext, buf->pContext->fd, buf->pContext->ipstr); + httpTrace("context:%p, fd:%d, json buf fd is 0", buf->pContext, buf->pContext->fd); buf->pContext->fd = -1; } @@ -188,11 +185,11 @@ void httpInitJsonBuf(JsonBuf* buf, struct HttpContext* pContext) { buf->pContext = pContext; memset(buf->lst, 0, JSON_BUFFER_SIZE); - if (pContext->acceptEncoding == HTTP_COMPRESS_GZIP) { + if (pContext->parser->acceptEncodingGzip == 1 && tsHttpEnableCompress) { httpGzipCompressInit(buf->pContext); } - httpDebug("context:%p, fd:%d, ip:%s, json buffer initialized", buf->pContext, buf->pContext->fd, buf->pContext->ipstr); + httpTrace("context:%p, fd:%d, json buffer initialized", buf->pContext, buf->pContext->fd); } void httpJsonItemToken(JsonBuf* buf) { @@ -203,19 +200,19 @@ void httpJsonItemToken(JsonBuf* buf) { if (buf->lst > buf->buf) httpJsonToken(buf, JsonItmTkn); } -void httpJsonString(JsonBuf* buf, char* sVal, int len) { +void httpJsonString(JsonBuf* buf, char* sVal, int32_t len) { httpJsonItemToken(buf); httpJsonToken(buf, JsonStrStt); httpJsonPrint(buf, sVal, len); httpJsonToken(buf, JsonStrEnd); } -void httpJsonOriginString(JsonBuf* buf, char* sVal, int len) { +void httpJsonOriginString(JsonBuf* buf, char* sVal, int32_t len) { httpJsonItemToken(buf); httpJsonPrint(buf, sVal, len); } -void httpJsonStringForTransMean(JsonBuf* buf, char* sVal, int maxLen) { +void httpJsonStringForTransMean(JsonBuf* buf, char* sVal, int32_t maxLen) { httpJsonItemToken(buf); httpJsonToken(buf, JsonStrStt); @@ -224,18 +221,18 @@ void httpJsonStringForTransMean(JsonBuf* buf, char* sVal, int maxLen) { char* lastPos = sVal; char* curPos = sVal; - for (int i = 0; i < maxLen; ++i) { + for (int32_t i = 0; i < maxLen; ++i) { if (*curPos == 0) { break; } if (*curPos == '\"') { - httpJsonPrint(buf, lastPos, (int)(curPos - lastPos)); + httpJsonPrint(buf, lastPos, (int32_t)(curPos - lastPos)); curPos++; lastPos = curPos; httpJsonPrint(buf, "\\\"", 2); } else if (*curPos == '\\') { - httpJsonPrint(buf, lastPos, (int)(curPos - lastPos)); + httpJsonPrint(buf, lastPos, (int32_t)(curPos - lastPos)); curPos++; lastPos = curPos; httpJsonPrint(buf, "\\\\", 2); @@ -245,7 +242,7 @@ void httpJsonStringForTransMean(JsonBuf* buf, char* sVal, int maxLen) { } if (*lastPos) { - httpJsonPrint(buf, lastPos, (int)(curPos - lastPos)); + httpJsonPrint(buf, lastPos, (int32_t)(curPos - lastPos)); } } @@ -261,14 +258,14 @@ void httpJsonInt64(JsonBuf* buf, int64_t num) { void httpJsonTimestamp(JsonBuf* buf, int64_t t, bool us) { char ts[35] = {0}; struct tm *ptm; - int precision = 1000; + int32_t precision = 1000; if (us) { precision = 1000000; } time_t tt = t / precision; ptm = localtime(&tt); - int length = (int) strftime(ts, 35, "%Y-%m-%d %H:%M:%S", ptm); + int32_t length = (int32_t) strftime(ts, 35, "%Y-%m-%d %H:%M:%S", ptm); if (us) { length += snprintf(ts + length, 8, ".%06ld", t % precision); } else { @@ -281,25 +278,25 @@ void httpJsonTimestamp(JsonBuf* buf, int64_t t, bool us) { void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, bool us) { char ts[40] = {0}; struct tm *ptm; - int precision = 1000; + int32_t precision = 1000; if (us) { precision = 1000000; } time_t tt = t / precision; ptm = localtime(&tt); - int length = (int) strftime(ts, 40, "%Y-%m-%dT%H:%M:%S", ptm); + int32_t length = (int32_t)strftime(ts, 40, "%Y-%m-%dT%H:%M:%S", ptm); if (us) { length += snprintf(ts + length, 8, ".%06ld", t % precision); } else { length += snprintf(ts + length, 5, ".%03ld", t % precision); } - length += (int) strftime(ts + length, 40 - length, "%z", ptm); + length += (int32_t)strftime(ts + length, 40 - length, "%z", ptm); httpJsonString(buf, ts, length); } -void httpJsonInt(JsonBuf* buf, int num) { +void httpJsonInt(JsonBuf* buf, int32_t num) { httpJsonItemToken(buf); httpJsonTestBuf(buf, MAX_NUM_STR_SZ); buf->lst += snprintf(buf->lst, MAX_NUM_STR_SZ, "%d", num); @@ -331,65 +328,65 @@ void httpJsonDouble(JsonBuf* buf, double num) { void httpJsonNull(JsonBuf* buf) { httpJsonString(buf, "null", 4); } -void httpJsonBool(JsonBuf* buf, int val) { +void httpJsonBool(JsonBuf* buf, int32_t val) { if (val == 0) httpJsonPrint(buf, JsonFalseTkn, sizeof(JsonFalseTkn)); else httpJsonPrint(buf, JsonTrueTkn, sizeof(JsonTrueTkn)); } -void httpJsonPairHead(JsonBuf* buf, char* name, int len) { +void httpJsonPairHead(JsonBuf* buf, char* name, int32_t len) { httpJsonItemToken(buf); httpJsonString(buf, name, len); httpJsonToken(buf, JsonPairTkn); } -void httpJsonPair(JsonBuf* buf, char* name, int nameLen, char* sVal, int valLen) { +void httpJsonPair(JsonBuf* buf, char* name, int32_t nameLen, char* sVal, int32_t valLen) { httpJsonPairHead(buf, name, nameLen); httpJsonString(buf, sVal, valLen); } -void httpJsonPairOriginString(JsonBuf* buf, char* name, int nameLen, char* sVal, int valLen) { +void httpJsonPairOriginString(JsonBuf* buf, char* name, int32_t nameLen, char* sVal, int32_t valLen) { httpJsonPairHead(buf, name, nameLen); httpJsonOriginString(buf, sVal, valLen); } -void httpJsonPairIntVal(JsonBuf* buf, char* name, int nNameLen, int num) { +void httpJsonPairIntVal(JsonBuf* buf, char* name, int32_t nNameLen, int32_t num) { httpJsonPairHead(buf, name, nNameLen); httpJsonInt(buf, num); } -void httpJsonPairInt64Val(JsonBuf* buf, char* name, int nNameLen, int64_t num) { +void httpJsonPairInt64Val(JsonBuf* buf, char* name, int32_t nNameLen, int64_t num) { httpJsonPairHead(buf, name, nNameLen); httpJsonInt64(buf, num); } -void httpJsonPairBoolVal(JsonBuf* buf, char* name, int nNameLen, int num) { +void httpJsonPairBoolVal(JsonBuf* buf, char* name, int32_t nNameLen, int32_t num) { httpJsonPairHead(buf, name, nNameLen); httpJsonBool(buf, num); } -void httpJsonPairFloatVal(JsonBuf* buf, char* name, int nNameLen, float num) { +void httpJsonPairFloatVal(JsonBuf* buf, char* name, int32_t nNameLen, float num) { httpJsonPairHead(buf, name, nNameLen); httpJsonFloat(buf, num); } -void httpJsonPairDoubleVal(JsonBuf* buf, char* name, int nNameLen, double num) { +void httpJsonPairDoubleVal(JsonBuf* buf, char* name, int32_t nNameLen, double num) { httpJsonPairHead(buf, name, nNameLen); httpJsonDouble(buf, num); } -void httpJsonPairNullVal(JsonBuf* buf, char* name, int nNameLen) { +void httpJsonPairNullVal(JsonBuf* buf, char* name, int32_t nNameLen) { httpJsonPairHead(buf, name, nNameLen); httpJsonNull(buf); } -void httpJsonPairArray(JsonBuf* buf, char* name, int len, httpJsonBuilder fnBuilder, void* dsHandle) { +void httpJsonPairArray(JsonBuf* buf, char* name, int32_t len, httpJsonBuilder fnBuilder, void* dsHandle) { httpJsonPairHead(buf, name, len); httpJsonArray(buf, fnBuilder, dsHandle); } -void httpJsonPairObject(JsonBuf* buf, char* name, int len, httpJsonBuilder fnBuilder, void* dsHandle) { +void httpJsonPairObject(JsonBuf* buf, char* name, int32_t len, httpJsonBuilder fnBuilder, void* dsHandle) { httpJsonPairHead(buf, name, len); httpJsonObject(buf, fnBuilder, dsHandle); } @@ -408,7 +405,7 @@ void httpJsonArray(JsonBuf* buf, httpJsonBuilder fnBuilder, void* jsonHandle) { httpJsonToken(buf, JsonArrEnd); } -void httpJsonTestBuf(JsonBuf* buf, int safety) { +void httpJsonTestBuf(JsonBuf* buf, int32_t safety) { if ((buf->lst - buf->buf + safety) < buf->size) return; // buf->slot = *buf->lst; httpWriteJsonBufBody(buf, false); @@ -419,7 +416,7 @@ void httpJsonToken(JsonBuf* buf, char c) { *buf->lst++ = c; } -void httpJsonPrint(JsonBuf* buf, const char* json, int len) { +void httpJsonPrint(JsonBuf* buf, const char* json, int32_t len) { if (len == 0 || len >= JSON_BUFFER_SIZE) { return; } @@ -435,7 +432,7 @@ void httpJsonPrint(JsonBuf* buf, const char* json, int len) { buf->lst += len; } -void httpJsonPairStatus(JsonBuf* buf, int code) { +void httpJsonPairStatus(JsonBuf* buf, int32_t code) { if (code == 0) { httpJsonPair(buf, "status", 6, "succ", 4); } else { @@ -448,7 +445,7 @@ void httpJsonPairStatus(JsonBuf* buf, int code) { } else if (code == TSDB_CODE_MND_INVALID_TABLE_NAME) { httpJsonPair(buf, "desc", 4, "failed to create table", 22); } else { - httpJsonPair(buf, "desc", 4, (char*)tstrerror(code), (int)strlen(tstrerror(code))); + httpJsonPair(buf, "desc", 4, (char*)tstrerror(code), (int32_t)strlen(tstrerror(code))); } } } diff --git a/src/plugins/http/src/httpParser.c b/src/plugins/http/src/httpParser.c new file mode 100644 index 0000000000000000000000000000000000000000..0c3204687a3fa92fb71d8da2551bb4c10a7a4097 --- /dev/null +++ b/src/plugins/http/src/httpParser.c @@ -0,0 +1,1134 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "taoserror.h" +#include "httpLog.h" +#include "httpContext.h" +#include "httpParser.h" +#include "httpGzip.h" +#include "httpAuth.h" + +static void httpOnData(ehttp_gzip_t *gzip, void *arg, const char *buf, int32_t len); + +static HttpStatus httpStatusCodes[] = { + {100, "Continue"}, + {101, "Switching Protocol"}, + {102, "Processing (WebDAV)"}, + {103, "Early Hints"}, + {200, "OK"}, + {201, "Created"}, + {202, "Accepted"}, + {203, "Non-Authoritative Information"}, + {204, "No Content"}, + {205, "Reset Content"}, + {206, "Partial Content"}, + {207, "Multi-Status (WebDAV)"}, + {208, "Already Reported (WebDAV)"}, + {226, "IM Used (HTTP Delta encoding)"}, + {300, "Multiple Choice"}, + {301, "Moved Permanently"}, + {302, "Found"}, + {303, "See Other"}, + {304, "Not Modified"}, + {305, "Use Proxy"}, + {306, "unused"}, + {307, "Temporary Redirect"}, + {308, "Permanent Redirect"}, + {400, "Bad Request"}, + {401, "Unauthorized"}, + {402, "Payment Required"}, + {403, "Forbidden"}, + {404, "Not Found"}, + {405, "Method Not Allowed"}, + {406, "Not Acceptable"}, + {407, "Proxy Authentication Required"}, + {408, "Request Timeout"}, + {409, "Conflict"}, + {410, "Gone"}, + {411, "Length Required"}, + {412, "Precondition Failed"}, + {413, "Payload Too Large"}, + {414, "URI Too Long"}, + {415, "Unsupported Media Type"}, + {416, "Range Not Satisfiable"}, + {417, "Expectation Failed"}, + {418, "I'm a teapot"}, + {421, "Misdirected Request"}, + {422, "Unprocessable Entity (WebDAV)"}, + {423, "Locked (WebDAV)"}, + {424, "Failed Dependency (WebDAV)"}, + {425, "Too Early"}, + {426, "Upgrade Required"}, + {428, "Precondition Required"}, + {429, "Too Many Requests"}, + {431, "Request Header Fields Too Large"}, + {451, "Unavailable For Legal Reasons"}, + {500, "Internal Server Error"}, + {501, "Not Implemented"}, + {502, "Bad Gateway"}, + {503, "Service Unavailable"}, + {504, "Gateway Timeout"}, + {505, "HTTP Version Not Supported"}, + {506, "Variant Also Negotiates"}, + {507, "Insufficient Storage"}, + {508, "Loop Detected (WebDAV)"}, + {510, "Not Extended"}, + {511, "Network Authentication Required"}, + {0, NULL} +}; + +char *httpGetStatusDesc(int32_t statusCode) { + HttpStatus *p = httpStatusCodes; + while (p->code != 0) { + if (p->code == statusCode) return p->desc; + ++p; + } + return "Unknow status code"; +} + +static void httpCleanupString(HttpString *str) { + free(str->str); + str->str = NULL; + str->pos = 0; + str->size = 0; +} + +static int32_t httpAppendString(HttpString *str, const char *s, int32_t len) { + if (str->size == 0) { + str->pos = 0; + str->size = 64; + str->str = malloc(str->size); + } else if (str->pos + len + 1 >= str->size) { + str->size += len; + str->size *= 4; + str->str = realloc(str->str, str->size); + } else { + } + + if (str->str == NULL) return -1; + + memcpy(str->str + str->pos, s, len); + str->pos += len; + str->str[str->pos] = 0; + return 0; +} + +static void httpClearString(HttpString *str) { + if (str->str) { + str->str[0] = '\0'; + str->pos = 0; + } +} + +static int32_t httpOnError(HttpParser *parser, int32_t httpCode, int32_t parseCode) { + HttpContext *pContext = parser->pContext; + if (httpCode != 0) parser->httpCode = httpCode; + if (parseCode != 0) parser->parseCode = parseCode; + + httpError("context:%p, fd:%d, parse failed, httpCode:%d parseCode:%d reason:%s", pContext, pContext->fd, httpCode, + parseCode & 0XFFFF, tstrerror(parseCode)); + return 0; +} + +static int32_t httpOnRequestLine(HttpParser *pParser, char *method, char *target, char *version) { + HttpContext *pContext = pParser->pContext; + httpDebug("context:%p, fd:%d, method:%s target:%s version:%s", pContext, pContext->fd, method, target, version); + + // parse url + char *pStart = target + 1; + for (int32_t i = 0; i < HTTP_MAX_URL; i++) { + char *pSeek = strchr(pStart, '/'); + if (pSeek == NULL) { + httpAppendString(pParser->path + i, pStart, strlen(pStart)); + break; + } else { + httpAppendString(pParser->path + i, pStart, (int32_t)(pSeek - pStart)); + } + pStart = pSeek + 1; + } + + // parse decode method + for (int32_t i = 0; i < tsHttpServer.methodScannerLen; i++) { + HttpDecodeMethod *method = tsHttpServer.methodScanner[i]; + if (strcmp(method->module, pParser->path[0].str) == 0) { + pContext->decodeMethod = method; + break; + } + } + + if (pContext->decodeMethod != NULL) { + httpTrace("context:%p, fd:%d, decode method is %s", pContext, pContext->fd, pContext->decodeMethod->module); + } else { + httpError("context:%p, fd:%d, the url is not support, target:%s", pContext, pContext->fd, target); + httpOnError(pParser, 0, TSDB_CODE_HTTP_UNSUPPORT_URL); + return -1; + } + + // parse version + if (pParser->httpVersion < HTTP_VERSION_10 || pParser->httpVersion > HTTP_VERSION_12) { + httpError("context:%p, fd:%d, unsupport httpVersion %d", pContext, pContext->fd, pParser->httpVersion); + httpOnError(pParser, 0, TSDB_CODE_HTTP_INVALID_VERSION); + } else { + httpTrace("context:%p, fd:%d, httpVersion:1.%d", pContext, pContext->fd, pParser->httpVersion); + } + + return 0; +} + +static int32_t httpOnStatusLine(HttpParser *pParser, int32_t code, const char *reason) { + HttpContext *pContext = pParser->pContext; + httpError("context:%p, fd:%d, status line, code:%d reason:%s", pContext, pContext->fd, code, reason); + return 0; +} + +static int32_t httpOnParseHeaderField(HttpParser *parser, const char *key, const char *val) { + HttpContext *pContext = parser->pContext; + httpTrace("context:%p, fd:%d, key:%s val:%s", pContext, pContext->fd, key, val); + + if (0 == strcasecmp(key, "Content-Length")) { + int32_t len = 0; + int32_t bytes = 0; + int32_t n = sscanf(val, "%d%n", &len, &bytes); + if (n == 1 && bytes == strlen(val)) { + parser->contentLength = len; + parser->chunkSize = len; + parser->contentLengthSpecified = 1; + httpTrace("context:%p, fd:%d, contentLength:%d chunkSize:%d contentLengthSpecified:%d", pContext, pContext->fd, + parser->contentLength, parser->chunkSize, parser->contentLengthSpecified); + return 0; + } else { + httpError("context:%p, fd:%d, failed to parser %s:%s", pContext, pContext->fd, key, val); + httpOnError(parser, 0, TSDB_CODE_HTTP_INVALID_CONTENT_LENGTH); + return -1; + } + } + + else if (0 == strcasecmp(key, "Accept-Encoding")) { + if (strstr(val, "gzip")) { + parser->acceptEncodingGzip = 1; + httpTrace("context:%p, fd:%d, acceptEncodingGzip:%d", pContext, pContext->fd, parser->acceptEncodingGzip); + } + if (strstr(val, "chunked")) { + parser->acceptEncodingChunked = 1; + httpTrace("context:%p, fd:%d, acceptEncodingChunked:%d", pContext, pContext->fd, parser->acceptEncodingChunked); + } + return 0; + } + + else if (strncasecmp(key, "Connection: ", 12) == 0) { + if (strncasecmp(val, "Keep-Alive", 10) == 0) { + parser->keepAlive = HTTP_KEEPALIVE_ENABLE; + } else { + parser->keepAlive = HTTP_KEEPALIVE_DISABLE; + } + httpTrace("context:%p, fd:%d, keepAlive:%d", pContext, pContext->fd, pContext->parser->keepAlive); + } + +#if 0 + else if (0 == strcasecmp(key, "Content-Encoding")) { + if (0 == strcmp(val, "gzip")) { + parser->contentChunked = 1; + httpTrace("context:%p, fd:%d, contentChunked:%d", pContext, pContext->fd, parser->contentChunked); + } + return 0; + } + #endif + + else if (0 == strcasecmp(key, "Transfer-Encoding") || 0 == strcasecmp(key, "Content-Encoding")) { + if (strstr(val, "gzip")) { + parser->transferGzip = 1; + ehttp_gzip_conf_t conf = {0}; + ehttp_gzip_callbacks_t callbacks = {0}; + + callbacks.on_data = httpOnData; + + parser->gzip = ehttp_gzip_create_decompressor(conf, callbacks, parser); + + if (!parser->gzip) { + httpError("context:%p, fd:%d, failed to create gzip decompressor", pContext, pContext->fd); + httpOnError(parser, 0, TSDB_CODE_HTTP_CREATE_GZIP_FAILED); + return -1; + } + } + if (strstr(val, "chunked")) { + parser->transferChunked = 1; + httpTrace("context:%p, fd:%d, transferChunked:%d", pContext, pContext->fd, parser->transferChunked); + } + return 0; + } + + else if (0 == strcasecmp(key, "Authorization")) { + char * t = NULL; + char * s = NULL; + int32_t bytes = 0; + int32_t n = sscanf(val, "%ms %ms%n", &t, &s, &bytes); + if (n == 2 && t && s && bytes == strlen(val)) { + if (strcmp(t, "Basic") == 0) { + free(parser->authContent); + parser->authContent = s; + parser->authType = HTTP_BASIC_AUTH; + s = NULL; + free(t); + free(s); + httpTrace("context:%p, fd:%d, basic auth:%s", pContext, pContext->fd, parser->authContent); + int32_t ok = httpParseBasicAuthToken(pContext, parser->authContent, strlen(parser->authContent)); + if (ok != 0) { + httpOnError(parser, 0, TSDB_CODE_HTTP_INVALID_BASIC_AUTH); + return -1; + } + return 0; + } else if (strcmp(t, "Taosd") == 0) { + free(parser->authContent); + parser->authContent = s; + parser->authType = HTTP_TAOSD_AUTH; + s = NULL; + free(t); + free(s); + httpTrace("context:%p, fd:%d, taosd auth:%s", pContext, pContext->fd, parser->authContent); + int32_t ok = httpParseTaosdAuthToken(pContext, parser->authContent, strlen(parser->authContent)); + if (ok != 0) { + httpOnError(parser, 0, TSDB_CODE_HTTP_INVALID_TAOSD_AUTH); + return -1; + } + return 0; + } else { + parser->authType = HTTP_INVALID_AUTH; + httpError("context:%p, fd:%d, invalid auth, t:%s s:%s", pContext, pContext->fd, t, s); + httpOnError(parser, 0, TSDB_CODE_HTTP_INVALID_AUTH_TYPE); + free(t); + free(s); + return -1; + } + } else { + parser->authType = HTTP_INVALID_AUTH; + httpError("context:%p, fd:%d, parse auth failed, t:%s s:%s", pContext, pContext->fd, t, s); + httpOnError(parser, 0, TSDB_CODE_HTTP_INVALID_AUTH_FORMAT); + free(t); + free(s); + return -1; + } + } + + return 0; +} + +static int32_t httpOnBody(HttpParser *parser, const char *chunk, int32_t len) { + HttpContext *pContext = parser->pContext; + HttpString * buf = &parser->body; + if (parser->parseCode != TSDB_CODE_SUCCESS) return -1; + + if (buf->size <= 0) { + buf->size = MIN(len + 2, HTTP_BUFFER_SIZE); + buf->str = malloc(buf->size); + } + + int32_t newSize = buf->pos + len + 1; + if (newSize >= buf->size) { + if (buf->size >= HTTP_BUFFER_SIZE) { + httpError("context:%p, fd:%d, failed parse body, exceeding buffer size %d", pContext, pContext->fd, buf->size); + httpOnError(parser, 0, TSDB_CODE_HTTP_REQUSET_TOO_BIG); + return -1; + } + + newSize = MAX(newSize, HTTP_BUFFER_INIT); + newSize *= 4; + newSize = MIN(newSize, HTTP_BUFFER_SIZE); + buf->str = realloc(buf->str, newSize); + buf->size = newSize; + + if (buf->str == NULL) { + httpError("context:%p, fd:%d, failed parse body, realloc %d failed", pContext, pContext->fd, buf->size); + httpOnError(parser, 0, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); + return -1; + } + } + + memcpy(buf->str + buf->pos, chunk, len); + buf->pos += len; + buf->str[buf->pos] = 0; + + return 0; +} + +static int32_t httpOnEnd(HttpParser *parser) { + HttpContext *pContext = parser->pContext; + parser->parsed = true; + + if (parser->parseCode != TSDB_CODE_SUCCESS) { + return -1; + } + + httpTrace("context:%p, fd:%d, parse success", pContext, pContext->fd); + return 0; +} + +static HTTP_PARSER_STATE httpTopStack(HttpParser *parser) { + HttpStack *stack = &parser->stacks; + ASSERT(stack->pos >= 1); + + return stack->stacks[stack->pos - 1]; +} + +static int32_t httpPushStack(HttpParser *parser, HTTP_PARSER_STATE state) { + HttpStack *stack = &parser->stacks; + if (stack->size == 0) { + stack->pos = 0; + stack->size = 32; + stack->stacks = malloc(stack->size * sizeof(int8_t)); + } else if (stack->pos + 1 > stack->size) { + stack->size *= 2; + stack->stacks = realloc(stack->stacks, stack->size * sizeof(int8_t)); + } else { + } + + if (stack->stacks == NULL) return -1; + + stack->stacks[stack->pos] = state; + stack->pos++; + + return 0; +} + +static int32_t httpPopStack(HttpParser *parser) { + HttpStack *stack = &parser->stacks; + ASSERT(stack->pos >= 1); + stack->pos--; + return 0; +} + +static void httpClearStack(HttpStack *stack) { + stack->pos = 0; +} + +static int32_t httpCleanupStack(HttpStack *stack) { + free(stack->stacks); + memset(stack, 0, sizeof(HttpStack)); + + return 0; +} + +void httpInitParser(HttpParser *parser) { + HttpContext *pContext = parser->pContext; + httpTrace("context:%p, fd:%d, init parser", pContext, pContext->fd); + + parser->parsed = false; + parser->inited = 1; + parser->httpVersion = 0; + parser->acceptEncodingGzip = 0; + parser->acceptEncodingChunked = 0; + parser->contentLengthSpecified = 0; + parser->contentChunked = 0; + parser->transferGzip = 0; + parser->transferChunked = 0; + parser->keepAlive = 0; + parser->authType = 0; + parser->contentLength = 0; + parser->chunkSize = 0; + parser->receivedChunkSize = 0; + parser->receivedSize = 0; + parser->statusCode = 0; + parser->httpCode = 0; + parser->parseCode = 0; + + free(parser->method); parser->method = NULL; + free(parser->target); parser->target = NULL; + free(parser->version); parser->version = NULL; + free(parser->reasonPhrase); parser->reasonPhrase = NULL; + free(parser->key); parser->key = NULL; + free(parser->val); parser->val = NULL; + free(parser->authContent); parser->authContent = NULL; + + httpClearStack(&parser->stacks); + httpClearString(&parser->str); + httpClearString(&parser->body); + for (int32_t i = 0; i < HTTP_MAX_URL; ++i) { + httpClearString(&parser->path[i]); + } + + if (parser->gzip != NULL) { + ehttp_gzip_destroy(parser->gzip); + parser->gzip = NULL; + } + + httpPushStack(parser, HTTP_PARSER_BEGIN); +} + +HttpParser *httpCreateParser(HttpContext *pContext) { + HttpParser *parser = calloc(1, sizeof(HttpParser)); + if (!parser) return NULL; + httpTrace("context:%p, fd:%d, create parser", pContext, pContext->fd); + + parser->pContext = pContext; + return parser; +} + +void httpClearParser(HttpParser *parser) { + HttpContext *pContext = parser->pContext; + httpTrace("context:%p, fd:%d, clear parser", pContext, pContext->fd); + + pContext->parser->inited = 0; + pContext->parser->parsed = false; +} + +void httpDestroyParser(HttpParser *parser) { + HttpContext *pContext = parser->pContext; + httpTrace("context:%p, fd:%d, destroy parser", pContext, pContext->fd); + + if (!parser) return; + + free(parser->method); parser->method = NULL; + free(parser->target); parser->target = NULL; + free(parser->version); parser->version = NULL; + free(parser->reasonPhrase); parser->reasonPhrase = NULL; + free(parser->key); parser->key = NULL; + free(parser->val); parser->val = NULL; + free(parser->authContent); parser->authContent = NULL; + + httpCleanupStack(&parser->stacks); + httpCleanupString(&parser->str); + httpCleanupString(&parser->body); + for (int32_t i = 0; i < HTTP_MAX_URL; ++i) { + httpCleanupString(&parser->path[i]); + } + + if (parser->gzip != NULL) { + ehttp_gzip_destroy(parser->gzip); + parser->gzip = NULL; + } + + free(parser); +} + +#define is_token(c) (strchr("!#$%&'*+-.^_`|~", c) || isdigit(c) || isalpha(c)) + +char *httpDecodeUrl(const char *enc) { + int32_t ok = 1; + HttpString str = {0}; + while (*enc) { + char *p = strchr(enc, '%'); + if (!p) break; + int32_t hex, cnt; + int32_t n = sscanf(p+1, "%2x%n", &hex, &cnt); + if (n!=1 && cnt !=2) { ok = 0; break; } + if (httpAppendString(&str, enc, p-enc)) { ok = 0; break; } + char c = (char)hex; + if (httpAppendString(&str, &c, 1)) { ok = 0; break; } + enc = p+3; + } + char *dec = NULL; + if (ok && *enc) { + if (httpAppendString(&str, enc, strlen(enc))) { ok = 0; } + } + if (ok) { + dec = str.str; + str.str = NULL; + } + httpCleanupString(&str); + return dec; +} + +static void httpOnData(ehttp_gzip_t *gzip, void *arg, const char *buf, int32_t len) { + HttpParser *parser = (HttpParser*)arg; + httpOnBody(parser, buf, len); +} + +static int32_t httpParserOnBegin(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (c == 'G' || c == 'P' || c == 'H' || c == 'D' || c == 'C' || c == 'O' || c == 'T') { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_METHOD_FAILED); + break; + } + httpPopStack(parser); + httpPushStack(parser, HTTP_PARSER_REQUEST_OR_RESPONSE); + break; + } + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_METHOD_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnRquestOrResponse(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (parser->str.pos == 1) { + if (c == 'T' && parser->str.str[0] == 'H') { + httpPopStack(parser); + httpPushStack(parser, HTTP_PARSER_END); + httpPushStack(parser, HTTP_PARSER_HEADER); + httpPushStack(parser, HTTP_PARSER_CRLF); + httpPushStack(parser, HTTP_PARSER_REASON_PHRASE); + httpPushStack(parser, HTTP_PARSER_SP); + httpPushStack(parser, HTTP_PARSER_STATUS_CODE); + httpPushStack(parser, HTTP_PARSER_SP); + httpPushStack(parser, HTTP_PARSER_HTTP_VERSION); + *again = 1; + break; + } + httpPopStack(parser); + httpPushStack(parser, HTTP_PARSER_END); + httpPushStack(parser, HTTP_PARSER_HEADER); + httpPushStack(parser, HTTP_PARSER_CRLF); + httpPushStack(parser, HTTP_PARSER_HTTP_VERSION); + httpPushStack(parser, HTTP_PARSER_SP); + httpPushStack(parser, HTTP_PARSER_TARGET); + httpPushStack(parser, HTTP_PARSER_SP); + httpPushStack(parser, HTTP_PARSER_METHOD); + *again = 1; + break; + } + + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_METHOD_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnMethod(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (isalnum(c) || strchr("!#$%&'*+-.^_`|~", c)) { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_METHOD_FAILED); + break; + } + break; + } + parser->method = strdup(parser->str.str); + if (!parser->method) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_METHOD_FAILED); + break; + } else { + httpTrace("context:%p, fd:%d, httpMethod:%s", pContext, pContext->fd, parser->method); + } + httpClearString(&parser->str); + httpPopStack(parser); + *again = 1; + } while (0); + return ok; +} + +static int32_t httpParserOnTarget(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (!isspace(c) && c != '\r' && c != '\n') { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_TARGET_FAILED); + break; + } + break; + } + parser->target = strdup(parser->str.str); + if (!parser->target) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_TARGET_FAILED); + break; + } + httpClearString(&parser->str); + httpPopStack(parser); + *again = 1; + } while (0); + return ok; +} + +static int32_t httpParserOnVersion(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + const char *prefix = "HTTP/1."; + int32_t len = strlen(prefix); + if (parser->str.pos < len) { + if (prefix[parser->str.pos] != c) { + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_VERSION_FAILED); + break; + } + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_VERSION_FAILED); + break; + } + break; + } + + if (c!='0' && c!='1') { + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_VERSION_FAILED); + break; + } + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_VERSION_FAILED); + break; + } + + if (c == '0') parser->httpVersion = HTTP_VERSION_10; + else if (c == '1') parser->httpVersion = HTTP_VERSION_11; + else if (c == '2') parser->httpVersion = HTTP_VERSION_12; + else parser->httpVersion = HTTP_INVALID_VERSION; + + parser->version = strdup(parser->str.str); + if (!parser->version) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_VERSION_FAILED); + break; + } + + if (parser->method) { + ok = httpOnRequestLine(parser, parser->method, parser->target, parser->version); + } + + httpClearString(&parser->str); + httpPopStack(parser); + } while (0); + return ok; +} + +static int32_t httpParserOnSp(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (c == ' ') { + httpPopStack(parser); + break; + } + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_SP_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnStatusCode(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (isdigit(c)) { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_STATUS_FAILED); + break; + } + if (parser->str.pos < 3) break; + + sscanf(parser->str.str, "%d", &parser->statusCode); + httpClearString(&parser->str); + httpPopStack(parser); + break; + } + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_STATUS_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnReasonPhrase(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (c == '\r') { + parser->reasonPhrase = strdup(parser->str.str); + if (!parser->reasonPhrase) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_PHRASE_FAILED); + break; + } + ok = httpOnStatusLine(parser, parser->statusCode, parser->reasonPhrase); + httpClearString(&parser->str); + httpPopStack(parser); + *again = 1; + break; + } + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_PHRASE_FAILED); + break; + } + } while (0); + return ok; +} + +static int32_t httpParserPostProcess(HttpParser *parser) { + HttpContext *pContext = parser->pContext; + if (parser->gzip) { + if (ehttp_gzip_finish(parser->gzip)) { + httpError("context:%p, fd:%d, gzip failed", pContext, pContext->fd); + httpOnError(parser, 507, TSDB_CODE_HTTP_FINISH_GZIP_FAILED); + return -1; + } + } + httpOnEnd(parser); + return 0; +} + +static int32_t httpParserOnCrlf(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + const char *s = "\r\n"; + int32_t len = strlen(s); + if (s[parser->str.pos] != c) { + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_CRLF_FAILED); + break; + } + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_CRLF_FAILED); + break; + } + if (parser->str.pos == len) { + httpClearString(&parser->str); + httpPopStack(parser); + if (httpTopStack(parser) == HTTP_PARSER_END) { + ok = httpParserPostProcess(parser); + } + } + break; + } while (0); + return ok; +} + +static int32_t httpParserOnHeader(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (c == '\r') { + httpPopStack(parser); + if (parser->transferChunked) { + httpPushStack(parser, HTTP_PARSER_CHUNK_SIZE); + httpPushStack(parser, HTTP_PARSER_CRLF); + } else { + if (parser->contentLength > 0) { + httpPushStack(parser, HTTP_PARSER_CHUNK); + } + httpPushStack(parser, HTTP_PARSER_CRLF); + } + *again = 1; + break; + } + if (c != ' ' && c != '\t' && c != ':') { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_HEADER_FAILED); + break; + } + httpPushStack(parser, HTTP_PARSER_CRLF); + httpPushStack(parser, HTTP_PARSER_HEADER_VAL); + httpPushStack(parser, HTTP_PARSER_SP); + httpPushStack(parser, HTTP_PARSER_HEADER_KEY); + break; + } + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_HEADER_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnHeaderKey(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (isalnum(c) || strchr("!#$%&'*+-.^_`|~", c)) { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_HEADER_KEY_FAILED); + break; + } + break; + } + if (c == ':') { + parser->key = strdup(parser->str.str); + if (!parser->key) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_HEADER_KEY_FAILED); + break; + } + httpClearString(&parser->str); + httpPopStack(parser); + break; + } + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_HEADER_KEY_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnHeaderVal(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (c != '\r' && c != '\n' && (!isspace(c) || parser->str.pos > 0)) { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + parser->parseCode = TSDB_CODE_HTTP_PARSE_HEADER_VAL_FAILED; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_HEADER_VAL_FAILED); + break; + } + break; + } + const char *val = parser->str.str; + ok = httpOnParseHeaderField(parser, parser->key, val); + free(parser->key); + parser->key = NULL; + val = NULL; + if (ok == -1) break; + httpClearString(&parser->str); + httpPopStack(parser); + *again = 1; + } while (0); + return ok; +} + +static int32_t httpParserOnChunkSize(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + int32_t bytes; + int32_t len; + int32_t n; + do { + if (isxdigit(c)) { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_CHUNK_SIZE_FAILED); + break; + } + break; + } + if (c == '\r') { + n = sscanf(parser->str.str, "%x%n", &len, &bytes); + if (n == 1 && bytes == strlen(parser->str.str) && len >= 0) { + if (len == 0) { + if (parser->contentLengthSpecified == 0 || parser->receivedSize == parser->contentLength) { + httpClearString(&parser->str); + httpPopStack(parser); + httpPushStack(parser, HTTP_PARSER_CRLF); + httpPushStack(parser, HTTP_PARSER_CRLF); + *again = 1; + break; + } + } else { + if (parser->contentLengthSpecified == 0 || parser->receivedSize + len <= parser->contentLength) { + parser->chunkSize = len; + httpClearString(&parser->str); + httpPopStack(parser); + httpPushStack(parser, HTTP_PARSER_CHUNK_SIZE); + httpPushStack(parser, HTTP_PARSER_CRLF); + httpPushStack(parser, HTTP_PARSER_CHUNK); + httpPushStack(parser, HTTP_PARSER_CRLF); + *again = 1; + break; + } + } + } + } + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 400, TSDB_CODE_HTTP_PARSE_CHUNK_SIZE_FAILED); + } while (0); + return ok; +} + +static int32_t httpParserOnChunk(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + if (httpAppendString(&parser->str, &c, 1)) { + httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_CHUNK_FAILED); + break; + } + ++parser->receivedSize; + ++parser->receivedChunkSize; + if (parser->receivedChunkSize < parser->chunkSize) break; + + if (parser->gzip) { + if (ehttp_gzip_write(parser->gzip, parser->str.str, parser->str.pos)) { + httpError("context:%p, fd:%d, gzip failed", pContext, pContext->fd); + ok = -1; + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_CHUNK_FAILED); + break; + } + } else { + httpOnBody(parser, parser->str.str, parser->str.pos); + } + parser->receivedChunkSize = 0; + httpClearString(&parser->str); + httpPopStack(parser); + if (httpTopStack(parser) == HTTP_PARSER_END) { + ok = httpParserPostProcess(parser); + } + } while (0); + return ok; +} + +static int32_t httpParserOnEnd(HttpParser *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + do { + ok = -1; + httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c); + httpOnError(parser, 507, TSDB_CODE_HTTP_PARSE_END_FAILED); + } while (0); + return ok; +} + +static int32_t httpParseChar(HttpParser *parser, const char c, int32_t *again) { + HttpContext *pContext = parser->pContext; + int32_t ok = 0; + HTTP_PARSER_STATE state = httpTopStack(parser); + do { + if (state == HTTP_PARSER_BEGIN) { + ok = httpParserOnBegin(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_REQUEST_OR_RESPONSE) { + ok = httpParserOnRquestOrResponse(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_METHOD) { + ok = httpParserOnMethod(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_TARGET) { + ok = httpParserOnTarget(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_HTTP_VERSION) { + ok = httpParserOnVersion(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_SP) { + ok = httpParserOnSp(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_STATUS_CODE) { + ok = httpParserOnStatusCode(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_REASON_PHRASE) { + ok = httpParserOnReasonPhrase(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_CRLF) { + ok = httpParserOnCrlf(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_HEADER) { + ok = httpParserOnHeader(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_HEADER_KEY) { + ok = httpParserOnHeaderKey(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_HEADER_VAL) { + ok = httpParserOnHeaderVal(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_CHUNK_SIZE) { + ok = httpParserOnChunkSize(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_CHUNK) { + ok = httpParserOnChunk(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_END) { + ok = httpParserOnEnd(parser, state, c, again); + break; + } + if (state == HTTP_PARSER_ERROR) { + ok = -2; + break; + } + + ok = -1; + httpError("context:%p, fd:%d, unknown parse state:%d", pContext, pContext->fd, state); + httpOnError(parser, 500, TSDB_CODE_HTTP_PARSE_INVALID_STATE); + } while (0); + + if (ok == -1) { + httpError("context:%p, fd:%d, failed to parse, state:%d", pContext, pContext->fd, state); + httpPushStack(parser, HTTP_PARSER_ERROR); + } + + if (ok == -2) { + ok = -1; + httpError("context:%p, fd:%d, failed to parse, invalid state", pContext, pContext->fd); + httpOnError(parser, 500, TSDB_CODE_HTTP_PARSE_ERROR_STATE); + } + + return ok; +} + +int32_t httpParseBuf(HttpParser *parser, const char *buf, int32_t len) { + HttpContext *pContext = parser->pContext; + const char *p = buf; + int32_t ret = 0; + int32_t i = 0; + + while (i < len) { + int32_t again = 0; + ret = httpParseChar(parser, *p, &again); + if (ret != 0) { + httpError("context:%p, fd:%d, parse failed, ret:%d i:%d len:%d buf:%s", pContext, pContext->fd, ret, i, len, buf); + break; + } + if (again) continue; + ++p; + ++i; + } + + return ret; +} diff --git a/src/plugins/http/src/httpQueue.c b/src/plugins/http/src/httpQueue.c index 9625102f7450daf409d35aa532267f3f999d80ab..86a97a6abe251e1fa99219b9fb63a525ba89f7d4 100644 --- a/src/plugins/http/src/httpQueue.c +++ b/src/plugins/http/src/httpQueue.c @@ -39,15 +39,15 @@ typedef struct { typedef struct { void *param; void *result; - int numOfRows; - void (*fp)(void *param, void *result, int numOfRows); + int32_t numOfRows; + void (*fp)(void *param, void *result, int32_t numOfRows); } SHttpResult; static SHttpWorkerPool tsHttpPool; static taos_qset tsHttpQset; static taos_queue tsHttpQueue; -void httpDispatchToResultQueue(void *param, TAOS_RES *result, int numOfRows, void (*fp)(void *param, void *result, int numOfRows)) { +void httpDispatchToResultQueue(void *param, TAOS_RES *result, int32_t numOfRows, void (*fp)(void *param, void *result, int32_t numOfRows)) { if (tsHttpQueue != NULL) { SHttpResult *pMsg = (SHttpResult *)taosAllocateQitem(sizeof(SHttpResult)); pMsg->param = param; @@ -71,7 +71,7 @@ static void *httpProcessResultQueue(void *param) { break; } - httpDebug("context:%p, res:%p will be processed in result queue", pMsg->param, pMsg->result); + httpTrace("context:%p, res:%p will be processed in result queue", pMsg->param, pMsg->result); (*pMsg->fp)(pMsg->param, pMsg->result, pMsg->numOfRows); taosFreeQitem(pMsg); } diff --git a/src/plugins/http/src/httpResp.c b/src/plugins/http/src/httpResp.c index f53aff7831619319c1600cb1f6a7605cb33ed1be..755dad2d850c24192f5eee35c49492378ba8fb73 100644 --- a/src/plugins/http/src/httpResp.c +++ b/src/plugins/http/src/httpResp.c @@ -19,7 +19,6 @@ #include "taosmsg.h" #include "httpLog.h" #include "httpResp.h" -#include "httpCode.h" #include "httpJson.h" #include "httpContext.h" @@ -45,155 +44,112 @@ const char *httpRespTemplate[] = { "%s 200 OK\r\nAccess-Control-Allow-Origin:*\r\n%sAccess-Control-Allow-Methods:POST, GET, OPTIONS, DELETE, PUT\r\nAccess-Control-Allow-Headers:Accept, Content-Type\r\nContent-Type: application/json;charset=utf-8\r\nContent-Length: %d\r\n\r\n" }; -static void httpSendErrorRespImp(HttpContext *pContext, int httpCode, char *httpCodeStr, int errNo, char *desc) { - httpError("context:%p, fd:%d, ip:%s, code:%d, error:%s", pContext, pContext->fd, pContext->ipstr, httpCode, desc); +static void httpSendErrorRespImp(HttpContext *pContext, int32_t httpCode, char *httpCodeStr, int32_t errNo, const char *desc) { + httpError("context:%p, fd:%d, code:%d, error:%s", pContext, pContext->fd, httpCode, desc); char head[512] = {0}; char body[512] = {0}; - int bodyLen = sprintf(body, httpRespTemplate[HTTP_RESPONSE_JSON_ERROR], errNo, desc); - int headLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_ERROR], httpVersionStr[pContext->httpVersion], httpCode, - httpCodeStr, httpKeepAliveStr[pContext->httpKeepAlive], bodyLen); + int32_t bodyLen = sprintf(body, httpRespTemplate[HTTP_RESPONSE_JSON_ERROR], errNo, desc); + int32_t headLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_ERROR], httpVersionStr[pContext->parser->httpVersion], + httpCode, httpCodeStr, httpKeepAliveStr[pContext->parser->keepAlive], bodyLen); httpWriteBuf(pContext, head, headLen); httpWriteBuf(pContext, body, bodyLen); httpCloseContextByApp(pContext); } -void httpSendErrorRespWithDesc(HttpContext *pContext, int errNo, char *desc) { - int httpCode = 500; - char *httpCodeStr = "Internal Server Error"; - switch (errNo) { - case HTTP_SUCCESS: - httpCode = 200; - httpCodeStr = "OK"; - break; - case HTTP_SERVER_OFFLINE: - case HTTP_UNSUPPORT_URL: - httpCode = 404; - httpCodeStr = "Not Found"; - break; - case HTTP_PARSE_HTTP_METHOD_ERROR: - httpCode = 405; - httpCodeStr = "Method Not Allowed"; - break; - case HTTP_PARSE_HTTP_VERSION_ERROR: - httpCode = 505; - httpCodeStr = "HTTP Version Not Supported"; - break; - case HTTP_PARSE_HEAD_ERROR: - httpCode = 406; - httpCodeStr = "Not Acceptable"; - break; - case HTTP_REQUSET_TOO_BIG: - httpCode = 413; - httpCodeStr = "Request Entity Too Large"; - break; - case HTTP_PARSE_BODY_ERROR: - case HTTP_PARSE_CHUNKED_BODY_ERROR: - httpCode = 409; - httpCodeStr = "Conflict"; - break; - case HTTP_PARSE_URL_ERROR: - httpCode = 414; - httpCodeStr = "Request-URI Invalid"; - break; - case HTTP_INVALID_AUTH_TOKEN: - case HTTP_PARSE_USR_ERROR: - httpCode = 401; - httpCodeStr = "Unauthorized"; - break; - case HTTP_NO_SQL_INPUT: - httpCode = 400; - httpCodeStr = "Bad Request"; - break; - case HTTP_SESSION_FULL: - httpCode = 421; - httpCodeStr = "Too many connections"; - break; - case HTTP_NO_ENOUGH_MEMORY: - case HTTP_GEN_TAOSD_TOKEN_ERR: - httpCode = 507; - httpCodeStr = "Insufficient Storage"; - break; - case HTTP_INVALID_DB_TABLE: - case HTTP_NO_EXEC_USEDB: - case HTTP_PARSE_GC_REQ_ERROR: - case HTTP_INVALID_MULTI_REQUEST: - case HTTP_NO_MSG_INPUT: - httpCode = 400; - httpCodeStr = "Bad Request"; - break; - case HTTP_NO_ENOUGH_SESSIONS: - httpCode = 421; - httpCodeStr = "Too many connections"; - break; - // telegraf - case HTTP_TG_DB_NOT_INPUT: - case HTTP_TG_DB_TOO_LONG: - case HTTP_TG_INVALID_JSON: - case HTTP_TG_METRICS_NULL: - case HTTP_TG_METRICS_SIZE: - case HTTP_TG_METRIC_NULL: - case HTTP_TG_METRIC_TYPE: - case HTTP_TG_METRIC_NAME_NULL: - case HTTP_TG_METRIC_NAME_LONG: - case HTTP_TG_TIMESTAMP_NULL: - case HTTP_TG_TIMESTAMP_TYPE: - case HTTP_TG_TIMESTAMP_VAL_NULL: - case HTTP_TG_TAGS_NULL: - case HTTP_TG_TAGS_SIZE_0: - case HTTP_TG_TAGS_SIZE_LONG: - case HTTP_TG_TAG_NULL: - case HTTP_TG_TAG_NAME_NULL: - case HTTP_TG_TAG_NAME_SIZE: - case HTTP_TG_TAG_VALUE_TYPE: - case HTTP_TG_TAG_VALUE_NULL: - case HTTP_TG_TABLE_NULL: - case HTTP_TG_TABLE_SIZE: - case HTTP_TG_FIELDS_NULL: - case HTTP_TG_FIELDS_SIZE_0: - case HTTP_TG_FIELDS_SIZE_LONG: - case HTTP_TG_FIELD_NULL: - case HTTP_TG_FIELD_NAME_NULL: - case HTTP_TG_FIELD_NAME_SIZE: - case HTTP_TG_FIELD_VALUE_TYPE: - case HTTP_TG_FIELD_VALUE_NULL: - case HTTP_INVALID_BASIC_AUTH_TOKEN: - case HTTP_INVALID_TAOSD_AUTH_TOKEN: - case HTTP_TG_HOST_NOT_STRING: - // grafana - case HTTP_GC_QUERY_NULL: - case HTTP_GC_QUERY_SIZE: - httpCode = 400; - httpCodeStr = "Bad Request"; - break; - default: - httpError("context:%p, fd:%d, ip:%s, error:%d not recognized", pContext, pContext->fd, pContext->ipstr, errNo); - break; +void httpSendErrorResp(HttpContext *pContext, int32_t errNo) { + int32_t httpCode = 500; + if (errNo == TSDB_CODE_SUCCESS) + httpCode = 200; + else if (errNo == TSDB_CODE_HTTP_SERVER_OFFLINE) + httpCode = 404; + else if (errNo == TSDB_CODE_HTTP_UNSUPPORT_URL) + httpCode = 404; + else if (errNo == TSDB_CODE_HTTP_INVLALID_URL) + httpCode = 404; + else if (errNo == TSDB_CODE_HTTP_NO_ENOUGH_MEMORY) + httpCode = 507; + else if (errNo == TSDB_CODE_HTTP_REQUSET_TOO_BIG) + httpCode = 413; + else if (errNo == TSDB_CODE_HTTP_NO_AUTH_INFO) + httpCode = 401; + else if (errNo == TSDB_CODE_HTTP_NO_MSG_INPUT) + httpCode = 400; + else if (errNo == TSDB_CODE_HTTP_NO_SQL_INPUT) + httpCode = 400; + else if (errNo == TSDB_CODE_HTTP_NO_EXEC_USEDB) + httpCode = 400; + else if (errNo == TSDB_CODE_HTTP_SESSION_FULL) + httpCode = 421; + else if (errNo == TSDB_CODE_HTTP_GEN_TAOSD_TOKEN_ERR) + httpCode = 507; + else if (errNo == TSDB_CODE_HTTP_INVALID_MULTI_REQUEST) + httpCode = 400; + else if (errNo == TSDB_CODE_HTTP_CREATE_GZIP_FAILED) + httpCode = 507; + else if (errNo == TSDB_CODE_HTTP_FINISH_GZIP_FAILED) + httpCode = 507; + else if (errNo == TSDB_CODE_HTTP_INVALID_VERSION) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_INVALID_CONTENT_LENGTH) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_INVALID_AUTH_TYPE) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_INVALID_AUTH_FORMAT) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_INVALID_BASIC_AUTH) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_INVALID_TAOSD_AUTH) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_METHOD_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_TARGET_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_VERSION_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_SP_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_STATUS_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_PHRASE_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_CRLF_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_HEADER_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_HEADER_KEY_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_HEADER_VAL_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_CHUNK_SIZE_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_CHUNK_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_END_FAILED) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_INVALID_STATE) + httpCode = 406; + else if (errNo == TSDB_CODE_HTTP_PARSE_ERROR_STATE) + httpCode = 406; + else + httpCode = 400; + + if (pContext->parser->httpCode != 0) { + httpCode = pContext->parser->httpCode; } - if (desc == NULL) { - httpSendErrorRespImp(pContext, httpCode, httpCodeStr, errNo + 5000, httpMsg[errNo]); - } else { - httpSendErrorRespImp(pContext, httpCode, httpCodeStr, errNo + 5000, desc); - } -} - -void httpSendErrorResp(HttpContext *pContext, int errNo) { httpSendErrorRespWithDesc(pContext, errNo, NULL); } - -void httpSendTaosdErrorResp(HttpContext *pContext, int errCode) { - int httpCode = 400; - - httpSendErrorRespImp(pContext, httpCode, "Bad Request", errCode & 0XFFFF, (char*)tstrerror(errCode)); + char *httpCodeStr = httpGetStatusDesc(httpCode); + httpSendErrorRespImp(pContext, httpCode, httpCodeStr, errNo & 0XFFFF, tstrerror(errNo)); } -void httpSendTaosdInvalidSqlErrorResp(HttpContext *pContext, char* errMsg) { - int httpCode = 400; - char temp[512] = {0}; - int len = sprintf(temp, "invalid SQL: %s", errMsg); +void httpSendTaosdInvalidSqlErrorResp(HttpContext *pContext, char *errMsg) { + int32_t httpCode = 400; + char temp[512] = {0}; + int32_t len = sprintf(temp, "invalid SQL: %s", errMsg); - for (int i = 0; i < len; ++i) { + for (int32_t i = 0; i < len; ++i) { if (temp[i] == '\"') { temp[i] = '\''; } else if (temp[i] == '\n') { @@ -208,9 +164,9 @@ void httpSendSuccResp(HttpContext *pContext, char *desc) { char head[1024] = {0}; char body[1024] = {0}; - int bodyLen = sprintf(body, httpRespTemplate[HTTP_RESPONSE_JSON_OK], HTTP_SUCCESS, desc); - int headLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_OK], httpVersionStr[pContext->httpVersion], - httpKeepAliveStr[pContext->httpKeepAlive], bodyLen); + int32_t bodyLen = sprintf(body, httpRespTemplate[HTTP_RESPONSE_JSON_OK], TSDB_CODE_SUCCESS, desc); + int32_t headLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_OK], httpVersionStr[pContext->parser->httpVersion], + httpKeepAliveStr[pContext->parser->keepAlive], bodyLen); httpWriteBuf(pContext, head, headLen); httpWriteBuf(pContext, body, bodyLen); @@ -221,9 +177,9 @@ void httpSendOptionResp(HttpContext *pContext, char *desc) { char head[1024] = {0}; char body[1024] = {0}; - int bodyLen = sprintf(body, httpRespTemplate[HTTP_RESPONSE_JSON_OK], HTTP_SUCCESS, desc); - int headLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_OPTIONS], httpVersionStr[pContext->httpVersion], - httpKeepAliveStr[pContext->httpKeepAlive], bodyLen); + int32_t bodyLen = sprintf(body, httpRespTemplate[HTTP_RESPONSE_JSON_OK], TSDB_CODE_SUCCESS, desc); + int32_t headLen = sprintf(head, httpRespTemplate[HTTP_RESPONSE_OPTIONS], httpVersionStr[pContext->parser->httpVersion], + httpKeepAliveStr[pContext->parser->keepAlive], bodyLen); httpWriteBuf(pContext, head, headLen); httpWriteBuf(pContext, body, bodyLen); diff --git a/src/plugins/http/src/restHandle.c b/src/plugins/http/src/httpRestHandle.c similarity index 78% rename from src/plugins/http/src/restHandle.c rename to src/plugins/http/src/httpRestHandle.c index f0841e2f9922e68e5bbd7ba441540945e2d7ca21..0a28c431ef313d36bd54b686e583e0dfb2313c0f 100644 --- a/src/plugins/http/src/restHandle.c +++ b/src/plugins/http/src/httpRestHandle.c @@ -15,9 +15,10 @@ #define _DEFAULT_SOURCE #include "os.h" +#include "taoserror.h" #include "httpLog.h" -#include "restHandle.h" -#include "restJson.h" +#include "httpRestHandle.h" +#include "httpRestJson.h" static HttpDecodeMethod restDecodeMethod = {"rest", restProcessRequest}; static HttpDecodeMethod restDecodeMethod2 = {"restful", restProcessRequest}; @@ -60,39 +61,37 @@ void restInitHandle(HttpServer* pServer) { } bool restGetUserFromUrl(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - if (pParser->path[REST_USER_URL_POS].len >= TSDB_USER_LEN || pParser->path[REST_USER_URL_POS].len <= 0) { + HttpParser* pParser = pContext->parser; + if (pParser->path[REST_USER_URL_POS].pos >= TSDB_USER_LEN || pParser->path[REST_USER_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->user, pParser->path[REST_USER_URL_POS].pos, TSDB_USER_LEN); + tstrncpy(pContext->user, pParser->path[REST_USER_URL_POS].str, TSDB_USER_LEN); return true; } bool restGetPassFromUrl(HttpContext* pContext) { - HttpParser* pParser = &pContext->parser; - if (pParser->path[REST_PASS_URL_POS].len >= TSDB_PASSWORD_LEN || pParser->path[REST_PASS_URL_POS].len <= 0) { + HttpParser* pParser = pContext->parser; + if (pParser->path[REST_PASS_URL_POS].pos >= TSDB_PASSWORD_LEN || pParser->path[REST_PASS_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->pass, pParser->path[REST_PASS_URL_POS].pos, TSDB_PASSWORD_LEN); + tstrncpy(pContext->pass, pParser->path[REST_PASS_URL_POS].str, TSDB_PASSWORD_LEN); return true; } bool restProcessLoginRequest(HttpContext* pContext) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process restful login msg", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpDebug("context:%p, fd:%d, user:%s, process restful login msg", pContext, pContext->fd, pContext->user); pContext->reqType = HTTP_REQTYPE_LOGIN; return true; } -bool restProcessSqlRequest(HttpContext* pContext, int timestampFmt) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process restful sql msg", pContext, pContext->fd, pContext->ipstr, - pContext->user); +bool restProcessSqlRequest(HttpContext* pContext, int32_t timestampFmt) { + httpDebug("context:%p, fd:%d, user:%s, process restful sql msg", pContext, pContext->fd, pContext->user); - char* sql = pContext->parser.data.pos; + char* sql = pContext->parser->body.str; if (sql == NULL) { - httpSendErrorResp(pContext, HTTP_NO_SQL_INPUT); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_SQL_INPUT); return false; } @@ -101,7 +100,7 @@ bool restProcessSqlRequest(HttpContext* pContext, int timestampFmt) { * for async test * if (httpCheckUsedbSql(sql)) { - httpSendErrorResp(pContext, HTTP_NO_EXEC_USEDB); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_EXEC_USEDB); return false; } */ @@ -128,7 +127,7 @@ bool restProcessRequest(struct HttpContext* pContext) { } if (strlen(pContext->user) == 0 || strlen(pContext->pass) == 0) { - httpSendErrorResp(pContext, HTTP_PARSE_USR_ERROR); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_AUTH_INFO); return false; } @@ -143,6 +142,6 @@ bool restProcessRequest(struct HttpContext* pContext) { } else { } - httpSendErrorResp(pContext, HTTP_PARSE_URL_ERROR); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_INVLALID_URL); return false; } diff --git a/src/plugins/http/src/restJson.c b/src/plugins/http/src/httpRestJson.c similarity index 82% rename from src/plugins/http/src/restJson.c rename to src/plugins/http/src/httpRestJson.c index 7a73f6559f21427d04d37289338d73ec64306dc0..26f04415196a0f93c8fe893ce71a7d704949923c 100644 --- a/src/plugins/http/src/restJson.c +++ b/src/plugins/http/src/httpRestJson.c @@ -18,10 +18,10 @@ #include "tglobal.h" #include "httpLog.h" #include "httpJson.h" -#include "restHandle.h" -#include "restJson.h" +#include "httpRestHandle.h" +#include "httpRestJson.h" -void restBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int affect_rows) { +void restBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int32_t affect_rows) { JsonBuf *jsonBuf = httpMallocJsonBuf(pContext); if (jsonBuf == NULL) return; @@ -43,7 +43,7 @@ void restStartSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result) if (jsonBuf == NULL) return; TAOS_FIELD *fields = taos_fetch_fields(result); - int num_fields = taos_num_fields(result); + int32_t num_fields = taos_num_fields(result); httpInitJsonBuf(jsonBuf, pContext); httpWriteJsonBufHead(jsonBuf); @@ -66,9 +66,9 @@ void restStartSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result) httpJsonItemToken(jsonBuf); httpJsonString(jsonBuf, REST_JSON_AFFECT_ROWS, REST_JSON_AFFECT_ROWS_LEN); } else { - for (int i = 0; i < num_fields; ++i) { + for (int32_t i = 0; i < num_fields; ++i) { httpJsonItemToken(jsonBuf); - httpJsonString(jsonBuf, fields[i].name, (int)strlen(fields[i].name)); + httpJsonString(jsonBuf, fields[i].name, (int32_t)strlen(fields[i].name)); } } @@ -83,16 +83,16 @@ void restStartSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result) httpJsonToken(jsonBuf, JsonArrStt); } -bool restBuildSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows, int timestampFormat) { +bool restBuildSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows, int32_t timestampFormat) { JsonBuf *jsonBuf = httpMallocJsonBuf(pContext); if (jsonBuf == NULL) return false; cmd->numOfRows += numOfRows; - int num_fields = taos_num_fields(result); + int32_t num_fields = taos_num_fields(result); TAOS_FIELD *fields = taos_fetch_fields(result); - for (int k = 0; k < numOfRows; ++k) { + for (int32_t k = 0; k < numOfRows; ++k) { TAOS_ROW row = taos_fetch_row(result); if (row == NULL) { cmd->numOfRows--; @@ -104,7 +104,7 @@ bool restBuildSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, httpJsonItemToken(jsonBuf); httpJsonToken(jsonBuf, JsonArrStt); - for (int i = 0; i < num_fields; i++) { + for (int32_t i = 0; i < num_fields; i++) { httpJsonItemToken(jsonBuf); if (row[i] == NULL) { @@ -155,33 +155,31 @@ bool restBuildSqlJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, } if (cmd->numOfRows >= tsRestRowLimit) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, retrieve rows:%d larger than limit:%d, abort retrieve", pContext, - pContext->fd, pContext->ipstr, pContext->user, cmd->numOfRows, tsRestRowLimit); + httpDebug("context:%p, fd:%d, user:%s, retrieve rows:%d larger than limit:%d, abort retrieve", pContext, + pContext->fd, pContext->user, cmd->numOfRows, tsRestRowLimit); return false; - } - else { + } else { if (pContext->fd <= 0) { - httpError("context:%p, fd:%d, ip:%s, user:%s, connection is closed, abort retrieve", pContext, pContext->fd, - pContext->ipstr, pContext->user); + httpError("context:%p, fd:%d, user:%s, connection is closed, abort retrieve", pContext, pContext->fd, + pContext->user); return false; - } - else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, total rows:%d retrieved", pContext, pContext->fd, pContext->ipstr, - pContext->user, cmd->numOfRows); + } else { + httpDebug("context:%p, fd:%d, user:%s, total rows:%d retrieved", pContext, pContext->fd, pContext->user, + cmd->numOfRows); return true; } } } -bool restBuildSqlTimestampJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows) { +bool restBuildSqlTimestampJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows) { return restBuildSqlJson(pContext,cmd, result, numOfRows, REST_TIMESTAMP_FMT_TIMESTAMP); } -bool restBuildSqlLocalTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows) { +bool restBuildSqlLocalTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows) { return restBuildSqlJson(pContext,cmd, result, numOfRows, REST_TIMESTAMP_FMT_LOCAL_STRING); } -bool restBuildSqlUtcTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int numOfRows) { +bool restBuildSqlUtcTimeStringJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result, int32_t numOfRows) { return restBuildSqlJson(pContext,cmd, result, numOfRows, REST_TIMESTAMP_FMT_UTC_STRING); } diff --git a/src/plugins/http/src/httpServer.c b/src/plugins/http/src/httpServer.c index f4aca91cba7fb330b3a74ba2206d568df8563cf3..d85a236cb16b0fe83924ab4affe81287cf9c9475 100644 --- a/src/plugins/http/src/httpServer.c +++ b/src/plugins/http/src/httpServer.c @@ -29,6 +29,8 @@ #define EPOLLWAKEUP (1u << 29) #endif +static bool httpReadData(HttpContext *pContext); + static void httpStopThread(HttpThread* pThread) { pThread->stop = true; @@ -59,7 +61,7 @@ void httpCleanUpConnect() { if (pServer->pThreads == NULL) return; pthread_join(pServer->thread, NULL); - for (int i = 0; i < pServer->numOfThreads; ++i) { + for (int32_t i = 0; i < pServer->numOfThreads; ++i) { HttpThread* pThread = pServer->pThreads + i; if (pThread != NULL) { httpStopThread(pThread); @@ -69,119 +71,11 @@ void httpCleanUpConnect() { httpDebug("http server:%s is cleaned up", pServer->label); } -int httpReadDataImp(HttpContext *pContext) { - HttpParser *pParser = &pContext->parser; - - while (pParser->bufsize <= (HTTP_BUFFER_SIZE - HTTP_STEP_SIZE)) { - int nread = (int)taosReadSocket(pContext->fd, pParser->buffer + pParser->bufsize, HTTP_STEP_SIZE); - if (nread >= 0 && nread < HTTP_STEP_SIZE) { - pParser->bufsize += nread; - break; - } else if (nread < 0) { - if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { - httpDebug("context:%p, fd:%d, ip:%s, read from socket error:%d, wait another event", - pContext, pContext->fd, pContext->ipstr, errno); - break; - } else { - httpError("context:%p, fd:%d, ip:%s, read from socket error:%d, close connect", - pContext, pContext->fd, pContext->ipstr, errno); - return HTTP_READ_DATA_FAILED; - } - } else { - pParser->bufsize += nread; - } - - if (pParser->bufsize >= (HTTP_BUFFER_SIZE - HTTP_STEP_SIZE)) { - httpError("context:%p, fd:%d, ip:%s, thread:%s, request big than:%d", - pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, HTTP_BUFFER_SIZE); - return HTTP_REQUSET_TOO_BIG; - } - } - - pParser->buffer[pParser->bufsize] = 0; - - return HTTP_READ_DATA_SUCCESS; -} - -static bool httpDecompressData(HttpContext *pContext) { - if (pContext->contentEncoding != HTTP_COMPRESS_GZIP) { - httpTraceL("context:%p, fd:%d, ip:%s, content:%s", pContext, pContext->fd, pContext->ipstr, pContext->parser.data.pos); - return true; - } - - char *decompressBuf = calloc(HTTP_DECOMPRESS_BUF_SIZE, 1); - int32_t decompressBufLen = HTTP_DECOMPRESS_BUF_SIZE; - size_t bufsize = sizeof(pContext->parser.buffer) - (pContext->parser.data.pos - pContext->parser.buffer) - 1; - if (decompressBufLen > (int)bufsize) { - decompressBufLen = (int)bufsize; - } - - int ret = httpGzipDeCompress(pContext->parser.data.pos, pContext->parser.data.len, decompressBuf, &decompressBufLen); - - if (ret == 0) { - memcpy(pContext->parser.data.pos, decompressBuf, decompressBufLen); - pContext->parser.data.pos[decompressBufLen] = 0; - httpTraceL("context:%p, fd:%d, ip:%s, rawSize:%d, decompressSize:%d, content:%s", pContext, pContext->fd, - pContext->ipstr, pContext->parser.data.len, decompressBufLen, decompressBuf); - pContext->parser.data.len = decompressBufLen; - } else { - httpError("context:%p, fd:%d, ip:%s, failed to decompress data, rawSize:%d, error:%d", - pContext, pContext->fd, pContext->ipstr, pContext->parser.data.len, ret); - } - - free(decompressBuf); - return ret == 0; -} - -static bool httpReadData(HttpContext *pContext) { - if (!pContext->parsed) { - httpInitContext(pContext); - } - - int32_t code = httpReadDataImp(pContext); - if (code != HTTP_READ_DATA_SUCCESS) { - if (code == HTTP_READ_DATA_FAILED) { - httpReleaseContext(pContext); - } else { - httpSendErrorResp(pContext, code); - httpNotifyContextClose(pContext); - } - return false; - } - - if (!httpParseRequest(pContext)) { - httpNotifyContextClose(pContext); - return false; - } - - int ret = httpCheckReadCompleted(pContext); - if (ret == HTTP_CHECK_BODY_CONTINUE) { - //httpDebug("context:%p, fd:%d, ip:%s, not finished yet, wait another event", pContext, pContext->fd, pContext->ipstr); - httpReleaseContext(pContext); - return false; - } else if (ret == HTTP_CHECK_BODY_SUCCESS){ - httpDebug("context:%p, fd:%d, ip:%s, thread:%s, read size:%d, dataLen:%d", - pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->parser.bufsize, pContext->parser.data.len); - if (httpDecompressData(pContext)) { - return true; - } else { - httpNotifyContextClose(pContext); - httpReleaseContext(pContext); - return false; - } - } else { - httpError("context:%p, fd:%d, ip:%s, failed to read http body, close connect", pContext, pContext->fd, pContext->ipstr); - httpNotifyContextClose(pContext); - httpReleaseContext(pContext); - return false; - } -} - static void httpProcessHttpData(void *param) { HttpServer *pServer = &tsHttpServer; HttpThread *pThread = (HttpThread *)param; HttpContext *pContext; - int fdNum; + int32_t fdNum; sigset_t set; sigemptyset(&set); @@ -198,7 +92,7 @@ static void httpProcessHttpData(void *param) { } if (fdNum <= 0) continue; - for (int i = 0; i < fdNum; ++i) { + for (int32_t i = 0; i < fdNum; ++i) { pContext = httpGetContext(events[i].data.ptr); if (pContext == NULL) { httpError("context:%p, is already released, close connect", events[i].data.ptr); @@ -208,49 +102,51 @@ static void httpProcessHttpData(void *param) { } if (events[i].events & EPOLLPRI) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s, EPOLLPRI events occured, accessed:%d, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); + httpDebug("context:%p, fd:%d, state:%s, EPOLLPRI events occured, accessed:%d, close connect", pContext, + pContext->fd, httpContextStateStr(pContext->state), pContext->accessTimes); httpCloseContextByServer(pContext); continue; } if (events[i].events & EPOLLRDHUP) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s, EPOLLRDHUP events occured, accessed:%d, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); + httpDebug("context:%p, fd:%d, state:%s, EPOLLRDHUP events occured, accessed:%d, close connect", pContext, + pContext->fd, httpContextStateStr(pContext->state), pContext->accessTimes); httpCloseContextByServer(pContext); continue; } if (events[i].events & EPOLLERR) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s, EPOLLERR events occured, accessed:%d, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); + httpDebug("context:%p, fd:%d, state:%s, EPOLLERR events occured, accessed:%d, close connect", pContext, + pContext->fd, httpContextStateStr(pContext->state), pContext->accessTimes); httpCloseContextByServer(pContext); continue; } if (events[i].events & EPOLLHUP) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s, EPOLLHUP events occured, accessed:%d, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); + httpDebug("context:%p, fd:%d, state:%s, EPOLLHUP events occured, accessed:%d, close connect", pContext, + pContext->fd, httpContextStateStr(pContext->state), pContext->accessTimes); httpCloseContextByServer(pContext); continue; } if (!httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s, not in ready state, ignore read events", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state)); - httpReleaseContext(pContext); + httpDebug("context:%p, fd:%d, state:%s, not in ready state, ignore read events", pContext, pContext->fd, + httpContextStateStr(pContext->state)); + httpReleaseContext(pContext, true); continue; } if (pServer->status != HTTP_SERVER_RUNNING) { - httpDebug("context:%p, fd:%d, ip:%s, state:%s, server is not running, accessed:%d, close connect", pContext, - pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); - httpSendErrorResp(pContext, HTTP_SERVER_OFFLINE); + httpDebug("context:%p, fd:%d, state:%s, server is not running, accessed:%d, close connect", pContext, + pContext->fd, httpContextStateStr(pContext->state), pContext->accessTimes); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_SERVER_OFFLINE); httpNotifyContextClose(pContext); } else { if (httpReadData(pContext)) { (*(pThread->processData))(pContext); atomic_fetch_add_32(&pServer->requestNum, 1); + } else { + httpReleaseContext(pContext, false); } } } @@ -258,13 +154,13 @@ static void httpProcessHttpData(void *param) { } static void *httpAcceptHttpConnection(void *arg) { - int connFd = -1; + int32_t connFd = -1; struct sockaddr_in clientAddr; - int threadId = 0; + int32_t threadId = 0; HttpServer * pServer = &tsHttpServer; HttpThread * pThread = NULL; HttpContext * pContext = NULL; - int totalFds = 0; + int32_t totalFds = 0; sigset_t set; sigemptyset(&set); @@ -284,7 +180,7 @@ static void *httpAcceptHttpConnection(void *arg) { while (1) { socklen_t addrlen = sizeof(clientAddr); - connFd = (int)accept(pServer->fd, (struct sockaddr *)&clientAddr, &addrlen); + connFd = (int32_t)accept(pServer->fd, (struct sockaddr *)&clientAddr, &addrlen); if (connFd == -1) { if (errno == EINVAL) { httpDebug("http server:%s socket was shutdown, exiting...", pServer->label); @@ -295,7 +191,7 @@ static void *httpAcceptHttpConnection(void *arg) { } totalFds = 1; - for (int i = 0; i < pServer->numOfThreads; ++i) { + for (int32_t i = 0; i < pServer->numOfThreads; ++i) { totalFds += pServer->pThreads[i].numOfContexts; } @@ -332,7 +228,7 @@ static void *httpAcceptHttpConnection(void *arg) { httpError("context:%p, fd:%d, ip:%s, thread:%s, failed to add http fd for epoll, error:%s", pContext, connFd, pContext->ipstr, pThread->label, strerror(errno)); taosClose(pContext->fd); - httpReleaseContext(pContext); + httpReleaseContext(pContext, true); continue; } @@ -359,7 +255,7 @@ bool httpInitConnect() { } HttpThread *pThread = pServer->pThreads; - for (int i = 0; i < pServer->numOfThreads; ++i) { + for (int32_t i = 0; i < pServer->numOfThreads; ++i) { sprintf(pThread->label, "%s%d", pServer->label, i); pThread->processData = pServer->processData; pThread->threadId = i; @@ -405,3 +301,59 @@ bool httpInitConnect() { pServer->serverPort, pServer->numOfThreads); return true; } + +static bool httpReadData(HttpContext *pContext) { + HttpParser *pParser = pContext->parser; + if (!pParser->inited) { + httpInitParser(pParser); + } + + if (pParser->parsed) { + httpDebug("context:%p, fd:%d, not in ready state, parsed:%d", pContext, pContext->fd, pParser->parsed); + return false; + } + + pContext->accessTimes++; + pContext->lastAccessTime = taosGetTimestampSec(); + + char buf[HTTP_STEP_SIZE + 1] = {0}; + int32_t nread = (int32_t)taosReadSocket(pContext->fd, buf, HTTP_STEP_SIZE); + if (nread > 0) { + buf[nread] = '\0'; + httpTraceL("context:%p, fd:%d, nread:%d content:%s", pContext, pContext->fd, nread, buf); + int32_t ok = httpParseBuf(pParser, buf, nread); + + if (ok) { + httpError("context:%p, fd:%d, parse failed, ret:%d code:%d close connect", pContext, pContext->fd, ok, pParser->parseCode); + httpSendErrorResp(pContext, pParser->parseCode); + httpNotifyContextClose(pContext); + return false; + } + + if (pParser->parseCode) { + httpError("context:%p, fd:%d, parse failed, code:%d close connect", pContext, pContext->fd, pParser->parseCode); + httpSendErrorResp(pContext, pParser->parseCode); + httpNotifyContextClose(pContext); + return false; + } + + if (!pParser->parsed) { + httpTrace("context:%p, fd:%d, read not over yet, len:%d", pContext, pContext->fd, pParser->body.pos); + return false; + } else { + httpDebug("context:%p, fd:%d, totalLen:%d", pContext, pContext->fd, pParser->body.pos); + return true; + } + } else if (nread < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + httpDebug("context:%p, fd:%d, read from socket error:%d, wait another event", pContext, pContext->fd, errno); + return false; // later again + } else { + httpError("context:%p, fd:%d, read from socket error:%d, close connect", pContext, pContext->fd, errno); + return false; + } + } else { + httpError("context:%p, fd:%d, nread:%d, wait another event", pContext, pContext->fd, nread); + return false; + } +} diff --git a/src/plugins/http/src/httpSession.c b/src/plugins/http/src/httpSession.c index f19679e0723cb392dfb78040424b7f7e02913fcc..a96e4433b065885a18b8c0b4f35e2a1925125fc3 100644 --- a/src/plugins/http/src/httpSession.c +++ b/src/plugins/http/src/httpSession.c @@ -16,6 +16,7 @@ #define _DEFAULT_SOURCE #include "os.h" #include "taos.h" +#include "taoserror.h" #include "tglobal.h" #include "tcache.h" #include "httpInt.h" @@ -39,15 +40,15 @@ void httpCreateSession(HttpContext *pContext, void *taos) { // taosCacheRelease(server->sessionCache, (void **)&temp, false); if (pContext->session == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, error:%s", pContext, pContext->fd, pContext->ipstr, pContext->user, - httpMsg[HTTP_SESSION_FULL]); + httpError("context:%p, fd:%d, user:%s, error:%s", pContext, pContext->fd, pContext->user, + tstrerror(TSDB_CODE_HTTP_SESSION_FULL)); taos_close(taos); pthread_mutex_unlock(&server->serverMutex); return; } - httpDebug("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p sessionRef:%d", pContext, pContext->fd, - pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); + httpDebug("context:%p, fd:%d, user:%s, create a new session:%p:%p sessionRef:%d", pContext, pContext->fd, + pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); pthread_mutex_unlock(&server->serverMutex); } @@ -61,11 +62,10 @@ static void httpFetchSessionImp(HttpContext *pContext) { pContext->session = taosCacheAcquireByKey(server->sessionCache, sessionId, len); if (pContext->session != NULL) { atomic_add_fetch_32(&pContext->session->refCount, 1); - httpDebug("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, sessionRef:%d", pContext, pContext->fd, - pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); + httpDebug("context:%p, fd:%d, user:%s, find an exist session:%p:%p, sessionRef:%d", pContext, pContext->fd, + pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); } else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, session not found", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpDebug("context:%p, fd:%d, user:%s, session not found", pContext, pContext->fd, pContext->user); } pthread_mutex_unlock(&server->serverMutex); diff --git a/src/plugins/http/src/httpSql.c b/src/plugins/http/src/httpSql.c index e86db2021a9807c725e71711f478469483920372..881fa55fb7b1b37901930775d9d67012e3debe18 100644 --- a/src/plugins/http/src/httpSql.c +++ b/src/plugins/http/src/httpSql.c @@ -17,6 +17,7 @@ #include "os.h" #include "tnote.h" #include "taos.h" +#include "taoserror.h" #include "tsclient.h" #include "httpInt.h" #include "httpContext.h" @@ -52,18 +53,18 @@ void httpProcessMultiSqlRetrieveCallBackImp(void *param, TAOS_RES *result, int n if (isContinue) { // retrieve next batch of rows - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, continue retrieve, numOfRows:%d, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, numOfRows, sql); + httpDebug("context:%p, fd:%d, user:%s, process pos:%d, continue retrieve, numOfRows:%d, sql:%s", pContext, + pContext->fd, pContext->user, multiCmds->pos, numOfRows, sql); taos_fetch_rows_a(result, httpProcessMultiSqlRetrieveCallBack, param); } else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, stop retrieve, numOfRows:%d, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, numOfRows, sql); + httpDebug("context:%p, fd:%d, user:%s, process pos:%d, stop retrieve, numOfRows:%d, sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos, numOfRows, sql); if (numOfRows < 0) { - httpError("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, retrieve failed code:%s, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, tstrerror(numOfRows), sql); - } - + httpError("context:%p, fd:%d, user:%s, process pos:%d, retrieve failed code:%s, sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos, tstrerror(numOfRows), sql); + } + taos_free_result(result); if (singleCmd->cmdReturnType == HTTP_CMD_RETURN_TYPE_WITH_RETURN && encode->stopJsonFp) { @@ -90,20 +91,20 @@ void httpProcessMultiSqlCallBackImp(void *param, TAOS_RES *result, int code) { char * sql = httpGetCmdsString(pContext, singleCmd->sql); if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { - httpWarn("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, code:%s:inprogress, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, tstrerror(code), sql); + httpWarn("context:%p, fd:%d, user:%s, process pos:%d, code:%s:inprogress, sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos, tstrerror(code), sql); return; } if (code < 0) { if (encode->checkFinishedFp != NULL && !encode->checkFinishedFp(pContext, singleCmd, code)) { singleCmd->code = code; - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process pos jump to:%d, last code:%s, last sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos + 1, tstrerror(code), sql); + httpDebug("context:%p, fd:%d, user:%s, process pos jump to:%d, last code:%s, last sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos + 1, tstrerror(code), sql); } else { singleCmd->code = code; - httpError("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, error code:%s, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, tstrerror(code), sql); + httpError("context:%p, fd:%d, user:%s, process pos:%d, error code:%s, sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos, tstrerror(code), sql); if (singleCmd->cmdReturnType == HTTP_CMD_RETURN_TYPE_WITH_RETURN) { if (encode->startJsonFp) (encode->startJsonFp)(pContext, singleCmd, result); @@ -121,8 +122,8 @@ void httpProcessMultiSqlCallBackImp(void *param, TAOS_RES *result, int code) { if (isUpdate) { // not select or show commands int affectRows = taos_affected_rows(result); - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, affect rows:%d, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, affectRows, sql); + httpDebug("context:%p, fd:%d, user:%s, process pos:%d, affect rows:%d, sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos, affectRows, sql); singleCmd->code = 0; @@ -147,8 +148,8 @@ void httpProcessMultiSqlCallBackImp(void *param, TAOS_RES *result, int code) { taos_free_result(result); httpProcessMultiSql(pContext); } else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, start retrieve, sql:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, sql); + httpDebug("context:%p, fd:%d, user:%s, process pos:%d, start retrieve, sql:%s", pContext, pContext->fd, + pContext->user, multiCmds->pos, sql); if (singleCmd->cmdReturnType == HTTP_CMD_RETURN_TYPE_WITH_RETURN && encode->startJsonFp) { (encode->startJsonFp)(pContext, singleCmd, result); @@ -166,8 +167,8 @@ void httpProcessMultiSql(HttpContext *pContext) { HttpEncodeMethod *encode = pContext->encodeMethod; if (multiCmds->pos >= multiCmds->size) { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, size:%d, stop mulit-querys", - pContext, pContext->fd, pContext->ipstr, pContext->user, multiCmds->pos, multiCmds->size); + httpDebug("context:%p, fd:%d, user:%s, process pos:%d, size:%d, stop mulit-querys", pContext, pContext->fd, + pContext->user, multiCmds->pos, multiCmds->size); if (encode->cleanJsonFp) { (encode->cleanJsonFp)(pContext); } @@ -178,8 +179,8 @@ void httpProcessMultiSql(HttpContext *pContext) { HttpSqlCmd *cmd = multiCmds->cmds + multiCmds->pos; char *sql = httpGetCmdsString(pContext, cmd->sql); - httpTraceL("context:%p, fd:%d, ip:%s, user:%s, process pos:%d, start query, sql:%s", pContext, pContext->fd, - pContext->ipstr, pContext->user, multiCmds->pos, sql); + httpTraceL("context:%p, fd:%d, user:%s, process pos:%d, start query, sql:%s", pContext, pContext->fd, pContext->user, + multiCmds->pos, sql); taosNotePrintHttp(sql); taos_query_a(pContext->session->taos, sql, httpProcessMultiSqlCallBack, (void *)pContext); } @@ -189,12 +190,12 @@ void httpProcessMultiSqlCmd(HttpContext *pContext) { HttpSqlCmds *multiCmds = pContext->multiCmds; if (multiCmds == NULL || multiCmds->size <= 0 || multiCmds->pos >= multiCmds->size || multiCmds->pos < 0) { - httpSendErrorResp(pContext, HTTP_INVALID_MULTI_REQUEST); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_INVALID_MULTI_REQUEST); return; } - httpDebug("context:%p, fd:%d, ip:%s, user:%s, start multi-querys pos:%d, size:%d", pContext, pContext->fd, - pContext->ipstr, pContext->user, multiCmds->pos, multiCmds->size); + httpDebug("context:%p, fd:%d, user:%s, start multi-querys pos:%d, size:%d", pContext, pContext->fd, pContext->user, + multiCmds->pos, multiCmds->size); HttpEncodeMethod *encode = pContext->encodeMethod; if (encode->initJsonFp) { (encode->initJsonFp)(pContext); @@ -221,16 +222,16 @@ void httpProcessSingleSqlRetrieveCallBackImp(void *param, TAOS_RES *result, int if (isContinue) { // retrieve next batch of rows - httpDebug("context:%p, fd:%d, ip:%s, user:%s, continue retrieve, numOfRows:%d", pContext, pContext->fd, - pContext->ipstr, pContext->user, numOfRows); + httpDebug("context:%p, fd:%d, user:%s, continue retrieve, numOfRows:%d", pContext, pContext->fd, pContext->user, + numOfRows); taos_fetch_rows_a(result, httpProcessSingleSqlRetrieveCallBack, param); } else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, stop retrieve, numOfRows:%d", pContext, pContext->fd, pContext->ipstr, - pContext->user, numOfRows); + httpDebug("context:%p, fd:%d, user:%s, stop retrieve, numOfRows:%d", pContext, pContext->fd, pContext->user, + numOfRows); if (numOfRows < 0) { - httpError("context:%p, fd:%d, ip:%s, user:%s, retrieve failed, code:%s", pContext, pContext->fd, pContext->ipstr, - pContext->user, tstrerror(numOfRows)); + httpError("context:%p, fd:%d, user:%s, retrieve failed, code:%s", pContext, pContext->fd, pContext->user, + tstrerror(numOfRows)); } taos_free_result(result); @@ -256,21 +257,21 @@ void httpProcessSingleSqlCallBackImp(void *param, TAOS_RES *result, int unUsedCo HttpEncodeMethod *encode = pContext->encodeMethod; if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { - httpError("context:%p, fd:%d, ip:%s, user:%s, query error, taos:%p, code:%s:inprogress, sqlObj:%p", - pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session->taos, tstrerror(code), (SSqlObj *)result); + httpError("context:%p, fd:%d, user:%s, query error, taos:%p, code:%s:inprogress, sqlObj:%p", pContext, pContext->fd, + pContext->user, pContext->session->taos, tstrerror(code), (SSqlObj *)result); return; } if (code < 0) { SSqlObj *pObj = (SSqlObj *)result; if (code == TSDB_CODE_TSC_INVALID_SQL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, query error, taos:%p, code:%s, sqlObj:%p, error:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session->taos, tstrerror(code), pObj, pObj->cmd.payload); + httpError("context:%p, fd:%d, user:%s, query error, taos:%p, code:%s, sqlObj:%p, error:%s", pContext, + pContext->fd, pContext->user, pContext->session->taos, tstrerror(code), pObj, pObj->cmd.payload); httpSendTaosdInvalidSqlErrorResp(pContext, pObj->cmd.payload); } else { - httpError("context:%p, fd:%d, ip:%s, user:%s, query error, taos:%p, code:%s, sqlObj:%p", - pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session->taos, tstrerror(code), pObj); - httpSendTaosdErrorResp(pContext, code); + httpError("context:%p, fd:%d, user:%s, query error, taos:%p, code:%s, sqlObj:%p", pContext, pContext->fd, + pContext->user, pContext->session->taos, tstrerror(code), pObj); + httpSendErrorResp(pContext, code); } taos_free_result(result); return; @@ -281,8 +282,8 @@ void httpProcessSingleSqlCallBackImp(void *param, TAOS_RES *result, int unUsedCo // not select or show commands int affectRows = taos_affected_rows(result); - httpDebug("context:%p, fd:%d, ip:%s, user:%s, affect rows:%d, stop query, sqlObj:%p", - pContext, pContext->fd, pContext->ipstr, pContext->user, affectRows, result); + httpDebug("context:%p, fd:%d, user:%s, affect rows:%d, stop query, sqlObj:%p", pContext, pContext->fd, + pContext->user, affectRows, result); if (encode->startJsonFp) { (encode->startJsonFp)(pContext, &pContext->singleCmd, result); @@ -299,8 +300,7 @@ void httpProcessSingleSqlCallBackImp(void *param, TAOS_RES *result, int unUsedCo taos_free_result(result); httpCloseContextByApp(pContext); } else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, start retrieve", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpDebug("context:%p, fd:%d, user:%s, start retrieve", pContext, pContext->fd, pContext->user); if (encode->startJsonFp) { (encode->startJsonFp)(pContext, &pContext->singleCmd, result); @@ -320,25 +320,23 @@ void httpProcessSingleSqlCmd(HttpContext *pContext) { HttpSession *pSession = pContext->session; if (sql == NULL || sql[0] == 0) { - httpError("context:%p, fd:%d, ip:%s, user:%s, error:no sql input", pContext, pContext->fd, pContext->ipstr, - pContext->user); - httpSendErrorResp(pContext, HTTP_NO_SQL_INPUT); + httpError("context:%p, fd:%d, user:%s, error:no sql input", pContext, pContext->fd, pContext->user); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_SQL_INPUT); return; } - httpTraceL("context:%p, fd:%d, ip:%s, user:%s, start query, sql:%s", pContext, pContext->fd, pContext->ipstr, - pContext->user, sql); + httpTraceL("context:%p, fd:%d, user:%s, start query, sql:%s", pContext, pContext->fd, pContext->user, sql); taosNotePrintHttp(sql); taos_query_a(pSession->taos, sql, httpProcessSingleSqlCallBack, (void *)pContext); } void httpProcessLoginCmd(HttpContext *pContext) { char token[128] = {0}; - if (!httpGenTaosdAuthToken(pContext, token, 128)) { - httpSendErrorResp(pContext, HTTP_GEN_TAOSD_TOKEN_ERR); + if (httpGenTaosdAuthToken(pContext, token, 128) != 0) { + httpSendErrorResp(pContext, TSDB_CODE_HTTP_GEN_TAOSD_TOKEN_ERR); } else { - httpDebug("context:%p, fd:%d, ip:%s, user:%s, login via http, return token:%s", - pContext, pContext->fd, pContext->ipstr, pContext->user, token); + httpDebug("context:%p, fd:%d, user:%s, login via http, return token:%s", pContext, pContext->fd, pContext->user, + token); httpSendSuccResp(pContext, token); } } @@ -384,25 +382,24 @@ void httpProcessRequestCb(void *param, TAOS_RES *result, int code) { if (pContext == NULL) return; if (code < 0) { - httpError("context:%p, fd:%d, ip:%s, user:%s, login error, code:%s", pContext, pContext->fd, pContext->ipstr, - pContext->user, tstrerror(code)); - httpSendTaosdErrorResp(pContext, code); + httpError("context:%p, fd:%d, user:%s, login error, code:%s", pContext, pContext->fd, pContext->user, + tstrerror(code)); + httpSendErrorResp(pContext, code); return; } - httpDebug("context:%p, fd:%d, ip:%s, user:%s, connect tdengine success, taos:%p", pContext, pContext->fd, - pContext->ipstr, pContext->user, pContext->taos); + httpDebug("context:%p, fd:%d, user:%s, connect tdengine success, taos:%p", pContext, pContext->fd, pContext->user, + pContext->taos); if (pContext->taos == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, login error, taos is empty", pContext, pContext->fd, pContext->ipstr, - pContext->user); - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_SESSIONS); + httpError("context:%p, fd:%d, user:%s, login error, taos is empty", pContext, pContext->fd, pContext->user); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_LOGIN_FAILED); return; } httpCreateSession(pContext, pContext->taos); if (pContext->session == NULL) { - httpSendErrorResp(pContext, HTTP_SESSION_FULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_SESSION_FULL); httpCloseContextByApp(pContext); } else { httpExecCmd(pContext); @@ -415,8 +412,8 @@ void httpProcessRequest(HttpContext *pContext) { if (pContext->session == NULL || pContext->reqType == HTTP_REQTYPE_LOGIN) { taos_connect_a(NULL, pContext->user, pContext->pass, "", 0, httpProcessRequestCb, (void *)pContext, &(pContext->taos)); - httpDebug("context:%p, fd:%d, ip:%s, user:%s, try connect tdengine, taos:%p", pContext, pContext->fd, - pContext->ipstr, pContext->user, pContext->taos); + httpDebug("context:%p, fd:%d, user:%s, try connect tdengine, taos:%p", pContext, pContext->fd, pContext->user, + pContext->taos); } else { httpExecCmd(pContext); } diff --git a/src/plugins/http/src/httpSystem.c b/src/plugins/http/src/httpSystem.c index e51c8dd4f773397862483d9284e765a51d49c923..8993b233dd1dde9283679d337845d42f5d649715 100644 --- a/src/plugins/http/src/httpSystem.c +++ b/src/plugins/http/src/httpSystem.c @@ -27,9 +27,9 @@ #include "httpResp.h" #include "httpHandle.h" #include "httpQueue.h" -#include "gcHandle.h" -#include "restHandle.h" -#include "tgHandle.h" +#include "httpGcHandle.h" +#include "httpRestHandle.h" +#include "httpTgHandle.h" #ifndef _ADMIN void adminInitHandle(HttpServer* pServer) {} @@ -37,9 +37,9 @@ void opInitHandle(HttpServer* pServer) {} #endif HttpServer tsHttpServer; -void taosInitNote(int numOfNoteLines, int maxNotes, char* lable); +void taosInitNote(int32_t numOfNoteLines, int32_t maxNotes, char* lable); -int httpInitSystem() { +int32_t httpInitSystem() { strcpy(tsHttpServer.label, "rest"); tsHttpServer.serverIp = 0; tsHttpServer.serverPort = tsHttpPort; @@ -60,7 +60,7 @@ int httpInitSystem() { return 0; } -int httpStartSystem() { +int32_t httpStartSystem() { httpInfo("start http server ..."); if (tsHttpServer.status != HTTP_SERVER_INIT) { diff --git a/src/plugins/http/src/tgHandle.c b/src/plugins/http/src/httpTgHandle.c similarity index 79% rename from src/plugins/http/src/tgHandle.c rename to src/plugins/http/src/httpTgHandle.c index 48c66c4c07905a5c5ea6ef609ba7ccb3ed7615ca..e2b57b87bb3a10ee50edbf55ae2590289f940bf6 100644 --- a/src/plugins/http/src/tgHandle.c +++ b/src/plugins/http/src/httpTgHandle.c @@ -19,8 +19,8 @@ #include "taosdef.h" #include "taosmsg.h" #include "httpInt.h" -#include "tgHandle.h" -#include "tgJson.h" +#include "httpTgHandle.h" +#include "httpTgJson.h" #include "cJSON.h" /* @@ -83,16 +83,16 @@ static const char DEFAULT_TELEGRAF_CFG[] = "]}"; typedef struct { - char *name; - char *tbName; - char **fields; - int fieldNum; + char * name; + char * tbName; + char ** fields; + int32_t fieldNum; } STgSchema; typedef struct { STgSchema *schemas; - int size; - int pos; + int32_t size; + int32_t pos; } STgSchemas; static STgSchemas tgSchemas = {0}; @@ -107,7 +107,7 @@ void tgFreeSchema(STgSchema *schema) { schema->tbName = NULL; } if (schema->fields != NULL) { - for (int f = 0; f < schema->fieldNum; ++f) { + for (int32_t f = 0; f < schema->fieldNum; ++f) { if (schema->fields[f] != NULL) { free(schema->fields[f]); schema->fields[f] = NULL; @@ -121,7 +121,7 @@ void tgFreeSchema(STgSchema *schema) { void tgFreeSchemas() { if (tgSchemas.schemas != NULL) { - for (int s = 0; s < tgSchemas.size; ++s) { + for (int32_t s = 0; s < tgSchemas.size; ++s) { tgFreeSchema(&tgSchemas.schemas[s]); } free(tgSchemas.schemas); @@ -130,7 +130,7 @@ void tgFreeSchemas() { } } -void tgInitSchemas(int size) { +void tgInitSchemas(int32_t size) { tgFreeSchemas(); tgSchemas.schemas = calloc(sizeof(STgSchema), size); tgSchemas.size = 0; @@ -154,7 +154,7 @@ void tgParseSchemaMetric(cJSON *metric) { parsedOk = false; goto ParseEnd; } - int nameLen = (int)strlen(name->valuestring); + int32_t nameLen = (int32_t)strlen(name->valuestring); if (nameLen == 0) { parsedOk = false; goto ParseEnd; @@ -177,7 +177,7 @@ void tgParseSchemaMetric(cJSON *metric) { parsedOk = false; goto ParseEnd; } - int tbnameLen = (int)strlen(tbname->valuestring); + int32_t tbnameLen = (int32_t)strlen(tbname->valuestring); if (tbnameLen == 0) { parsedOk = false; goto ParseEnd; @@ -191,7 +191,7 @@ void tgParseSchemaMetric(cJSON *metric) { if (fields == NULL) { goto ParseEnd; } - int fieldSize = cJSON_GetArraySize(fields); + int32_t fieldSize = cJSON_GetArraySize(fields); if (fieldSize <= 0 || fieldSize > TSDB_MAX_COLUMNS) { goto ParseEnd; } @@ -199,7 +199,7 @@ void tgParseSchemaMetric(cJSON *metric) { if (fieldSize > 0) { schema.fields = calloc(sizeof(STgSchema), (size_t)fieldSize); schema.fieldNum = fieldSize; - for (int i = 0; i < fieldSize; i++) { + for (int32_t i = 0; i < fieldSize; i++) { cJSON *field = cJSON_GetArrayItem(fields, i); if (field == NULL) { parsedOk = false; @@ -209,7 +209,7 @@ void tgParseSchemaMetric(cJSON *metric) { parsedOk = false; goto ParseEnd; } - int nameLen = (int)strlen(field->valuestring); + int32_t nameLen = (int32_t)strlen(field->valuestring); if (nameLen == 0 || nameLen >= TSDB_TABLE_NAME_LEN) { parsedOk = false; goto ParseEnd; @@ -227,13 +227,13 @@ ParseEnd: } } -int tgParseSchema(const char *content, char*fileName) { +int32_t tgParseSchema(const char *content, char*fileName) { cJSON *root = cJSON_Parse(content); if (root == NULL) { httpError("failed to parse telegraf schema file:%s, invalid json format, content:%s", fileName, content); return -1; } - int size = 0; + int32_t size = 0; cJSON *metrics = cJSON_GetObjectItem(root, "metrics"); if (metrics != NULL) { size = cJSON_GetArraySize(metrics); @@ -244,7 +244,7 @@ int tgParseSchema(const char *content, char*fileName) { } tgInitSchemas(size); - for (int i = 0; i < size; i++) { + for (int32_t i = 0; i < size; i++) { cJSON *metric = cJSON_GetArrayItem(metrics, i); if (metric != NULL) { tgParseSchemaMetric(metric); @@ -260,7 +260,7 @@ int tgParseSchema(const char *content, char*fileName) { return size; } -int tgReadSchema(char *fileName) { +int32_t tgReadSchema(char *fileName) { FILE *fp = fopen(fileName, "r"); if (fp == NULL) { return -1; @@ -286,7 +286,7 @@ int tgReadSchema(char *fileName) { } content[contentSize] = 0; - int schemaNum = tgParseSchema(content, fileName); + int32_t schemaNum = tgParseSchema(content, fileName); free(content); fclose(fp); @@ -313,53 +313,53 @@ void tgCleanupHandle() { } bool tgGetUserFromUrl(HttpContext *pContext) { - HttpParser *pParser = &pContext->parser; - if (pParser->path[TG_USER_URL_POS].len >= TSDB_USER_LEN || pParser->path[TG_USER_URL_POS].len <= 0) { + HttpParser *pParser = pContext->parser; + if (pParser->path[TG_USER_URL_POS].pos >= TSDB_USER_LEN || pParser->path[TG_USER_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->user, pParser->path[TG_USER_URL_POS].pos, sizeof(pContext->user)); + tstrncpy(pContext->user, pParser->path[TG_USER_URL_POS].str, sizeof(pContext->user)); return true; } bool tgGetPassFromUrl(HttpContext *pContext) { - HttpParser *pParser = &pContext->parser; - if (pParser->path[TG_PASS_URL_POS].len >= TSDB_PASSWORD_LEN || pParser->path[TG_PASS_URL_POS].len <= 0) { + HttpParser *pParser = pContext->parser; + if (pParser->path[TG_PASS_URL_POS].pos >= TSDB_PASSWORD_LEN || pParser->path[TG_PASS_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->pass, pParser->path[TG_PASS_URL_POS].pos, sizeof(pContext->pass)); + tstrncpy(pContext->pass, pParser->path[TG_PASS_URL_POS].str, sizeof(pContext->pass)); return true; } char *tgGetDbFromUrl(HttpContext *pContext) { - HttpParser *pParser = &pContext->parser; - if (pParser->path[TG_DB_URL_POS].len <= 0) { - httpSendErrorResp(pContext, HTTP_TG_DB_NOT_INPUT); + HttpParser *pParser = pContext->parser; + if (pParser->path[TG_DB_URL_POS].pos <= 0) { + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_DB_NOT_INPUT); return NULL; } - if (pParser->path[TG_DB_URL_POS].len >= TSDB_DB_NAME_LEN) { - httpSendErrorResp(pContext, HTTP_TG_DB_TOO_LONG); + if (pParser->path[TG_DB_URL_POS].pos >= TSDB_DB_NAME_LEN) { + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_DB_TOO_LONG); return NULL; } - return pParser->path[TG_DB_URL_POS].pos; + return pParser->path[TG_DB_URL_POS].str; } -char *tgGetStableName(char *stname, cJSON *fields, int fieldsSize) { - for (int s = 0; s < tgSchemas.size; ++s) { +char *tgGetStableName(char *stname, cJSON *fields, int32_t fieldsSize) { + for (int32_t s = 0; s < tgSchemas.size; ++s) { STgSchema *schema = &tgSchemas.schemas[s]; if (strcasecmp(schema->name, stname) != 0) { continue; } bool schemaMatched = true; - for (int f = 0; f < schema->fieldNum; ++f) { + for (int32_t f = 0; f < schema->fieldNum; ++f) { char *fieldName = schema->fields[f]; bool fieldMatched = false; - for (int i = 0; i < fieldsSize; i++) { + for (int32_t i = 0; i < fieldsSize; i++) { cJSON *field = cJSON_GetArrayItem(fields, i); if (strcasecmp(field->string, fieldName) == 0) { fieldMatched = true; @@ -401,70 +401,70 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { // metric name cJSON *name = cJSON_GetObjectItem(metric, "name"); if (name == NULL) { - httpSendErrorResp(pContext, HTTP_TG_METRIC_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRIC_NULL); return false; } if (name->type != cJSON_String) { - httpSendErrorResp(pContext, HTTP_TG_METRIC_TYPE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRIC_TYPE); return false; } if (name->valuestring == NULL) { - httpSendErrorResp(pContext, HTTP_TG_METRIC_NAME_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRIC_NAME_NULL); return false; } - int nameLen = (int)strlen(name->valuestring); + int32_t nameLen = (int32_t)strlen(name->valuestring); if (nameLen == 0) { - httpSendErrorResp(pContext, HTTP_TG_METRIC_NAME_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRIC_NAME_NULL); return false; } if (nameLen >= TSDB_TABLE_NAME_LEN - 8) { - httpSendErrorResp(pContext, HTTP_TG_METRIC_NAME_LONG); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRIC_NAME_LONG); return false; } // timestamp cJSON *timestamp = cJSON_GetObjectItem(metric, "timestamp"); if (timestamp == NULL) { - httpSendErrorResp(pContext, HTTP_TG_TIMESTAMP_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TIMESTAMP_NULL); return false; } if (timestamp->type != cJSON_Number) { - httpSendErrorResp(pContext, HTTP_TG_TIMESTAMP_TYPE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TIMESTAMP_TYPE); return false; } if (timestamp->valueint <= 0) { - httpSendErrorResp(pContext, HTTP_TG_TIMESTAMP_VAL_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TIMESTAMP_VAL_NULL); return false; } // tags cJSON *tags = cJSON_GetObjectItem(metric, "tags"); if (tags == NULL) { - httpSendErrorResp(pContext, HTTP_TG_TAGS_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAGS_NULL); return false; } - int tagsSize = cJSON_GetArraySize(tags); + int32_t tagsSize = cJSON_GetArraySize(tags); if (tagsSize <= 0) { - httpSendErrorResp(pContext, HTTP_TG_TAGS_SIZE_0); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAGS_SIZE_0); return false; } if (tagsSize > TG_MAX_SORT_TAG_SIZE) { - httpSendErrorResp(pContext, HTTP_TG_TAGS_SIZE_LONG); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAGS_SIZE_LONG); return false; } cJSON *host = NULL; - for (int i = 0; i < tagsSize; i++) { + for (int32_t i = 0; i < tagsSize; i++) { cJSON *tag = cJSON_GetArrayItem(tags, i); if (tag == NULL) { - httpSendErrorResp(pContext, HTTP_TG_TAG_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAG_NULL); return false; } if (tag->string == NULL || strlen(tag->string) == 0) { - httpSendErrorResp(pContext, HTTP_TG_TAG_NAME_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAG_NAME_NULL); return false; } @@ -474,19 +474,19 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { */ if (0) { if (strlen(tag->string) >= TSDB_COL_NAME_LEN) { - httpSendErrorResp(pContext, HTTP_TG_TAG_NAME_SIZE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAG_NAME_SIZE); return false; } } if (tag->type != cJSON_Number && tag->type != cJSON_String) { - httpSendErrorResp(pContext, HTTP_TG_TAG_VALUE_TYPE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAG_VALUE_TYPE); return false; } if (tag->type == cJSON_String) { if (tag->valuestring == NULL || strlen(tag->valuestring) == 0) { - httpSendErrorResp(pContext, HTTP_TG_TAG_VALUE_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TAG_VALUE_NULL); return false; } } @@ -497,46 +497,46 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { } if (host == NULL) { - httpSendErrorResp(pContext, HTTP_TG_TABLE_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TABLE_NULL); return false; } if (host->type != cJSON_String) { - httpSendErrorResp(pContext, HTTP_TG_HOST_NOT_STRING); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_HOST_NOT_STRING); return false; } if (strlen(host->valuestring) >= TSDB_TABLE_NAME_LEN - 1) { - httpSendErrorResp(pContext, HTTP_TG_TABLE_SIZE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_TABLE_SIZE); return false; } // fields cJSON *fields = cJSON_GetObjectItem(metric, "fields"); if (fields == NULL) { - httpSendErrorResp(pContext, HTTP_TG_FIELDS_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELDS_NULL); return false; } - int fieldsSize = cJSON_GetArraySize(fields); + int32_t fieldsSize = cJSON_GetArraySize(fields); if (fieldsSize <= 0) { - httpSendErrorResp(pContext, HTTP_TG_FIELDS_SIZE_0); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELDS_SIZE_0); return false; } if (fieldsSize > (TSDB_MAX_COLUMNS - TSDB_MAX_TAGS - 1)) { - httpSendErrorResp(pContext, HTTP_TG_FIELDS_SIZE_LONG); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELDS_SIZE_LONG); return false; } - for (int i = 0; i < fieldsSize; i++) { + for (int32_t i = 0; i < fieldsSize; i++) { cJSON *field = cJSON_GetArrayItem(fields, i); if (field == NULL) { - httpSendErrorResp(pContext, HTTP_TG_FIELD_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELD_NULL); return false; } if (field->string == NULL || strlen(field->string) == 0) { - httpSendErrorResp(pContext, HTTP_TG_FIELD_NAME_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELD_NAME_NULL); return false; } /* @@ -545,17 +545,17 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { */ if (0) { if (strlen(field->string) >= TSDB_COL_NAME_LEN) { - httpSendErrorResp(pContext, HTTP_TG_FIELD_NAME_SIZE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELD_NAME_SIZE); return false; } } if (field->type != cJSON_Number && field->type != cJSON_String) { - httpSendErrorResp(pContext, HTTP_TG_FIELD_VALUE_TYPE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELD_VALUE_TYPE); return false; } if (field->type == cJSON_String) { if (field->valuestring == NULL || strlen(field->valuestring) == 0) { - httpSendErrorResp(pContext, HTTP_TG_FIELD_VALUE_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_FIELD_VALUE_NULL); return false; } } @@ -564,7 +564,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { // assembling cmds HttpSqlCmd *stable_cmd = httpNewSqlCmd(pContext); if (stable_cmd == NULL) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); return false; } stable_cmd->cmdType = HTTP_CMD_TYPE_CREATE_STBALE; @@ -572,18 +572,18 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { HttpSqlCmd *table_cmd = httpNewSqlCmd(pContext); if (table_cmd == NULL) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); return false; } table_cmd->cmdType = HTTP_CMD_TYPE_INSERT; // order by tag name cJSON *orderedTags[TG_MAX_SORT_TAG_SIZE] = {0}; - int orderTagsLen = 0; - for (int i = 0; i < tagsSize; ++i) { + int32_t orderTagsLen = 0; + for (int32_t i = 0; i < tagsSize; ++i) { cJSON *tag = cJSON_GetArrayItem(tags, i); orderedTags[orderTagsLen++] = tag; - for (int j = orderTagsLen - 1; j >= 1; --j) { + for (int32_t j = orderTagsLen - 1; j >= 1; --j) { cJSON *tag1 = orderedTags[j]; cJSON *tag2 = orderedTags[j - 1]; if (strcasecmp(tag1->string, "host") == 0 || strcmp(tag1->string, tag2->string) < 0) { @@ -609,7 +609,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { httpShrinkTableName(pContext, table_cmd->stable, httpGetCmdsString(pContext, table_cmd->stable)); // stable tag for detail - for (int i = 0; i < orderTagsLen; ++i) { + for (int32_t i = 0; i < orderTagsLen; ++i) { cJSON *tag = orderedTags[i]; stable_cmd->tagNames[i] = table_cmd->tagNames[i] = httpAddToSqlCmdBuffer(pContext, tag->string); @@ -631,7 +631,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { } else { table_cmd->table = stable_cmd->table = httpAddToSqlCmdBufferNoTerminal(pContext, "%s_%d_%d_%s", stname, fieldsSize, orderTagsLen, host->valuestring); } - for (int i = 0; i < orderTagsLen; ++i) { + for (int32_t i = 0; i < orderTagsLen; ++i) { cJSON *tag = orderedTags[i]; if (tag == host) continue; if (tag->type == cJSON_String) @@ -653,7 +653,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { // assembling create stable sql stable_cmd->sql = httpAddToSqlCmdBufferNoTerminal(pContext, "create table if not exists %s.%s(ts timestamp", db, httpGetCmdsString(pContext, table_cmd->stable)); - for (int i = 0; i < fieldsSize; ++i) { + for (int32_t i = 0; i < fieldsSize; ++i) { cJSON *field = cJSON_GetArrayItem(fields, i); char * field_type = "double"; if (field->type == cJSON_String) @@ -668,7 +668,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { } httpAddToSqlCmdBufferNoTerminal(pContext, ") tags("); - for (int i = 0; i < orderTagsLen; ++i) { + for (int32_t i = 0; i < orderTagsLen; ++i) { cJSON *tag = orderedTags[i]; char * tag_type = "bigint"; if (tag->type == cJSON_String) @@ -689,7 +689,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { table_cmd->sql = httpAddToSqlCmdBufferNoTerminal(pContext, "import into %s.%s using %s.%s tags(", db, httpGetCmdsString(pContext, table_cmd->table), db, httpGetCmdsString(pContext, table_cmd->stable)); - for (int i = 0; i < orderTagsLen; ++i) { + for (int32_t i = 0; i < orderTagsLen; ++i) { cJSON *tag = orderedTags[i]; if (i != orderTagsLen - 1) { if (tag->type == cJSON_Number) @@ -719,7 +719,7 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { } httpAddToSqlCmdBufferNoTerminal(pContext, " values(%" PRId64 ",", timestamp->valueint); - for (int i = 0; i < fieldsSize; ++i) { + for (int32_t i = 0; i < fieldsSize; ++i) { cJSON *field = cJSON_GetArrayItem(fields, i); if (i != fieldsSize - 1) { if (field->type == cJSON_Number) @@ -800,48 +800,46 @@ bool tgProcessSingleMetric(HttpContext *pContext, cJSON *metric, char *db) { } */ bool tgProcessQueryRequest(HttpContext *pContext, char *db) { - httpDebug("context:%p, fd:%d, ip:%s, process telegraf query msg", pContext, pContext->fd, pContext->ipstr); + httpDebug("context:%p, fd:%d, process telegraf query msg", pContext, pContext->fd); - HttpParser *pParser = &pContext->parser; - char * filter = pParser->data.pos; + char *filter = pContext->parser->body.str; if (filter == NULL) { - httpSendErrorResp(pContext, HTTP_NO_MSG_INPUT); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_MSG_INPUT); return false; } cJSON *root = cJSON_Parse(filter); if (root == NULL) { - httpSendErrorResp(pContext, HTTP_TG_INVALID_JSON); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_INVALID_JSON); return false; } cJSON *metrics = cJSON_GetObjectItem(root, "metrics"); if (metrics != NULL) { - int size = cJSON_GetArraySize(metrics); - httpDebug("context:%p, fd:%d, ip:%s, multiple metrics:%d at one time", pContext, pContext->fd, pContext->ipstr, - size); + int32_t size = cJSON_GetArraySize(metrics); + httpDebug("context:%p, fd:%d, multiple metrics:%d at one time", pContext, pContext->fd, size); if (size <= 0) { - httpSendErrorResp(pContext, HTTP_TG_METRICS_NULL); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRICS_NULL); cJSON_Delete(root); return false; } - int cmdSize = size * 2 + 1; + int32_t cmdSize = size * 2 + 1; if (cmdSize > HTTP_MAX_CMD_SIZE) { - httpSendErrorResp(pContext, HTTP_TG_METRICS_SIZE); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_TG_METRICS_SIZE); cJSON_Delete(root); return false; } if (!httpMallocMultiCmds(pContext, cmdSize, HTTP_BUFFER_SIZE)) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); cJSON_Delete(root); return false; } HttpSqlCmd *cmd = httpNewSqlCmd(pContext); if (cmd == NULL) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); cJSON_Delete(root); return false; } @@ -849,7 +847,7 @@ bool tgProcessQueryRequest(HttpContext *pContext, char *db) { cmd->cmdReturnType = HTTP_CMD_RETURN_TYPE_NO_RETURN; cmd->sql = httpAddToSqlCmdBuffer(pContext, "create database if not exists %s", db); - for (int i = 0; i < size; i++) { + for (int32_t i = 0; i < size; i++) { cJSON *metric = cJSON_GetArrayItem(metrics, i); if (metric != NULL) { if (!tgProcessSingleMetric(pContext, metric, db)) { @@ -859,17 +857,17 @@ bool tgProcessQueryRequest(HttpContext *pContext, char *db) { } } } else { - httpDebug("context:%p, fd:%d, ip:%s, single metric", pContext, pContext->fd, pContext->ipstr); + httpDebug("context:%p, fd:%d, single metric", pContext, pContext->fd); if (!httpMallocMultiCmds(pContext, 3, HTTP_BUFFER_SIZE)) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); cJSON_Delete(root); return false; } HttpSqlCmd *cmd = httpNewSqlCmd(pContext); if (cmd == NULL) { - httpSendErrorResp(pContext, HTTP_NO_ENOUGH_MEMORY); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_ENOUGH_MEMORY); cJSON_Delete(root); return false; } @@ -894,7 +892,7 @@ bool tgProcessQueryRequest(HttpContext *pContext, char *db) { bool tgProcessRquest(struct HttpContext *pContext) { if (strlen(pContext->user) == 0 || strlen(pContext->pass) == 0) { - httpSendErrorResp(pContext, HTTP_PARSE_USR_ERROR); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_NO_AUTH_INFO); return false; } diff --git a/src/plugins/http/src/tgJson.c b/src/plugins/http/src/httpTgJson.c similarity index 73% rename from src/plugins/http/src/tgJson.c rename to src/plugins/http/src/httpTgJson.c index ed4ee0d7de0acbb88e5eb20937fa96984b2e68dc..603092f09df96ae9bc9be2c0c4445d3d3f795ea1 100644 --- a/src/plugins/http/src/tgJson.c +++ b/src/plugins/http/src/httpTgJson.c @@ -19,8 +19,8 @@ #include "httpLog.h" #include "httpJson.h" #include "httpResp.h" -#include "tgHandle.h" -#include "tgJson.h" +#include "httpTgHandle.h" +#include "httpTgJson.h" void tgInitQueryJson(HttpContext *pContext) { JsonBuf *jsonBuf = httpMallocJsonBuf(pContext); @@ -61,19 +61,19 @@ void tgStartQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result) // data httpJsonItemToken(jsonBuf); httpJsonPair(jsonBuf, "metric", 6, httpGetCmdsString(pContext, cmd->stable), - (int)strlen(httpGetCmdsString(pContext, cmd->metric))); + (int32_t)strlen(httpGetCmdsString(pContext, cmd->metric))); httpJsonItemToken(jsonBuf); httpJsonPair(jsonBuf, "stable", 6, httpGetCmdsString(pContext, cmd->stable), - (int)strlen(httpGetCmdsString(pContext, cmd->stable))); + (int32_t)strlen(httpGetCmdsString(pContext, cmd->stable))); httpJsonItemToken(jsonBuf); httpJsonPair(jsonBuf, "table", 5, httpGetCmdsString(pContext, cmd->table), - (int)strlen(httpGetCmdsString(pContext, cmd->table))); + (int32_t)strlen(httpGetCmdsString(pContext, cmd->table))); httpJsonItemToken(jsonBuf); httpJsonPair(jsonBuf, "timestamp", 9, httpGetCmdsString(pContext, cmd->timestamp), - (int)strlen(httpGetCmdsString(pContext, cmd->timestamp))); // hack way + (int32_t)strlen(httpGetCmdsString(pContext, cmd->timestamp))); // hack way } void tgStopQueryJson(HttpContext *pContext, HttpSqlCmd *cmd) { @@ -88,7 +88,7 @@ void tgStopQueryJson(HttpContext *pContext, HttpSqlCmd *cmd) { httpJsonToken(jsonBuf, JsonObjEnd); } -void tgBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int affect_rows) { +void tgBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int32_t affect_rows) { JsonBuf *jsonBuf = httpMallocJsonBuf(pContext); if (jsonBuf == NULL) return; @@ -96,10 +96,10 @@ void tgBuildSqlAffectRowsJson(HttpContext *pContext, HttpSqlCmd *cmd, int affect httpJsonPairIntVal(jsonBuf, "affected_rows", 13, affect_rows); } -bool tgCheckFinished(struct HttpContext *pContext, HttpSqlCmd *cmd, int code) { +bool tgCheckFinished(struct HttpContext *pContext, HttpSqlCmd *cmd, int32_t code) { HttpSqlCmds *multiCmds = pContext->multiCmds; - httpDebug("context:%p, fd:%d, ip:%s, check telegraf command, code:%s, state:%d, type:%d, rettype:%d, tags:%d", - pContext, pContext->fd, pContext->ipstr, tstrerror(code), cmd->cmdState, cmd->cmdType, cmd->cmdReturnType, cmd->tagNum); + httpDebug("context:%p, fd:%d, check telegraf command, code:%s, state:%d, type:%d, rettype:%d, tags:%d", pContext, + pContext->fd, tstrerror(code), cmd->cmdState, cmd->cmdType, cmd->cmdReturnType, cmd->tagNum); if (cmd->cmdType == HTTP_CMD_TYPE_INSERT) { if (cmd->cmdState == HTTP_CMD_STATE_NOT_RUN_YET) { @@ -107,16 +107,14 @@ bool tgCheckFinished(struct HttpContext *pContext, HttpSqlCmd *cmd, int code) { cmd->cmdState = HTTP_CMD_STATE_RUN_FINISHED; if (multiCmds->cmds[0].cmdState == HTTP_CMD_STATE_NOT_RUN_YET) { multiCmds->pos = (int16_t)-1; - httpDebug("context:%p, fd:%d, ip:%s, import failed, try create database", pContext, pContext->fd, - pContext->ipstr); + httpDebug("context:%p, fd:%d, import failed, try create database", pContext, pContext->fd); return false; } } else if (code == TSDB_CODE_MND_INVALID_TABLE_NAME) { cmd->cmdState = HTTP_CMD_STATE_RUN_FINISHED; if (multiCmds->cmds[multiCmds->pos - 1].cmdState == HTTP_CMD_STATE_NOT_RUN_YET) { multiCmds->pos = (int16_t)(multiCmds->pos - 2); - httpDebug("context:%p, fd:%d, ip:%s, import failed, try create stable", pContext, pContext->fd, - pContext->ipstr); + httpDebug("context:%p, fd:%d, import failed, try create stable", pContext, pContext->fd); return false; } } else { @@ -125,22 +123,21 @@ bool tgCheckFinished(struct HttpContext *pContext, HttpSqlCmd *cmd, int code) { } } else if (cmd->cmdType == HTTP_CMD_TYPE_CREATE_DB) { cmd->cmdState = HTTP_CMD_STATE_RUN_FINISHED; - httpDebug("context:%p, fd:%d, ip:%s, code:%s, create database failed", pContext, pContext->fd, pContext->ipstr, - tstrerror(code)); + httpDebug("context:%p, fd:%d, code:%s, create database failed", pContext, pContext->fd, tstrerror(code)); } else if (cmd->cmdType == HTTP_CMD_TYPE_CREATE_STBALE) { cmd->cmdState = HTTP_CMD_STATE_RUN_FINISHED; - httpDebug("context:%p, fd:%d, ip:%s, code:%s, create stable failed", pContext, pContext->fd, pContext->ipstr, tstrerror(code)); + httpDebug("context:%p, fd:%d, code:%s, create stable failed", pContext, pContext->fd, tstrerror(code)); } else { } return true; } -void tgSetNextCmd(struct HttpContext *pContext, HttpSqlCmd *cmd, int code) { +void tgSetNextCmd(struct HttpContext *pContext, HttpSqlCmd *cmd, int32_t code) { HttpSqlCmds *multiCmds = pContext->multiCmds; - httpDebug("context:%p, fd:%d, ip:%s, get telegraf next command, pos:%d, code:%s, state:%d, type:%d, rettype:%d, tags:%d", - pContext, pContext->fd, pContext->ipstr, multiCmds->pos, tstrerror(code), cmd->cmdState, cmd->cmdType, - cmd->cmdReturnType, cmd->tagNum); + httpDebug("context:%p, fd:%d, get telegraf next command, pos:%d, code:%s, state:%d, type:%d, rettype:%d, tags:%d", + pContext, pContext->fd, multiCmds->pos, tstrerror(code), cmd->cmdState, cmd->cmdType, cmd->cmdReturnType, + cmd->tagNum); if (cmd->cmdType == HTTP_CMD_TYPE_INSERT) { multiCmds->pos = (int16_t)(multiCmds->pos + 2); diff --git a/src/plugins/http/src/httpUtil.c b/src/plugins/http/src/httpUtil.c index d1a0eb90f03de4108ad16b6d2f836058f7273eb2..2c8879f8804828fdd9de268ab1b6348df3a6b77c 100644 --- a/src/plugins/http/src/httpUtil.c +++ b/src/plugins/http/src/httpUtil.c @@ -29,7 +29,7 @@ bool httpCheckUsedbSql(char *sql) { return false; } -void httpTimeToString(time_t t, char *buf, int buflen) { +void httpTimeToString(time_t t, char *buf, int32_t buflen) { memset(buf, 0, (size_t)buflen); char ts[32] = {0}; @@ -44,13 +44,13 @@ int32_t httpAddToSqlCmdBuffer(HttpContext *pContext, const char *const format, . HttpSqlCmds *cmd = pContext->multiCmds; if (cmd->buffer == NULL) return -1; - int remainLength = cmd->bufferSize - cmd->bufferPos; + int32_t remainLength = cmd->bufferSize - cmd->bufferPos; if (remainLength < 4096) { if (!httpReMallocMultiCmdsBuffer(pContext, cmd->bufferSize * 2)) return -1; } - char *buffer = cmd->buffer + cmd->bufferPos; - int len = 0; + char * buffer = cmd->buffer + cmd->bufferPos; + int32_t len = 0; va_list argpointer; va_start(argpointer, format); @@ -76,13 +76,13 @@ int32_t httpAddToSqlCmdBufferNoTerminal(HttpContext *pContext, const char *const HttpSqlCmds *cmd = pContext->multiCmds; if (cmd->buffer == NULL) return -1; - int remainLength = cmd->bufferSize - cmd->bufferPos; + int32_t remainLength = cmd->bufferSize - cmd->bufferPos; if (remainLength < 4096) { if (!httpReMallocMultiCmdsBuffer(pContext, cmd->bufferSize * 2)) return -1; } - char *buffer = cmd->buffer + cmd->bufferPos; - int len = 0; + char * buffer = cmd->buffer + cmd->bufferPos; + int32_t len = 0; va_list argpointer; va_start(argpointer, format); @@ -107,7 +107,7 @@ int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext) { HttpSqlCmds *cmd = pContext->multiCmds; if (cmd->buffer == NULL) return -1; - int remainLength = cmd->bufferSize - cmd->bufferPos; + int32_t remainLength = cmd->bufferSize - cmd->bufferPos; if (remainLength < 4096) { if (!httpReMallocMultiCmdsBuffer(pContext, cmd->bufferSize * 2)) return -1; } @@ -124,7 +124,7 @@ int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext) { return (int32_t)(buffer - cmd->buffer); } -int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize) { +int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int32_t mallocSize) { HttpSqlCmds *cmd = pContext->multiCmds; if (cmd->buffer == NULL) return -1; @@ -139,18 +139,17 @@ int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize) { return (int32_t)(buffer - cmd->buffer); } -bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize) { +bool httpMallocMultiCmds(HttpContext *pContext, int32_t cmdSize, int32_t bufferSize) { if (cmdSize > HTTP_MAX_CMD_SIZE) { - httpError("context:%p, fd:%d, ip:%s, user:%s, mulitcmd size:%d large then %d", pContext, pContext->fd, - pContext->ipstr, pContext->user, cmdSize, HTTP_MAX_CMD_SIZE); + httpError("context:%p, fd:%d, user:%s, mulitcmd size:%d large then %d", pContext, pContext->fd, pContext->user, + cmdSize, HTTP_MAX_CMD_SIZE); return false; } if (pContext->multiCmds == NULL) { pContext->multiCmds = (HttpSqlCmds *)malloc(sizeof(HttpSqlCmds)); if (pContext->multiCmds == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, malloc multiCmds error", pContext, pContext->fd, pContext->ipstr, - pContext->user); + httpError("context:%p, fd:%d, user:%s, malloc multiCmds error", pContext, pContext->fd, pContext->user); return false; } memset(pContext->multiCmds, 0, sizeof(HttpSqlCmds)); @@ -161,7 +160,7 @@ bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize) { free(multiCmds->cmds); multiCmds->cmds = (HttpSqlCmd *)malloc((size_t)cmdSize * sizeof(HttpSqlCmd)); if (multiCmds->cmds == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, malloc cmds:%d error", pContext, pContext->fd, pContext->ipstr, + httpError("context:%p, fd:%d, user:%s, malloc cmds:%d error", pContext, pContext->fd, pContext->user, cmdSize); return false; } @@ -172,8 +171,8 @@ bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize) { free(multiCmds->buffer); multiCmds->buffer = (char *)malloc((size_t)bufferSize); if (multiCmds->buffer == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, malloc buffer:%d error", pContext, pContext->fd, pContext->ipstr, - pContext->user, bufferSize); + httpError("context:%p, fd:%d, user:%s, malloc buffer:%d error", pContext, pContext->fd, pContext->user, + bufferSize); return false; } multiCmds->bufferSize = bufferSize; @@ -187,19 +186,18 @@ bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize) { return true; } -bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize) { +bool httpReMallocMultiCmdsSize(HttpContext *pContext, int32_t cmdSize) { HttpSqlCmds *multiCmds = pContext->multiCmds; if (cmdSize > HTTP_MAX_CMD_SIZE) { - httpError("context:%p, fd:%d, ip:%s, user:%s, mulitcmd size:%d large then %d", pContext, pContext->fd, - pContext->ipstr, pContext->user, cmdSize, HTTP_MAX_CMD_SIZE); + httpError("context:%p, fd:%d, user:%s, mulitcmd size:%d large then %d", pContext, pContext->fd, pContext->user, + cmdSize, HTTP_MAX_CMD_SIZE); return false; } multiCmds->cmds = (HttpSqlCmd *)realloc(multiCmds->cmds, (size_t)cmdSize * sizeof(HttpSqlCmd)); if (multiCmds->cmds == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, malloc cmds:%d error", pContext, pContext->fd, pContext->ipstr, - pContext->user, cmdSize); + httpError("context:%p, fd:%d, user:%s, malloc cmds:%d error", pContext, pContext->fd, pContext->user, cmdSize); return false; } memset(multiCmds->cmds + multiCmds->maxSize, 0, (size_t)(cmdSize - multiCmds->maxSize) * sizeof(HttpSqlCmd)); @@ -208,19 +206,18 @@ bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize) { return true; } -bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int bufferSize) { +bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int32_t bufferSize) { HttpSqlCmds *multiCmds = pContext->multiCmds; if (bufferSize > HTTP_MAX_BUFFER_SIZE) { - httpError("context:%p, fd:%d, ip:%s, user:%s, mulitcmd buffer size:%d large then %d", - pContext, pContext->fd, pContext->ipstr, pContext->user, bufferSize, HTTP_MAX_BUFFER_SIZE); + httpError("context:%p, fd:%d, user:%s, mulitcmd buffer size:%d large then %d", pContext, pContext->fd, + pContext->user, bufferSize, HTTP_MAX_BUFFER_SIZE); return false; } multiCmds->buffer = (char *)realloc(multiCmds->buffer, (size_t)bufferSize); if (multiCmds->buffer == NULL) { - httpError("context:%p, fd:%d, ip:%s, user:%s, malloc buffer:%d error", pContext, pContext->fd, pContext->ipstr, - pContext->user, bufferSize); + httpError("context:%p, fd:%d, user:%s, malloc buffer:%d error", pContext, pContext->fd, pContext->user, bufferSize); return false; } memset(multiCmds->buffer + multiCmds->bufferSize, 0, (size_t)(bufferSize - multiCmds->bufferSize)); @@ -261,7 +258,7 @@ bool httpCompareMethod(HttpDecodeMethod *pSrc, HttpDecodeMethod *pCmp) { } void httpAddMethod(HttpServer *pServer, HttpDecodeMethod *pMethod) { - int pos = 0; + int32_t pos = 0; for (pos = 0; pos < pServer->methodScannerLen; ++pos) { if (httpCompareMethod(pServer->methodScanner[pos], pMethod)) { break; @@ -296,13 +293,13 @@ HttpSqlCmd *httpCurrSqlCmd(HttpContext *pContext) { return multiCmds->cmds + multiCmds->size - 1; } -int httpNextSqlCmdPos(HttpContext *pContext) { +int32_t httpNextSqlCmdPos(HttpContext *pContext) { HttpSqlCmds *multiCmds = pContext->multiCmds; return multiCmds->size; } void httpTrimTableName(char *name) { - for (int i = 0; name[i] != 0; i++) { + for (int32_t i = 0; name[i] != 0; i++) { if (name[i] == ' ' || name[i] == ':' || name[i] == '.' || name[i] == '-' || name[i] == '/' || name[i] == '\'') name[i] = '_'; if (i == TSDB_TABLE_NAME_LEN) { @@ -312,9 +309,9 @@ void httpTrimTableName(char *name) { } } -int httpShrinkTableName(HttpContext *pContext, int pos, char *name) { - int len = 0; - for (int i = 0; name[i] != 0; i++) { +int32_t httpShrinkTableName(HttpContext *pContext, int32_t pos, char *name) { + int32_t len = 0; + for (int32_t i = 0; name[i] != 0; i++) { if (name[i] == ' ' || name[i] == ':' || name[i] == '.' || name[i] == '-' || name[i] == '/' || name[i] == '\'' || name[i] == '\"') name[i] = '_'; @@ -330,7 +327,7 @@ int httpShrinkTableName(HttpContext *pContext, int pos, char *name) { MD5Update(&context, (uint8_t *)name, (uint32_t)len); MD5Final(&context); - int table_name = httpAddToSqlCmdBuffer( + int32_t table_name = httpAddToSqlCmdBuffer( pContext, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0], context.digest[1], context.digest[2], context.digest[3], context.digest[4], context.digest[5], context.digest[6], context.digest[7], context.digest[8], context.digest[9], context.digest[10], context.digest[11], @@ -343,7 +340,7 @@ int httpShrinkTableName(HttpContext *pContext, int pos, char *name) { return table_name; } -char *httpGetCmdsString(HttpContext *pContext, int pos) { +char *httpGetCmdsString(HttpContext *pContext, int32_t pos) { HttpSqlCmds *multiCmds = pContext->multiCmds; if (pos < 0 || pos >= multiCmds->bufferSize) { return ""; @@ -352,8 +349,8 @@ char *httpGetCmdsString(HttpContext *pContext, int pos) { return multiCmds->buffer + pos; } -int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData) { - int err = 0; +int32_t httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData) { + int32_t err = 0; z_stream gzipStream = {0}; static char dummyHead[2] = { @@ -396,7 +393,7 @@ int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t return 0; } -int httpGzipCompressInit(HttpContext *pContext) { +int32_t httpGzipCompressInit(HttpContext *pContext) { pContext->gzipStream.zalloc = (alloc_func) 0; pContext->gzipStream.zfree = (free_func) 0; pContext->gzipStream.opaque = (voidpf) 0; @@ -407,8 +404,8 @@ int httpGzipCompressInit(HttpContext *pContext) { return 0; } -int httpGzipCompress(HttpContext *pContext, char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData, bool isTheLast) { - int err = 0; +int32_t httpGzipCompress(HttpContext *pContext, char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData, bool isTheLast) { + int32_t err = 0; pContext->gzipStream.next_in = (Bytef *) srcData; pContext->gzipStream.avail_in = (uLong) nSrcData; pContext->gzipStream.next_out = (Bytef *) destData; @@ -442,3 +439,21 @@ int httpGzipCompress(HttpContext *pContext, char *srcData, int32_t nSrcData, cha *nDestData = (int32_t) (pContext->gzipStream.total_out); return 0; } + +bool httpUrlMatch(HttpContext* pContext, int32_t pos, char* cmp) { + HttpParser* pParser = pContext->parser; + + if (pos < 0 || pos >= HTTP_MAX_URL) { + return false; + } + + if (pParser->path[pos].pos <= 0) { + return false; + } + + if (strcmp(pParser->path[pos].str, cmp) != 0) { + return false; + } + + return true; +} diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index f4927ecb7825b09e853351a07ea5f9a502585482..b5adeafd23bd2e651316b3eef2d9016b1e77a8c9 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1976,36 +1976,36 @@ static void changeExecuteScanOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bo // todo handle the case the the order irrelevant query type mixed up with order critical query type // descending order query for last_row query - if (isFirstLastRowQuery(pQuery) && !QUERY_IS_ASC_QUERY(pQuery)) { + if (isFirstLastRowQuery(pQuery)) { qDebug("QInfo:%p scan order changed for last_row query, old:%d, new:%d", GET_QINFO_ADDR(pQuery), pQuery->order.order, TSDB_ORDER_ASC); - SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); pQuery->order.order = TSDB_ORDER_ASC; - assert (pQuery->window.skey <= pQuery->window.ekey); + if (pQuery->window.skey > pQuery->window.ekey) { + SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); + } - doExchangeTimeWindow(pQInfo, &pQuery->window); return; } - if (isGroupbyNormalCol(pQuery->pGroupbyExpr) && !QUERY_IS_ASC_QUERY(pQuery)) { + if (isGroupbyNormalCol(pQuery->pGroupbyExpr) && pQuery->order.order == TSDB_ORDER_DESC) { pQuery->order.order = TSDB_ORDER_ASC; - SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); - assert (pQuery->window.skey <= pQuery->window.ekey); + if (pQuery->window.skey > pQuery->window.ekey) { + SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); + } doExchangeTimeWindow(pQInfo, &pQuery->window); return; } - if (isPointInterpoQuery(pQuery) && (pQuery->intervalTime == 0) && !QUERY_IS_ASC_QUERY(pQuery)) { - qDebug(msg, GET_QINFO_ADDR(pQuery), "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, - pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); - SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); + if (isPointInterpoQuery(pQuery) && pQuery->intervalTime == 0) { + if (!QUERY_IS_ASC_QUERY(pQuery)) { + qDebug(msg, GET_QINFO_ADDR(pQuery), "interp", pQuery->order.order, TSDB_ORDER_ASC, pQuery->window.skey, + pQuery->window.ekey, pQuery->window.ekey, pQuery->window.skey); + SWAP(pQuery->window.skey, pQuery->window.ekey, TSKEY); + } pQuery->order.order = TSDB_ORDER_ASC; - - assert (pQuery->window.skey <= pQuery->window.ekey); - doExchangeTimeWindow(pQInfo, &pQuery->window); return; } @@ -2392,16 +2392,16 @@ static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pB memset(tmp + sizeof(tFilePage) + bytes * pRec->rows, 0, (size_t)((newSize - pRec->rows) * bytes)); pQuery->sdata[i] = (tFilePage *)tmp; } - + // set the pCtx output buffer position pRuntimeEnv->pCtx[i].aOutputBuf = pQuery->sdata[i]->data + pRec->rows * bytes; - + int32_t functionId = pQuery->pSelectExpr[i].base.functionId; if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { pRuntimeEnv->pCtx[i].ptsOutputBuf = pRuntimeEnv->pCtx[0].aOutputBuf; } } - + qDebug("QInfo:%p realloc output buffer, new size: %d rows, old:%" PRId64 ", remain:%" PRId64, GET_QINFO_ADDR(pRuntimeEnv), newSize, pRec->capacity, newSize - pRec->rows); @@ -2950,11 +2950,11 @@ int32_t mergeIntoGroupResultImpl(SQInfo *pQInfo, SArray *pGroup) { STableQueryInfo *item = taosArrayGetP(pGroup, i); SIDList list = getDataBufPagesIdList(pRuntimeEnv->pResultBuf, TSDB_TABLEID(item->pTable)->tid); + pageList = list; + tid = TSDB_TABLEID(item->pTable)->tid; if (taosArrayGetSize(list) > 0 && item->windowResInfo.size > 0) { pTableList[numOfTables++] = item; - tid = TSDB_TABLEID(item->pTable)->tid; - pageList = list; } } @@ -3387,7 +3387,7 @@ void skipResults(SQueryRuntimeEnv *pRuntimeEnv) { for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t functionId = pQuery->pSelectExpr[i].base.functionId; int32_t bytes = pRuntimeEnv->pCtx[i].outputBytes; - + memmove(pQuery->sdata[i]->data, (char*)pQuery->sdata[i]->data + bytes * numOfSkip, (size_t)(pQuery->rec.rows * bytes)); pRuntimeEnv->pCtx[i].aOutputBuf = ((char*) pQuery->sdata[i]->data) + pQuery->rec.rows * bytes; @@ -4384,32 +4384,6 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { return true; } -static void freeTableQueryInfo(STableGroupInfo* pTableGroupInfo) { - if (pTableGroupInfo->pGroupList == NULL) { - assert(pTableGroupInfo->numOfTables == 0); - } else { - size_t numOfGroups = taosArrayGetSize(pTableGroupInfo->pGroupList); - for (int32_t i = 0; i < numOfGroups; ++i) { - SArray *p = taosArrayGetP(pTableGroupInfo->pGroupList, i); - - size_t num = taosArrayGetSize(p); - for(int32_t j = 0; j < num; ++j) { - STableQueryInfo* item = taosArrayGetP(p, j); - destroyTableQueryInfo(item); - } - - taosArrayDestroy(p); - } - - taosArrayDestroy(pTableGroupInfo->pGroupList); - pTableGroupInfo->pGroupList = NULL; - pTableGroupInfo->numOfTables = 0; - } - - taosHashCleanup(pTableGroupInfo->map); - pTableGroupInfo->map = NULL; -} - static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) { SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; @@ -4445,22 +4419,20 @@ static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) terrno = TSDB_CODE_SUCCESS; if (isFirstLastRowQuery(pQuery)) { pRuntimeEnv->pQueryHandle = tsdbQueryLastRow(tsdb, &cond, &pQInfo->tableGroupInfo, pQInfo); - if (pRuntimeEnv->pQueryHandle == NULL) { // no data in current stable, clear all - freeTableQueryInfo(&pQInfo->tableqinfoGroupInfo); - } else { // update the query time window - pQuery->window = cond.twindow; - size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); - for (int32_t i = 0; i < numOfGroups; ++i) { - SArray *group = GET_TABLEGROUP(pQInfo, i); + // update the query time window + pQuery->window = cond.twindow; + + size_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + for(int32_t i = 0; i < numOfGroups; ++i) { + SArray *group = GET_TABLEGROUP(pQInfo, i); - size_t t = taosArrayGetSize(group); - for (int32_t j = 0; j < t; ++j) { - STableQueryInfo *pCheckInfo = taosArrayGetP(group, j); + size_t t = taosArrayGetSize(group); + for (int32_t j = 0; j < t; ++j) { + STableQueryInfo *pCheckInfo = taosArrayGetP(group, j); - pCheckInfo->win = pQuery->window; - pCheckInfo->lastKey = pCheckInfo->win.skey; - } + pCheckInfo->win = pQuery->window; + pCheckInfo->lastKey = pCheckInfo->win.skey; } } } else if (isPointInterpoQuery(pQuery)) { @@ -4514,12 +4486,6 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo return code; } - if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { - qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo); - setQueryStatus(pQuery, QUERY_COMPLETED); - return TSDB_CODE_SUCCESS; - } - pQInfo->tsdb = tsdb; pQInfo->vgId = vgId; @@ -4642,7 +4608,7 @@ static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) { SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv; SQuery* pQuery = pRuntimeEnv->pQuery; SQueryCostInfo* summary = &pRuntimeEnv->summary; - + int64_t st = taosGetTimestampMs(); TsdbQueryHandleT pQueryHandle = IS_MASTER_SCAN(pRuntimeEnv)? pRuntimeEnv->pQueryHandle : pRuntimeEnv->pSecQueryHandle; @@ -4652,7 +4618,7 @@ static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) { while (tsdbNextDataBlock(pQueryHandle)) { summary->totalBlocks += 1; - + if (IS_QUERY_KILLED(pQInfo)) { longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED); } @@ -4697,7 +4663,7 @@ static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) { summary->totalRows += blockInfo.rows; stableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, pDataBlock, binarySearchForKey); - + qDebug("QInfo:%p check data block completed, uid:%"PRId64", tid:%d, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, " "lastKey:%" PRId64, pQInfo, blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, @@ -6421,10 +6387,25 @@ static void freeQInfo(SQInfo *pQInfo) { taosTFree(pQuery); } - freeTableQueryInfo(&pQInfo->tableqinfoGroupInfo); + // todo refactor, extract method to destroytableDataInfo + if (pQInfo->tableqinfoGroupInfo.pGroupList != NULL) { + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); + for (int32_t i = 0; i < numOfGroups; ++i) { + SArray *p = GET_TABLEGROUP(pQInfo, i); - taosTFree(pQInfo->pBuf); + size_t num = taosArrayGetSize(p); + for(int32_t j = 0; j < num; ++j) { + STableQueryInfo* item = taosArrayGetP(p, j); + destroyTableQueryInfo(item); + } + + taosArrayDestroy(p); + } + } + taosTFree(pQInfo->pBuf); + taosArrayDestroy(pQInfo->tableqinfoGroupInfo.pGroupList); + taosHashCleanup(pQInfo->tableqinfoGroupInfo.map); tsdbDestroyTableGroup(&pQInfo->tableGroupInfo); taosArrayDestroy(pQInfo->arrTableIdInfo); diff --git a/src/rpc/src/rpcTcp.c b/src/rpc/src/rpcTcp.c index 3475e0f317fcb2e083dbc3a8277b545459e48eee..56b3fa8616089e72cfb9ba55e96520fa084a0176 100644 --- a/src/rpc/src/rpcTcp.c +++ b/src/rpc/src/rpcTcp.c @@ -245,6 +245,8 @@ static void *taosAcceptTcpConnection(void *arg) { } taosKeepTcpAlive(connFd); + struct timeval to={1, 0}; + taosSetSockOpt(connFd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); // pick up the thread to handle this connection pThreadObj = pServerObj->pThreadObj + threadId; diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index a84bb69777f512a6c5d947dd48f8f2865b867200..564d7f5db51c80929391283e4b6fa1128275ea14 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -27,7 +27,8 @@ static int tsdbCompareSchemaVersion(const void *key1, const void *key2); static int tsdbRestoreTable(void *pHandle, void *cont, int contLen); static void tsdbOrgMeta(void *pHandle); static char * getTagIndexKey(const void *pData); -static STable *tsdbNewTable(STableCfg *pCfg, bool isSuper); +static STable *tsdbNewTable(); +static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper); static void tsdbFreeTable(STable *pTable); static int tsdbAddTableToMeta(STsdbRepo *pRepo, STable *pTable, bool addIdx, bool lock); static void tsdbRemoveTableFromMeta(STsdbRepo *pRepo, STable *pTable, bool rmFromIdx, bool lock); @@ -92,7 +93,7 @@ int tsdbCreateTable(TSDB_REPO_T *repo, STableCfg *pCfg) { super = tsdbGetTableByUid(pMeta, pCfg->superUid); if (super == NULL) { // super table not exists, try to create it newSuper = 1; - super = tsdbNewTable(pCfg, true); + super = tsdbCreateTableFromCfg(pCfg, true); if (super == NULL) goto _err; } else { if (TABLE_TYPE(super) != TSDB_SUPER_TABLE || TABLE_UID(super) != pCfg->superUid) { @@ -102,7 +103,7 @@ int tsdbCreateTable(TSDB_REPO_T *repo, STableCfg *pCfg) { } } - table = tsdbNewTable(pCfg, false); + table = tsdbCreateTableFromCfg(pCfg, false); if (table == NULL) goto _err; // Register to meta @@ -654,16 +655,25 @@ static char *getTagIndexKey(const void *pData) { return res; } -static STable *tsdbNewTable(STableCfg *pCfg, bool isSuper) { - STable *pTable = NULL; - size_t tsize = 0; - - pTable = (STable *)calloc(1, sizeof(STable)); +static STable *tsdbNewTable() { + STable *pTable = (STable *)calloc(1, sizeof(*pTable)); if (pTable == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - goto _err; + return NULL; } + pTable->lastKey = TSKEY_INITIAL_VAL; + + return pTable; +} + +static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper) { + STable *pTable = NULL; + size_t tsize = 0; + + pTable = tsdbNewTable(); + if (pTable == NULL) goto _err; + if (isSuper) { pTable->type = TSDB_SUPER_TABLE; tsize = strnlen(pCfg->sname, TSDB_TABLE_NAME_LEN - 1); @@ -731,8 +741,6 @@ static STable *tsdbNewTable(STableCfg *pCfg, bool isSuper) { } } } - - pTable->lastKey = TSKEY_INITIAL_VAL; } T_REF_INC(pTable); @@ -1139,11 +1147,9 @@ static int tsdbEncodeTable(void **buf, STable *pTable) { } static void *tsdbDecodeTable(void *buf, STable **pRTable) { - STable *pTable = (STable *)calloc(1, sizeof(STable)); - if (pTable == NULL) { - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - return NULL; - } + STable *pTable = tsdbNewTable(); + if (pTable == NULL) return NULL; + uint8_t type = 0; buf = taosDecodeFixedU8(buf, &type); diff --git a/tests/pytest/import_merge/importToCommit.py b/tests/pytest/import_merge/importToCommit.py index 9a17ae95faf039c4ceee29f949f6d0e47a2b2d28..7bec5fcd5d3124e588b4d6d0910e1dafc1a991bb 100644 --- a/tests/pytest/import_merge/importToCommit.py +++ b/tests/pytest/import_merge/importToCommit.py @@ -33,7 +33,7 @@ class TDTestCase: tdDnodes.start(1) tdSql.execute('reset query cache') tdSql.execute('drop database if exists db') - tdSql.execute('create database db cache 128 maxtables 10') + tdSql.execute('create database db cache 128') tdSql.execute('use db') tdLog.info("================= step1") diff --git a/tests/pytest/tag_lite/datatype-without-alter.py b/tests/pytest/tag_lite/datatype-without-alter.py index 42bc42bdbf61cc3f88d83b5da04883742ea7ebc6..da52e149a51c3128f82b8878ed8dc836fb726513 100644 --- a/tests/pytest/tag_lite/datatype-without-alter.py +++ b/tests/pytest/tag_lite/datatype-without-alter.py @@ -38,7 +38,7 @@ class TDTestCase: tdLog.info("drop database db if exits") tdSql.execute('drop database if exists db') tdLog.info("================= step1") - tdSql.execute('create database db maxtables 4') + tdSql.execute('create database db') tdLog.sleep(5) tdSql.execute('use db') diff --git a/tests/pytest/tag_lite/datatype.py b/tests/pytest/tag_lite/datatype.py index bc99cf74b0be5fc20538c8a1ad0d060854d9cba2..f7fa9fa3a2dddaa3f352d02f74872ba42bd32f44 100644 --- a/tests/pytest/tag_lite/datatype.py +++ b/tests/pytest/tag_lite/datatype.py @@ -38,7 +38,7 @@ class TDTestCase: tdLog.info("drop database db if exits") tdSql.execute('drop database if exists db') tdLog.info("================= step1") - tdSql.execute('create database db maxtables 4') + tdSql.execute('create database db') tdLog.sleep(5) tdSql.execute('use db') diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py index 627d71247487f8a0f71385e766886a9b50a917d0..7de8efdfe96c2312a7bb844329fb91f770c54180 100644 --- a/tests/pytest/util/sql.py +++ b/tests/pytest/util/sql.py @@ -123,8 +123,12 @@ class TDSql: def checkData(self, row, col, data): self.checkRowCol(row, col) - if str(self.queryResult[row][col]) != str(data): - if isinstance(data, float) and abs(self.queryResult[row][col] - data) <= 0.000001: + if self.queryResult[row][col] != data: + if str(self.queryResult[row][col]) != str(data): + tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" % + (self.sql, row, col, self.queryResult[row][col], data)) + return + elif isinstance(data, float) and abs(self.queryResult[row][col] - data) <= 0.000001: tdLog.info("sql:%s, row:%d col:%d data:%f == expect:%f" % (self.sql, row, col, self.queryResult[row][col], data)) return diff --git a/tests/script/fullGeneralSuite.sim b/tests/script/fullGeneralSuite.sim index d137e53d2721842e4921b10450b3432589c15e37..4df79002658056c44670baf0664fccfacefd0261 100644 --- a/tests/script/fullGeneralSuite.sim +++ b/tests/script/fullGeneralSuite.sim @@ -130,7 +130,6 @@ run general/parser/join.sim run general/parser/join_multivnode.sim run general/parser/select_with_tags.sim run general/parser/groupby.sim -run general/parser/bug.sim run general/parser/tags_dynamically_specifiy.sim run general/parser/set_tag_vals.sim #unsupport run general/parser/repeatAlter.sim diff --git a/tests/script/general/http/autocreate.sim b/tests/script/general/http/autocreate.sim index 6a005b028a0187d9796a7e7d1902374fd95257b7..98d64ab839df11d17bd6d9036a53fcc087b69ea8 100644 --- a/tests/script/general/http/autocreate.sim +++ b/tests/script/general/http/autocreate.sim @@ -24,5 +24,10 @@ print curl 127.0.0.1:7111/rest/sql -----> $system_content # return -1 #endi +sql select * from db.win_cpu_windows_1_processor +print rows: $rows +if $rows != 1 then + return -1 +endi #system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/general/http/chunked.sim b/tests/script/general/http/chunked.sim new file mode 100644 index 0000000000000000000000000000000000000000..8673655d969392873b297c82e8ae4d394ac3b190 --- /dev/null +++ b/tests/script/general/http/chunked.sim @@ -0,0 +1,37 @@ +system sh/stop_dnodes.sh +sleep 3000 +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c wallevel -v 0 +system sh/cfg.sh -n dnode1 -c http -v 1 +system sh/cfg.sh -n dnode1 -c maxSQLLength -v 7340032 +system sh/exec.sh -n dnode1 -s start + +sleep 3000 +sql connect + +print ============================ dnode1 start + +print =============== step1 - prepare data +sql create database d1 +sql use d1 + +sql create table table_rest (ts timestamp, i int) +print sql length is 270KB +restful d1 table_rest 1591072800 10000 +restful d1 table_rest 1591172800 10000 +restful d1 table_rest 1591272800 10000 +restful d1 table_rest 1591372800 10000 +restful d1 table_rest 1591472800 10000 +restful d1 table_rest 1591572800 10000 +restful d1 table_rest 1591672800 10000 +restful d1 table_rest 1591772800 10000 +restful d1 table_rest 1591872800 10000 +restful d1 table_rest 1591972800 10000 + +sql select * from table_rest; +print rows: $rows +if $rows != 100000 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/general/http/grafana.sim b/tests/script/general/http/grafana.sim index cea804cfbb19cd0a193744fbee458b44910497bf..c7866e5f4ce950292f17a1b4d0f8a49838fc18a1 100644 --- a/tests/script/general/http/grafana.sim +++ b/tests/script/general/http/grafana.sim @@ -54,13 +54,13 @@ print =============== step2 - login system_content curl 127.0.0.1:7111/grafana/ print 1-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi system_content curl 127.0.0.1:7111/grafana/xx print 2-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi @@ -72,7 +72,7 @@ endi system_content curl 127.0.0.1:7111/grafana/root/1/123/1/1/3 print 4-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi @@ -84,13 +84,13 @@ endi system_content curl -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cudGFvc2RhdGEuY29tIiwicGFzcyI6InRhb3NkYXRhIiwic3ViIjoicm9vdCJ9.xPv3b5odlR7YF8G_QWASjIRbMtA5v4ItToJ35fFgi' -d 'show databases' 127.0.0.1:7111/grafana/root/1/login print 6-> $system_content -if $system_content != @{"status":"error","code":5010,"desc":"invalid type of Authorization"}@ then +if $system_content != @{"status":"error","code":4386,"desc":"invalid type of Authorization"}@ then return -1 endi system_content curl -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cudGFvc2RhdGEuY29tIiwicGFzcyI6InRhb3NkYXRhIiwic3ViIjoicm9vdCJ9.xPv3b5odlR7YF8G_QWASjIRbMtA5v4ItToJ35fFgi' -d 'show databases' 127.0.0.1:7111/grafana/root/1/login print 7-> $system_content -if $system_content != @{"status":"error","code":5010,"desc":"invalid type of Authorization"}@ then +if $system_content != @{"status":"error","code":4387,"desc":"invalid format of Authorization"}@ then return -1 endi diff --git a/tests/script/general/http/gzip.sim b/tests/script/general/http/gzip.sim new file mode 100644 index 0000000000000000000000000000000000000000..0289e337a66f7fbb52752ef51f00432d8f1c3ff6 --- /dev/null +++ b/tests/script/general/http/gzip.sim @@ -0,0 +1,27 @@ +system sh/stop_dnodes.sh +sleep 3000 +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c wallevel -v 0 +system sh/cfg.sh -n dnode1 -c http -v 1 +system sh/cfg.sh -n dnode1 -c maxSQLLength -v 7340032 +system sh/exec.sh -n dnode1 -s start + +sleep 3000 +sql connect + +print ============================ dnode1 start + +print =============== step1 - prepare data +sql create database d1 +sql use d1 + +sql create table table_rest (ts timestamp, i int) +print sql length is 270KB +restful d1 table_rest 1591072800 10000 gzip +sql select * from table_rest; +print rows: $rows +if $rows != 10000 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/general/http/restful_full.sim b/tests/script/general/http/restful_full.sim index b7f98e49e06e6efa5f6adca372a2917c6e91ca21..a02140a4199054775c405ec3c6223faa2ef681e4 100644 --- a/tests/script/general/http/restful_full.sim +++ b/tests/script/general/http/restful_full.sim @@ -14,26 +14,26 @@ print =============== step1 - login system_content curl 127.0.0.1:7111/rest/ print 1-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi system_content curl 127.0.0.1:7111/rest/xx print 2-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi system_content curl 127.0.0.1:7111/rest/login print 3-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi #4 system_content curl 127.0.0.1:7111/rest/login/root print 4-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi @@ -58,13 +58,13 @@ endi #8 system_content curl -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cudGFvc2RhdGEuY29tIiwicGFzcyI6InRhb3NkYXRhIiwic3ViIjoicm9vdCJ9.xPv3b5odlR7YF8G_QWASjIRbMtA5v4ItToJ35fFgi' -d 'show databases' 127.0.0.1:7111/rest/login/root/1 print 8-> $system_content -if $system_content != @{"status":"error","code":5010,"desc":"invalid type of Authorization"}@ then +if $system_content != @{"status":"error","code":4386,"desc":"invalid type of Authorization"}@ then return -1 endi system_content curl -H 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cudGFvc2RhdGEuY29tIiwicGFzcyI6InRhb3NkYXRhIiwic3ViIjoicm9vdCJ9.xPv3b5odlR7YF8G_QWASjIRbMtA5v4ItToJ35fFgi' -d 'show databases' 127.0.0.1:7111/rest/login/root/1 print 9-> $system_content -if $system_content != @{"status":"error","code":5010,"desc":"invalid type of Authorization"}@ then +if $system_content != @{"status":"error","code":4387,"desc":"invalid format of Authorization"}@ then return -1 endi @@ -100,7 +100,7 @@ endi #14 system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d '' 127.0.0.1:7111/rest/sql print 14-> $system_content -if $system_content != @{"status":"error","code":5012,"desc":"no sql input"}@ then +if $system_content != @{"status":"error","code":4359,"desc":"no sql input"}@ then return -1 endi diff --git a/tests/script/general/http/telegraf.sim b/tests/script/general/http/telegraf.sim index e54af99ad732e4841717a8e9cf126f5acff3de46..4018d9661a0a1d7b445fc9eff416bd40f84d2116 100644 --- a/tests/script/general/http/telegraf.sim +++ b/tests/script/general/http/telegraf.sim @@ -16,224 +16,224 @@ print =============== step1 - parse system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/ print $system_content -if $system_content != @{"status":"error","code":5022,"desc":"database name can not be null"}@ then +if $system_content != @{"status":"error","code":4448,"desc":"database name can not be null"}@ then return -1 endi system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from d1.table_admin' -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/ print $system_content -if $system_content != @{"status":"error","code":5022,"desc":"database name can not be null"}@ then +if $system_content != @{"status":"error","code":4448,"desc":"database name can not be null"}@ then return -1 endi system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from d1.table_admin' -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/d123456789012345678901234567890123456 print $system_content -if $system_content != @{"status":"error","code":5023,"desc":"database name too long"}@ then +if $system_content != @{"status":"error","code":4449,"desc":"database name too long"}@ then return -1 endi system_content curl -u root:taosdata -d '[]' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5027,"desc":"metric name not find"}@ then +if $system_content != @{"status":"error","code":4453,"desc":"metric name not find"}@ then return -1 endi system_content curl -u root:taosdata -d '{}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5027,"desc":"metric name not find"}@ then +if $system_content != @{"status":"error","code":4453,"desc":"metric name not find"}@ then return -1 endi system_content curl -u root:taosdata -d '[{}]' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5027,"desc":"metric name not find"}@ then +if $system_content != @{"status":"error","code":4453,"desc":"metric name not find"}@ then return -1 endi system_content curl -u root:taosdata -d '{"metrics": []}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5025,"desc":"metrics size is 0"}@ then +if $system_content != @{"status":"error","code":4451,"desc":"metrics size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '{"metrics": [{}]}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5027,"desc":"metric name not find"}@ then +if $system_content != @{"status":"error","code":4453,"desc":"metric name not find"}@ then return -1 endi system_content curl -u root:taosdata -d '{"metrics": 12}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5025,"desc":"metrics size is 0"}@ then +if $system_content != @{"status":"error","code":4451,"desc":"metrics size is 0"}@ then return -1 endi #system_content curl -u root:taosdata -d '{"metrics": [{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}]}' 127.0.0.1:7111/telegraf/db/root/taosdata1 #print $system_content -#if $system_content != @{"status":"error","code":5026,"desc":"metrics size can not more than 50"}@ then +#if $system_content != @{"status":"error","code":4452,"desc":"metrics size can not more than 50"}@ then # return -1 #endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5027,"desc":"metric name not find"}@ then +if $system_content != @{"status":"error","code":4453,"desc":"metric name not find"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":111,"tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5028,"desc":"metric name type should be string"}@ then +if $system_content != @{"status":"error","code":4454,"desc":"metric name type should be string"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5029,"desc":"metric name length is 0"}@ then +if $system_content != @{"status":"error","code":4455,"desc":"metric name length is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234a1234567890123456789012345678901234","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5030,"desc":"metric name length too long"}@ then +if $system_content != @{"status":"error","code":4456,"desc":"metric name length too long"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"}}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5031,"desc":"timestamp not find"}@ then +if $system_content != @{"status":"error","code":4457,"desc":"timestamp not find"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":""}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5032,"desc":"timestamp type should be integer"}@ then +if $system_content != @{"status":"error","code":4458,"desc":"timestamp type should be integer"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":-1}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5033,"desc":"timestamp value smaller than 0"}@ then +if $system_content != @{"status":"error","code":4459,"desc":"timestamp value smaller than 0"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5034,"desc":"tags not find"}@ then +if $system_content != @{"status":"error","code":4460,"desc":"tags not find"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5035,"desc":"tags size is 0"}@ then +if $system_content != @{"status":"error","code":4461,"desc":"tags size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":"","timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5035,"desc":"tags size is 0"}@ then +if $system_content != @{"status":"error","code":4461,"desc":"tags size is 0"}@ then return -1 endi #system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor","host":"windows","instance":"1","objectname":"Processor","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata #print $system_content -#if $system_content != @{"status":"error","code":5036,"desc":"tags size too long"}@ then +#if $system_content != @{"status":"error","code":4461,"desc":"tags size too long"}@ then # return -1 #endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5035,"desc":"tags size is 0"}@ then +if $system_content != @{"status":"error","code":4461,"desc":"tags size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"":"windows"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5038,"desc":"tag name is null"}@ then +if $system_content != @{"status":"error","code":4464,"desc":"tag name is null"}@ then return -1 endi #system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host111111111111222222222222222222222":""},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 #print $system_content -#if $system_content != @{"status":"error","code":5039,"desc":"tag name length too long"}@ then +#if $system_content != @{"status":"error","code":4465,"desc":"tag name length too long"}@ then # return -1 #endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":true},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5040,"desc":"tag value type should be number or string"}@ then +if $system_content != @{"status":"error","code":4466,"desc":"tag value type should be number or string"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":""},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5041,"desc":"tag value is null"}@ then +if $system_content != @{"status":"error","code":4467,"desc":"tag value is null"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"5022":"111"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5042,"desc":"table is null"}@ then +if $system_content != @{"status":"error","code":4468,"desc":"table is null"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"host111111111111222222222222222222222host111111111111222222222222222222222host111111111111222222222222222222222host111111111111222222222222222222222host111111111111222222222222222222222host111111111111222222222222222222222host111111111111222222222222222222222host111111111111222222222222222222222"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5043,"desc":"table name length too long"}@ then +if $system_content != @{"status":"error","code":4469,"desc":"table name length too long"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5045,"desc":"fields size is 0"}@ then +if $system_content != @{"status":"error","code":4471,"desc":"fields size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"":0,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5048,"desc":"field name is null"}@ then +if $system_content != @{"status":"error","code":4474,"desc":"field name is null"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":"","Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5051,"desc":"field value is null"}@ then +if $system_content != @{"status":"error","code":4477,"desc":"field value is null"}@ then return -1 endi system_content curl -u root:taosdata -d '{"fields":{"Percent_DPC_Time":true,"Percent_Idle_Time":95.59830474853516,"Percent_Interrupt_Time":0,"Percent_Privileged_Time":0,"Percent_Processor_Time":0,"Percent_User_Time":0},"name":"win_cpu","tags":{"host":"windows","instance":"1","objectname":"Processor"},"timestamp":1535784122}' 127.0.0.1:7111/telegraf/db/root/taosdata1 print $system_content -if $system_content != @{"status":"error","code":5050,"desc":"field value type should be number or string"}@ then +if $system_content != @{"status":"error","code":4476,"desc":"field value type should be number or string"}@ then return -1 endi diff --git a/tests/script/general/http/testSuite.sim b/tests/script/general/http/testSuite.sim index d91e9f452d17d4f46f82123b7e6911c094681971..f35362bf070a11e2fa2f1dd870acfe2074c0cbf5 100644 --- a/tests/script/general/http/testSuite.sim +++ b/tests/script/general/http/testSuite.sim @@ -1,3 +1,5 @@ +run general/http/autocreate.sim +run general/http/chunked.sim run general/http/restful.sim run general/http/restful_insert.sim run general/http/restful_limit.sim diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index 063d11bd9d1d0a57629545e53cc350c5a553639c..adb22aa265a34b95f61f881984dedb007805a268 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -77,6 +77,8 @@ cd ../../../debug; make ./test.sh -f general/field/smallint.sim ./test.sh -f general/field/tinyint.sim +./test.sh -f general/http/autocreate.sim +./test.sh -f general/http/chunked.sim ./test.sh -f general/http/restful.sim ./test.sh -f general/http/restful_insert.sim ./test.sh -f general/http/restful_limit.sim diff --git a/tests/script/unique/http/admin.sim b/tests/script/unique/http/admin.sim index dc17520d02523a61658831bf7732eee43ddd7e89..8833397487aaca05342b7c41db6c979b6084ca97 100644 --- a/tests/script/unique/http/admin.sim +++ b/tests/script/unique/http/admin.sim @@ -33,25 +33,25 @@ print =============== step1 - login system_content curl 127.0.0.1:7111/admin/ print 1-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi system_content curl 127.0.0.1:7111/admin/xx print 2-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi system_content curl 127.0.0.1:7111/admin/login print 3-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi system_content curl 127.0.0.1:7111/admin/login/root print 4-> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi @@ -69,13 +69,13 @@ endi system_content curl -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.' -d 'show databases' 127.0.0.1:7111/admin/login/root/1 print 7-> $system_content -if $system_content != @{"status":"error","code":5010,"desc":"invalid type of Authorization"}@ then +if $system_content != @{"status":"error","code":4386,"desc":"invalid type of Authorization"}@ then return -1 endi system_content curl -H 'Authorization: Taosd eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ3d3cudGFvc2RhdGEuY29tIiwicGFzcyI6InRhb3NkYXRhIiwic3ViIjoicm9vdCJ9.xPv3b5odlR7YF8G_QWASjIRbMtA5v4ItToJ35fFgi' 127.0.0.1:7111/admin/login/root/1 print 8-> $system_content -if $system_content != @{"status":"error","code":5053,"desc":"parse http auth token error"}@ then +if $system_content != @{"status":"error","code":4389,"desc":"invalid taosd Authorization"}@ then return -1 endi @@ -105,7 +105,7 @@ endi system_content curl 127.0.0.1:7111/admin/logout print 11 -----> $system_content -if $system_content != @{"status":"error","code":5011,"desc":"no auth info input"}@ then +if $system_content != @{"status":"error","code":4357,"desc":"no auth info input"}@ then return -1 endi @@ -168,7 +168,7 @@ print =============== step7 - use dbs system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'use d1;' 127.0.0.1:7111/admin/all print 23-> $system_content -if $system_content != @{"status":"error","code":5017,"desc":"no need to execute use db cmd"}@ then +if $system_content != @{"status":"error","code":4360,"desc":"no need to execute use db cmd"}@ then return -1 endi diff --git a/tests/script/unique/http/opentsdb.sim b/tests/script/unique/http/opentsdb.sim index 4901c5b3fdf29ccf7e699594478d6ac189c080a2..526981716537ed8966e23fa3bc98662de0e06854 100644 --- a/tests/script/unique/http/opentsdb.sim +++ b/tests/script/unique/http/opentsdb.sim @@ -13,62 +13,62 @@ print ============================ dnode1 start print =============== step1 - parse system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/ print $system_content -if $system_content != @{"status":"error","code":5057,"desc":"database name can not be null"}@ then +if $system_content != @{"status":"error","code":4496,"desc":"database name can not be null"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db123456789012345678901234567890db print $system_content -if $system_content != @{"status":"error","code":5058,"desc":"database name too long"}@ then +if $system_content != @{"status":"error","code":4497,"desc":"database name too long"}@ then return -1 endi system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/ print $system_content -if $system_content != @{"status":"error","code":5057,"desc":"database name can not be null"}@ then +if $system_content != @{"status":"error","code":4496,"desc":"database name can not be null"}@ then return -1 endi system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put2 print $system_content -if $system_content != @{"status":"error","code":5009,"desc":"http url parse error"}@ then +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then return -1 endi system_content curl -u root:taosdata -d '[]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5060,"desc":"metrics size is 0"}@ then +if $system_content != @{"status":"error","code":4499,"desc":"metrics size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '[' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5059,"desc":"invalid opentsdb json fromat"}@ then +if $system_content != @{"status":"error","code":4498,"desc":"invalid opentsdb json fromat"}@ then return -1 endi system_content curl -u root:taosdata -d '{}' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5060,"desc":"metrics size is 0"}@ then +if $system_content != @{"status":"error","code":4499,"desc":"metrics size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '[{}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5062,"desc":"metric name not find"}@ then +if $system_content != @{"status":"error","code":4501,"desc":"metric name not find"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": 1,"timestamp": 1346846400,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5063,"desc":"metric name type should be string"}@ then +if $system_content != @{"status":"error","code":4502,"desc":"metric name type should be string"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "","timestamp": 1346846400,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5064,"desc":"metric name length is 0"}@ then +if $system_content != @{"status":"error","code":4503,"desc":"metric name length is 0"}@ then return -1 endi @@ -80,25 +80,25 @@ endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5066,"desc":"timestamp not find"}@ then +if $system_content != @{"status":"error","code":4505,"desc":"timestamp not find"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": "2","value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5067,"desc":"timestamp type should be integer"}@ then +if $system_content != @{"status":"error","code":4506,"desc":"timestamp type should be integer"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": -1,"value": 18,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5068,"desc":"timestamp value smaller than 0"}@ then +if $system_content != @{"status":"error","code":4507,"desc":"timestamp value smaller than 0"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"tags": {"host": "web01","group1": "1","dc": "lga"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5078,"desc":"value not find"}@ then +if $system_content != @{"status":"error","code":4517,"desc":"value not find"}@ then return -1 endi @@ -106,19 +106,19 @@ endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5069,"desc":"tags not find"}@ then +if $system_content != @{"status":"error","code":4508,"desc":"tags not find"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5070,"desc":"tags size is 0"}@ then +if $system_content != @{"status":"error","code":4509,"desc":"tags size is 0"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": 0}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5070,"desc":"tags size is 0"}@ then +if $system_content != @{"status":"error","code":4509,"desc":"tags size is 0"}@ then return -1 endi @@ -130,25 +130,25 @@ endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"": "web01"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5073,"desc":"tag name is null"}@ then +if $system_content != @{"status":"error","code":4512,"desc":"tag name is null"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host01123456789001123456789001123456789001123456789001123456789001123456789": "01"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5074,"desc":"tag name length too long"}@ then +if $system_content != @{"status":"error","code":4513,"desc":"tag name length too long"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host": "web011234567890011234567890011234567890011234567890011234567890011234567890011234567890011234567890"}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5077,"desc":"tag value can not more than 64"}@ then +if $system_content != @{"status":"error","code":4516,"desc":"tag value can not more than 64"}@ then return -1 endi system_content curl -u root:taosdata -d '[{"metric": "sys_cpu","timestamp": 1346846400,"value": 18,"tags": {"host": ""}}]' 127.0.0.1:7111/opentsdb/db/put print $system_content -if $system_content != @{"status":"error","code":5076,"desc":"tag value is null"}@ then +if $system_content != @{"status":"error","code":4515,"desc":"tag value is null"}@ then return -1 endi diff --git a/tests/test/c/CMakeLists.txt b/tests/test/c/CMakeLists.txt index e1fedaee3cecb8f55fa882c71b32ab49014bb5ea..ffab39d41c0170074687684c23dfdc9f57322d44 100644 --- a/tests/test/c/CMakeLists.txt +++ b/tests/test/c/CMakeLists.txt @@ -5,6 +5,12 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/plugins/http/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) IF (TD_LINUX) #add_executable(insertPerTable insertPerTable.c) @@ -28,6 +34,13 @@ IF (TD_LINUX) #add_executable(createNormalTable createNormalTable.c) #target_link_libraries(createNormalTable taos_static tutil common pthread) - add_executable(queryPerformance queryPerformance.c) - target_link_libraries(queryPerformance taos_static tutil common pthread) + #add_executable(queryPerformance queryPerformance.c) + #target_link_libraries(queryPerformance taos_static tutil common pthread) + + add_executable(httpTest httpTest.c) + target_link_libraries(httpTest taos_static tutil common pthread mnode monitor http tsdb twal vnode cJson lz4) + + add_executable(cacheTest cacheTest.c) + target_link_libraries(cacheTest taos_static tutil common pthread mnode monitor http tsdb twal vnode cJson lz4) ENDIF() + diff --git a/tests/test/c/cacheTest.c b/tests/test/c/cacheTest.c new file mode 100644 index 0000000000000000000000000000000000000000..54aca0038ed39d8d0294a5f88acd271c10f42319 --- /dev/null +++ b/tests/test/c/cacheTest.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include +#include "os.h" +#include "taos.h" +#include "tcache.h" +#include "tulog.h" +#include "tutil.h" + +#define MAX_REFRESH_TIME_SEC 2 +#define MAX_RANDOM_POINTS 20000 +#define GREEN "\033[1;32m" +#define NC "\033[0m" + +int32_t tsKeepTimeInSec = 3; +int32_t tsNumOfRows = 1000000; +int32_t tsSizeOfRow = 64 * 1024; +void * tsCacheObj = NULL; +int32_t destroyTimes = 0; + +typedef int64_t CacheTestKey; +typedef struct CacheTestRow { + int32_t index; + void ** ppRow; + void * data; +} CacheTestRow; + +CacheTestRow *initRow(int32_t index) { + CacheTestRow *row = calloc(sizeof(CacheTestRow), 1); + row->index = index; + row->data = malloc(tsSizeOfRow * sizeof(int8_t)); + return row; +} + +void detroyRow(void *data) { + CacheTestRow *row = *(CacheTestRow **)data; + free(row->data); + free(row); + destroyTimes++; + if (destroyTimes % 50000 == 0) { + pPrint("%s ===> destroyTimes:%d %s", GREEN, destroyTimes, NC); + } +} + +void initCache() { + tsCacheObj = taosCacheInit(TSDB_DATA_TYPE_BIGINT, MAX_REFRESH_TIME_SEC, true, detroyRow, "cachetest"); +} + +void putRowInCache() { + for (int index = 0; index < tsNumOfRows; ++index) { + CacheTestRow *row = initRow(index); + uint64_t key = (uint64_t)row; + void **ppRow = taosCachePut(tsCacheObj, &key, sizeof(int64_t), &row, sizeof(int64_t), tsKeepTimeInSec * 1000); + row->ppRow = ppRow; + taosCacheRelease(tsCacheObj, (void **)&ppRow, false); + } +} + +void cleanupCache() { + taosCacheCleanup(tsCacheObj); +} + +void initGetMemory() { + osInit(); + taos_init(); +} + +float getProcMemory() { + float procMemoryUsedMB = 0; + taosGetProcMemory(&procMemoryUsedMB); + return procMemoryUsedMB; +} + +void doTest() { + initCache(); + pPrint("%s initialize procMemory %f MB %s", GREEN, getProcMemory(), NC); + + putRowInCache(); + pPrint("%s insert %d rows, procMemory %f MB %s", GREEN, tsNumOfRows, getProcMemory(), NC); + + int32_t sleepMs = (MAX_REFRESH_TIME_SEC * 3) * 1000 + tsKeepTimeInSec * 1000; + taosMsleep(sleepMs); + pPrint("%s after sleep %d ms, procMemory %f MB %s", GREEN, sleepMs, getProcMemory(), NC); + + cleanupCache(); + taosMsleep(sleepMs); + pPrint("%s after cleanup cache, procMemory %f MB %s", GREEN, getProcMemory(), NC); + + malloc_trim(0); + taosMsleep(sleepMs); + pPrint("%s after malloc_trim, procMemory %f MB %s", GREEN, getProcMemory(), NC); +} + +void printHelp() { + char indent[10] = " "; + printf("Used to test the performance of cache\n"); + + printf("%s%s\n", indent, "-k"); + printf("%s%s%s%d\n", indent, indent, "KeepTimeInSec, default is ", tsKeepTimeInSec); + printf("%s%s\n", indent, "-n"); + printf("%s%s%s%d\n", indent, indent, "NumOfRows, default is ", tsNumOfRows); + printf("%s%s\n", indent, "-s"); + printf("%s%s%s%d\n", indent, indent, "SizeOfData, default is ", tsSizeOfRow); + + exit(EXIT_SUCCESS); +} + +void parseArgument(int argc, char *argv[]) { + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + printHelp(); + exit(0); + } else if (strcmp(argv[i], "-k") == 0) { + tsKeepTimeInSec = atoi(argv[++i]); + } else if (strcmp(argv[i], "-n") == 0) { + tsNumOfRows = atoi(argv[++i]); + } else if (strcmp(argv[i], "-s") == 0) { + tsSizeOfRow = atoi(argv[++i]); + } else { + } + } + + pPrint("%s KeepTimeInSec:%d %s", GREEN, tsKeepTimeInSec, NC); + pPrint("%s NumOfRows:%d %s", GREEN, tsNumOfRows, NC); + pPrint("%s SizeOfData:%d %s", GREEN, tsSizeOfRow, NC); +} + +int main(int argc, char *argv[]) { + initGetMemory(); + parseArgument(argc, argv); + doTest(); +} diff --git a/tests/test/c/httpTest.c b/tests/test/c/httpTest.c new file mode 100644 index 0000000000000000000000000000000000000000..261546770eed889894ec93cbbdfb2cdad9f4cad0 --- /dev/null +++ b/tests/test/c/httpTest.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "os.h" +#include "os.h" +#include "tglobal.h" +#include "taoserror.h" +#include "httpSystem.h" + +void signal_handler(int signum) { + httpStopSystem(); + httpCleanUpSystem(); + exit(EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) { + struct sigaction act; + act.sa_handler = signal_handler; + sigaction(SIGTERM, &act, NULL); + sigaction(SIGHUP, &act, NULL); + sigaction(SIGINT, &act, NULL); + sigaction(SIGABRT, &act, NULL); + + // Initialize the system + if (httpInitSystem() < 0) { + exit(EXIT_FAILURE); + } + + if (httpStartSystem() < 0) { + exit(EXIT_FAILURE); + } + + while (1) { + sleep(1000); + } +} diff --git a/tests/tsim/inc/sim.h b/tests/tsim/inc/sim.h index 6f3bc7099d306598da774fb9eeb6712e415ac1ce..58e58a442cedca564864578604faa6cea28ede68 100644 --- a/tests/tsim/inc/sim.h +++ b/tests/tsim/inc/sim.h @@ -84,6 +84,7 @@ enum { SIM_CMD_SQL, SIM_CMD_SQL_ERROR, SIM_CMD_SQL_SLOW, + SIM_CMD_RESTFUL, SIM_CMD_TEST, SIM_CMD_RETURN, SIM_CMD_END @@ -172,6 +173,7 @@ bool simExecuteReturnCmd(SScript *script, char *option); bool simExecuteSqlCmd(SScript *script, char *option); bool simExecuteSqlErrorCmd(SScript *script, char *rest); bool simExecuteSqlSlowCmd(SScript *script, char *option); +bool simExecuteRestfulCmd(SScript *script, char *rest); void simVisuallizeOption(SScript *script, char *src, char *dst); #endif \ No newline at end of file diff --git a/tests/tsim/src/simExe.c b/tests/tsim/src/simExe.c index adc2fd0b9d5624d86de296b6b9f80108938301a4..463dc33c7cc4f73e888fe5583b8311102fdd41b1 100644 --- a/tests/tsim/src/simExe.c +++ b/tests/tsim/src/simExe.c @@ -915,6 +915,47 @@ bool simExecuteSqlSlowCmd(SScript *script, char *rest) { return simExecuteSqlImpCmd(script, rest, isSlow); } +bool simExecuteRestfulCmd(SScript *script, char *rest) { + FILE *fp = NULL; + char filename[256]; + sprintf(filename, "%s/tmp.sql", tsScriptDir); + fp = fopen(filename, "w"); + if (fp == NULL) { + fprintf(stderr, "ERROR: failed to open file: %s\n", filename); + return false; + } + + char db[64] = {0}; + char tb[64] = {0}; + char gzip[32] = {0}; + int32_t ts; + int32_t times; + sscanf(rest, "%s %s %d %d %s", db, tb, &ts, ×, gzip); + + fprintf(fp, "insert into %s.%s values ", db, tb); + for (int i = 0; i < times; ++i) { + fprintf(fp, "(%d000, %d)", ts + i, ts); + } + fprintf(fp, " \n"); + fflush(fp); + fclose(fp); + + char cmd[1024] = {0}; + if (strcmp(gzip, "gzip") == 0) { + sprintf(cmd, + "curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' --header " + "--compressed --data-ascii @%s 127.0.0.1:7111/rest/sql", + filename); + } else { + sprintf(cmd, + "curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' --header " + "'Transfer-Encoding: chunked' --data-ascii @%s 127.0.0.1:7111/rest/sql", + filename); + } + + return simExecuteSystemCmd(script, cmd); +} + bool simExecuteSqlErrorCmd(SScript *script, char *rest) { char buf[3000]; SCmdLine *line = &script->lines[script->linePos]; diff --git a/tests/tsim/src/simParse.c b/tests/tsim/src/simParse.c index 8dcf83806f9588653041de343c2ba72e435d8e88..2e6121304f18022a74b9e4f09a8043b5b4beb909 100644 --- a/tests/tsim/src/simParse.c +++ b/tests/tsim/src/simParse.c @@ -721,6 +721,12 @@ bool simParseSqlSlowCmd(char *rest, SCommand *pCmd, int lineNum) { return true; } +bool simParseRestfulCmd(char *rest, SCommand *pCmd, int lineNum) { + simParseSqlCmd(rest, pCmd, lineNum); + cmdLine[numOfLines - 1].cmdno = SIM_CMD_RESTFUL; + return true; +} + bool simParseSystemCmd(char *rest, SCommand *pCmd, int lineNum) { int expLen; @@ -1020,6 +1026,14 @@ void simInitsimCmdList() { simCmdList[cmdno].executeCmd = simExecuteSqlSlowCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); + cmdno = SIM_CMD_RESTFUL; + simCmdList[cmdno].cmdno = cmdno; + strcpy(simCmdList[cmdno].name, "restful"); + simCmdList[cmdno].nlen = (int16_t)strlen(simCmdList[cmdno].name); + simCmdList[cmdno].parseCmd = simParseRestfulCmd; + simCmdList[cmdno].executeCmd = simExecuteRestfulCmd; + simAddCmdIntoHash(&(simCmdList[cmdno])); + /* test is only an internal command */ cmdno = SIM_CMD_TEST; simCmdList[cmdno].cmdno = cmdno;