diff --git a/src/kit/shell/inc/shell.h b/src/kit/shell/inc/shell.h index 1e2136a8abefc44daa29e10d48af7f95a350bda1..d85354c1019aab68f546469fade7aa751cb47415 100644 --- a/src/kit/shell/inc/shell.h +++ b/src/kit/shell/inc/shell.h @@ -48,13 +48,11 @@ typedef struct SShellArguments { char* database; char* timezone; bool restful; - char* token; #ifdef WINDOWS SOCKET socket; #else int socket; #endif - TAOS* con; bool is_raw_time; bool is_use_passwd; @@ -70,6 +68,8 @@ typedef struct SShellArguments { int pktNum; char* pktType; char* netTestRole; + char* cloudDsn; + bool cloud; } SShellArguments; typedef enum WS_ACTION_TYPE_S { WS_CONN, WS_QUERY, WS_FETCH, WS_FETCH_BLOCK } WS_ACTION_TYPE; diff --git a/src/kit/shell/src/shellDarwin.c b/src/kit/shell/src/shellDarwin.c index f5e5b8728011d102090caf0cb00c3b316e93028a..d73970123aff65f9ed66b37a5803b1ccc9a4eb7f 100644 --- a/src/kit/shell/src/shellDarwin.c +++ b/src/kit/shell/src/shellDarwin.c @@ -62,8 +62,8 @@ void printHelp() { printf("%s%s%s\n", indent, indent, "Number of threads when using multi-thread to import data."); printf("%s%s\n", indent, "-R"); printf("%s%s%s\n", indent, indent, "Connect and interact with TDengine use restful."); - printf("%s%s\n", indent, "-t"); - printf("%s%s%s\n", indent, indent, "The token to use when connecting TDengine's cloud services."); + printf("%s%s\n", indent, "-E"); + printf("%s%s%s\n", indent, indent, "The DSN to use when connecting TDengine's cloud services."); exit(EXIT_SUCCESS); } @@ -76,20 +76,13 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { for (int i = 1; i < argc; i++) { // for host if (strcmp(argv[i], "-h") == 0) { - if (i < argc - 1) { - char* arg = argv[++i]; - char* tmp = strstr(arg, ":"); - if (tmp == NULL) { - arguments->host = arg; - } else if ((tmp + 1) != NULL) { - arguments->port = atoi(tmp + 1); - tmp[0] = '\0'; - arguments->host = arg; - } - } else { - fprintf(stderr, "option -h requires an argument\n"); - exit(EXIT_FAILURE); - } + if (i < argc - 1) { + arguments->cloud = false; + arguments->host = argv[++i]; + } else { + fprintf(stderr, "option -h requires an argument\n"); + exit(EXIT_FAILURE); + } } // for password else if ((strncmp(argv[i], "-p", 2) == 0) @@ -116,6 +109,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { // for management port else if (strcmp(argv[i], "-P") == 0) { if (i < argc - 1) { + arguments->cloud = false; arguments->port = atoi(argv[++i]); } else { fprintf(stderr, "option -P requires an argument\n"); @@ -132,6 +126,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } } else if (strcmp(argv[i], "-c") == 0) { if (i < argc - 1) { + arguments->cloud = false; if (strlen(argv[++i]) >= TSDB_FILENAME_LEN) { fprintf(stderr, "config file path: %s overflow max len %d\n", argv[i], TSDB_FILENAME_LEN - 1); exit(EXIT_FAILURE); @@ -203,14 +198,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } else if (strcmp(argv[i], "-R") == 0) { + arguments->cloud = false; arguments->restful = true; } - else if (strcmp(argv[i], "-t") == 0) { + else if (strcmp(argv[i], "-E") == 0) { if (i < argc - 1) { - arguments->token = argv[++i]; + arguments->cloudDsn = argv[++i]; } else { - fprintf(stderr, "options -t requires an argument\n"); + fprintf(stderr, "options -E requires an argument\n"); exit(EXIT_FAILURE); } } @@ -225,6 +221,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { exit(EXIT_FAILURE); } } + if (args.cloudDsn == NULL) { + if (args.cloud) { + args.cloudDsn = getenv("TDENGINE_CLOUD_DSN"); + if (args.cloudDsn == NULL) { + args.cloud = false; + } + } + } else { + args.cloud = true; + } } int32_t shellReadCommand(TAOS *con, char *command) { diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index e3fc2539366508d34bb2a4657fcf17c360b28679..b099f71fd6e22505e2c6d8d8cd279d365f8ad931 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -72,8 +72,7 @@ void shellInit(SShellArguments *_args) { _args->user = TSDB_DEFAULT_USER; } - if (_args->restful) { - _args->database = calloc(1, 128); + if (_args->restful || _args->cloud) { if (wsclient_handshake()) { exit(EXIT_FAILURE); } @@ -159,7 +158,7 @@ static int32_t shellRunSingleCommand(TAOS *con, char *command) { // Analyse the command. if (regex_match(command, "^[ \t]*(quit|q|exit)[ \t;]*$", REG_EXTENDED | REG_ICASE)) { - if (args.restful) { + if (args.restful || args.cloud) { close(args.socket); } else { taos_close(con); @@ -290,7 +289,7 @@ void shellRunCommandOnServer(TAOS *con, char command[]) { printMode = true; // When output to a file, the switch does not work. } - if (args.restful) { + if (args.restful || args.cloud) { wsclient_query(command); return; } @@ -1161,12 +1160,39 @@ int wsclient_handshake() { key_nonce[i] = rand() & 0xff; } taos_base64_encode(key_nonce, 16, websocket_key, 256); - if (args.token) { - snprintf(request_header, 1024, - "GET /rest/ws?token=%s HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: " - "%s:%d\r\nSec-WebSocket-Key: " - "%s\r\nSec-WebSocket-Version: 13\r\n\r\n", - args.token, args.host, args.port, websocket_key); + if (args.cloud) { + if (args.cloudDsn == NULL) { + fprintf(stderr, "Cannot read cloud service info\n"); + return -1; + } else { + char* start = strstr(args.cloudDsn, "http://"); + if (start != NULL) { + args.cloudDsn = start + strlen("http://"); + } else { + start = strstr(args.cloudDsn, "https://"); + if (start != NULL) { + args.cloudDsn = start + strlen("https://"); + } + } + char* port = strstr(args.cloudDsn, ":"); + if ((port == NULL) || (port + 1) == NULL) { + fprintf(stderr, "Invalid format in TDengine cloud dsn: %s\n", args.cloudDsn); + return -1; + } + port[0] = '\0'; + char* token = strstr(port+ strlen(":"), "?token="); + if ((token == NULL) || (token + strlen("?token=")) == NULL) { + fprintf(stderr, "Invalid format in TDengine cloud dsn: %s\n", args.cloudDsn); + return -1; + } + token[0] = '\0'; + snprintf(request_header, 1024, + "GET /rest/ws?token=%s HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: " + "%s:%s\r\nSec-WebSocket-Key: " + "%s\r\nSec-WebSocket-Version: 13\r\n\r\n", + token + strlen("?token="), args.cloudDsn, port + strlen(":"), websocket_key); + } + } else { snprintf(request_header, 1024, "GET /rest/ws HTTP/1.1\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nHost: %s:%d\r\nSec-WebSocket-Key: " @@ -1267,9 +1293,9 @@ int wsclient_send_sql(char *command, WS_ACTION_TYPE type, int id) { switch (type) { case WS_CONN: cJSON_AddStringToObject(json, "action", "conn"); - cJSON_AddStringToObject(_args, "user", "root"); - cJSON_AddStringToObject(_args, "password", "taosdata"); - cJSON_AddStringToObject(_args, "db", ""); + cJSON_AddStringToObject(_args, "user", args.user); + cJSON_AddStringToObject(_args, "password", args.password); + cJSON_AddStringToObject(_args, "db", args.database); break; case WS_QUERY: @@ -1322,6 +1348,12 @@ int wsclient_conn() { } if (code->valueint == 0) { cJSON_Delete(root); + if (args.cloud) { + fprintf(stdout, "Successfully connect to cloud service in restful mode\n"); + } else { + fprintf(stdout, "Successfully connect to %s in restful mode\n", args.host); + } + return 0; } else { cJSON *message = cJSON_GetObjectItem(root, "message"); @@ -1587,4 +1619,4 @@ void wsclient_query(char *command) { } cJSON_Delete(query); return; -} +} \ No newline at end of file diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index b9a8005ec71749a2ec256db3174449066d3fa241..9843a24dadb0dd753c66c89ba2c6e94a24da2673 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -54,7 +54,7 @@ static struct argp_option options[] = { {"pktnum", 'N', "PKTNUM", 0, "Packet numbers used for net test, default is 100."}, {"pkttype", 'S', "PKTTYPE", 0, "Choose packet type used for net test, default is TCP. Only speed test could be either TCP or UDP."}, {"restful", 'R', 0, 0, "Connect and interact with TDengine use restful."}, - {"token", 't', "TOKEN", 0, "The token to use when connecting TDengine's cloud services."}, + {0, 'E', "DSN", 0, "The DSN to use when connecting TDengine's cloud services."}, {0}}; static error_t parse_opt(int key, char *arg, struct argp_state *state) { @@ -64,21 +64,20 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { wordexp_t full_path; switch (key) { - case 'h':{ - char* tmp = strstr(arg, ":"); - if (tmp == NULL) { - arguments->host = arg; - } else if ((tmp + 1) != NULL) { - arguments->port = atoi(tmp + 1); - tmp[0] = '\0'; - arguments->host = arg; - } - break; - } + case 'h': + if (arg) { + args.cloud = false; + args.host = arg; + } else { + fprintf(stderr, "Invalid host\n"); + return -1; + } + break; case 'p': break; case 'P': if (arg) { + args.cloud = false; tsDnodeShellPort = atoi(arg); p_port = atoi(arg); } else { @@ -106,6 +105,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { wordfree(&full_path); return -1; } + args.cloud = false; tstrncpy(configDir, full_path.we_wordv[0], TSDB_FILENAME_LEN); wordfree(&full_path); break; @@ -173,11 +173,17 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case OPT_ABORT: arguments->abort = 1; break; - case 't': - arguments->token = arg; - break; case 'R': arguments->restful = true; + arguments->cloud = false; + break; + case 'E': + if (arg) { + arguments->cloudDsn = arg; + } else { + fprintf(stderr, "Invalid -E option\n"); + return -1; + } break; default: return ARGP_ERR_UNKNOWN; @@ -231,8 +237,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } argp_parse(&argp, argc, argv, 0, 0, arguments); - if (arguments->token == NULL) { - arguments->port = p_port; + + if (args.cloudDsn == NULL) { + if (args.cloud) { + args.cloudDsn = getenv("TDENGINE_CLOUD_DSN"); + if (args.cloudDsn == NULL) { + args.cloud = false; + } + } + } else { + args.cloud = true; } if (arguments->abort) { diff --git a/src/kit/shell/src/shellMain.c b/src/kit/shell/src/shellMain.c index 18edc6bdc0bb53e4469fb7613b05f837a6f95f0b..6fc27dde6aef17dc7f9f62d3eb1705257a42e116 100644 --- a/src/kit/shell/src/shellMain.c +++ b/src/kit/shell/src/shellMain.c @@ -76,7 +76,6 @@ SShellArguments args = {.host = NULL, .database = NULL, .timezone = NULL, .restful = false, - .token = NULL, .is_raw_time = false, .is_use_passwd = false, .dump_config = false, @@ -87,7 +86,10 @@ SShellArguments args = {.host = NULL, .pktLen = 1000, .pktNum = 100, .pktType = "TCP", - .netTestRole = NULL}; + .netTestRole = NULL, + .cloudDsn = NULL, + .cloud = true, + }; /* * Main function. @@ -102,35 +104,6 @@ int main(int argc, char* argv[]) { exit(EXIT_FAILURE); } - char* cloud_url = getenv("TDENGINE_CLOUD_URL"); - if (cloud_url != NULL) { - char* start = strstr(cloud_url, "http://"); - if (start != NULL) { - cloud_url = start + strlen("http://"); - } else { - start = strstr(cloud_url, "https://"); - if (start != NULL) { - cloud_url = start + strlen("https://"); - } - } - - char* tmp = last_strstr(cloud_url, ":"); - if ((tmp == NULL) && ((tmp + 1) != NULL )) { - fprintf(stderr, "Invalid format in environment variable TDENGINE_CLOUD_URL: %s\n", cloud_url); - exit(EXIT_FAILURE); - } else { - args.port = atoi(tmp + 1); - tmp[0] = '\0'; - args.host = cloud_url; - } - } - - char* cloud_token = getenv("TDENGINE_CLOUD_TOKEN"); - - if (cloud_token != NULL) { - args.token = cloud_token; - } - shellParseArgument(argc, argv, &args); if (args.dump_config) { @@ -155,7 +128,7 @@ int main(int argc, char* argv[]) { exit(0); } - if (args.restful) { + if (args.restful || args.cloud) { if (tcpConnect()) { exit(EXIT_FAILURE); } diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index a3aa7a6fe4894583763776ac14c46e53e2610252..2fdbcfd5c2fbea3d36d0ba85b720d0e334589e94 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -64,8 +64,8 @@ void printHelp() { printf("%s%s%s\n", indent, indent, "Packet numbers used for net test, default is 100."); printf("%s%s\n", indent, "-R"); printf("%s%s%s\n", indent, indent, "Connect and interact with TDengine use restful."); - printf("%s%s\n", indent, "-t"); - printf("%s%s%s\n", indent, indent, "The token to use when connecting TDengine's cloud services."); + printf("%s%s\n", indent, "-E"); + printf("%s%s%s\n", indent, indent, "The DSN to use when connecting TDengine's cloud services."); printf("%s%s\n", indent, "-S"); printf("%s%s%s\n", indent, indent, "Packet type used for net test, default is TCP."); printf("%s%s\n", indent, "-V"); @@ -80,15 +80,8 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { // for host if (strcmp(argv[i], "-h") == 0) { if (i < argc - 1) { - char* arg = argv[++i]; - char* tmp = strstr(arg, ":"); - if (tmp == NULL) { - arguments->host = arg; - } else if ((tmp + 1) != NULL) { - arguments->port = atoi(tmp + 1); - tmp[0] = '\0'; - arguments->host = arg; - } + arguments->cloud = false; + arguments->host = argv[++i]; } else { fprintf(stderr, "option -h requires an argument\n"); exit(EXIT_FAILURE); @@ -119,6 +112,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { // for management port else if (strcmp(argv[i], "-P") == 0) { if (i < argc - 1) { + arguments->cloud = false; arguments->port = atoi(argv[++i]); } else { fprintf(stderr, "option -P requires an argument\n"); @@ -142,6 +136,7 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } } else if (strcmp(argv[i], "-c") == 0) { if (i < argc - 1) { + arguments->cloud = false; char *tmp = argv[++i]; if (strlen(tmp) >= TSDB_FILENAME_LEN) { fprintf(stderr, "config file path: %s overflow max len %d\n", tmp, TSDB_FILENAME_LEN - 1); @@ -225,14 +220,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } else if (strcmp(argv[i], "-R") == 0) { + arguments->cloud = false; arguments->restful = true; } - else if (strcmp(argv[i], "-t") == 0) { + else if (strcmp(argv[i], "-E") == 0) { if (i < argc - 1) { - arguments->token = argv[++i]; + arguments->cloudDsn = argv[++i]; } else { - fprintf(stderr, "options -t requires an argument\n"); + fprintf(stderr, "options -E requires an argument\n"); exit(EXIT_FAILURE); } } @@ -251,6 +247,16 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { exit(EXIT_FAILURE); } } + if (args.cloudDsn == NULL) { + if (args.cloud) { + args.cloudDsn = getenv("TDENGINE_CLOUD_DSN"); + if (args.cloudDsn == NULL) { + args.cloud = false; + } + } + } else { + args.cloud = true; + } } void shellPrintContinuePrompt() { printf("%s", CONTINUE_PROMPT); }