From d386a555f2c57ccf5b11b0808c0e406a5dca3431 Mon Sep 17 00:00:00 2001 From: Yang Zhao Date: Sat, 11 Jun 2022 17:18:50 +0800 Subject: [PATCH] impr: add windows support for taos shell restful (#13721) * impr: add windows support for taos shell restful * fix: fix linux compile * fix: mac os x compile --- src/kit/shell/inc/shell.h | 14 +++-- src/kit/shell/src/shellDarwin.c | 67 +++++++++++++++++++++-- src/kit/shell/src/shellEngine.c | 43 ++------------- src/kit/shell/src/shellLinux.c | 36 +++++++++++- src/kit/shell/src/shellMain.c | 2 +- src/kit/shell/src/shellWindows.c | 94 ++++++++++++++++++++++++++++++-- 6 files changed, 202 insertions(+), 54 deletions(-) diff --git a/src/kit/shell/inc/shell.h b/src/kit/shell/inc/shell.h index 42516a5b66..1e2136a8ab 100644 --- a/src/kit/shell/inc/shell.h +++ b/src/kit/shell/inc/shell.h @@ -17,6 +17,9 @@ #define __SHELL__ #if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) #include +#else +#include +#pragma comment(lib,"ws2_32.lib") #endif #include "stdbool.h" #include "taos.h" @@ -46,8 +49,12 @@ typedef struct SShellArguments { char* timezone; bool restful; char* token; - int socket; - struct sockaddr_in serv_addr; +#ifdef WINDOWS + SOCKET socket; +#else + int socket; +#endif + TAOS* con; bool is_raw_time; bool is_use_passwd; @@ -84,9 +91,7 @@ void shellCheck(TAOS* con, SShellArguments* args); void get_history_path(char* history); void shellCheck(TAOS* con, SShellArguments* args); void cleanup_handler(void* arg); -int convertHostToServAddr(); char *last_strstr(const char *haystack, const char *needle); -void encode_base_64(char* base64_buf, char* user, char* password); void exitShell(); int shellDumpResult(TAOS_RES* con, char* fname, int* error_no, bool printMode); void shellGetGrantInfo(void* con); @@ -94,6 +99,7 @@ int isCommentLine(char* line); int wsclient_handshake(); int wsclient_conn(); void wsclient_query(char* command); +int tcpConnect(); /**************** Global variable declarations ****************/ extern char PROMPT_HEADER[]; diff --git a/src/kit/shell/src/shellDarwin.c b/src/kit/shell/src/shellDarwin.c index 97cca273f7..f5e5b87280 100644 --- a/src/kit/shell/src/shellDarwin.c +++ b/src/kit/shell/src/shellDarwin.c @@ -54,13 +54,16 @@ void printHelp() { printf("%s%s%s\n", indent, indent, "Script to run without enter the shell."); printf("%s%s\n", indent, "-d"); printf("%s%s%s\n", indent, indent, "Database to use when connecting to the server."); - printf("%s%s\n", indent, "-t"); + printf("%s%s\n", indent, "-z"); printf("%s%s%s\n", indent, indent, "Time zone of the shell, default is local."); printf("%s%s\n", indent, "-D"); printf("%s%s%s\n", indent, indent, "Use multi-thread to import all SQL files in the directory separately."); printf("%s%s\n", indent, "-T"); 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."); exit(EXIT_SUCCESS); } @@ -74,7 +77,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { // for host if (strcmp(argv[i], "-h") == 0) { if (i < argc - 1) { - arguments->host = argv[++i]; + 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); @@ -159,11 +170,11 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } } // For time zone - else if (strcmp(argv[i], "-t") == 0) { + else if (strcmp(argv[i], "-z") == 0) { if (i < argc - 1) { arguments->timezone = argv[++i]; } else { - fprintf(stderr, "option -t requires an argument\n"); + fprintf(stderr, "option -z requires an argument\n"); exit(EXIT_FAILURE); } } @@ -190,6 +201,20 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { exit(EXIT_FAILURE); } } + + else if (strcmp(argv[i], "-R") == 0) { + arguments->restful = true; + } + + else if (strcmp(argv[i], "-t") == 0) { + if (i < argc - 1) { + arguments->token = argv[++i]; + } else { + fprintf(stderr, "options -t requires an argument\n"); + exit(EXIT_FAILURE); + } + } + // For temperory command TODO else if (strcmp(argv[i], "--help") == 0) { printHelp(); @@ -547,3 +572,35 @@ void exitShell() { tcsetattr(0, TCSANOW, &oldtio); exit(EXIT_SUCCESS); } + +int tcpConnect() { + struct sockaddr_in serv_addr; + if (args.port == 0) { + args.port = 6041; + } + if (NULL == args.host) { + args.host = "localhost"; + } + + struct hostent *server = gethostbyname(args.host); + if ((server == NULL) || (server->h_addr == NULL)) { + fprintf(stderr, "no such host: %s\n", args.host); + return -1; + } + memset(&serv_addr, 0, sizeof(struct sockaddr_in)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(args.port); + memcpy(&(serv_addr.sin_addr.s_addr), server->h_addr, server->h_length); + args.socket = socket(AF_INET, SOCK_STREAM, 0); + if (args.socket < 0) { + fprintf(stderr, "failed to create socket\n"); + return -1; + } + int retConn = connect(args.socket, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)); + if (retConn < 0) { + fprintf(stderr, "failed to connect\n"); + close(args.socket); + return -1; + } + return 0; +} \ No newline at end of file diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index a18a172bb7..e3fc253936 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -74,17 +74,6 @@ void shellInit(SShellArguments *_args) { if (_args->restful) { _args->database = calloc(1, 128); - _args->socket = socket(AF_INET, SOCK_STREAM, 0); - if (_args->socket < 0) { - fprintf(stderr, "failed to create socket\n"); - exit(EXIT_FAILURE); - } - int retConn = connect(_args->socket, (struct sockaddr *)&(_args->serv_addr), sizeof(struct sockaddr)); - if (retConn < 0) { - fprintf(stderr, "failed to connect\n"); - close(_args->socket); - exit(EXIT_FAILURE); - } if (wsclient_handshake()) { exit(EXIT_FAILURE); } @@ -1159,30 +1148,6 @@ char *last_strstr(const char *haystack, const char *needle) { return res; } -int convertHostToServAddr() { - if (args.port == 0) { - args.port = 6041; - } - if (NULL == args.host) { - args.host = "127.0.0.1"; - } - struct hostent *server = gethostbyname(args.host); - if ((server == NULL) || (server->h_addr == NULL)) { - fprintf(stderr, "no such host: %s\n", args.host); - return -1; - } - memset(&(args.serv_addr), 0, sizeof(struct sockaddr_in)); - args.serv_addr.sin_family = AF_INET; - args.serv_addr.sin_port = htons(args.port); -#ifdef WINDOWS - args.serv_addr.sin_addr.s_addr = inet_addr(args.host); -#else - memcpy(&(args.serv_addr.sin_addr.s_addr), server->h_addr, server->h_length); -#endif - - return 0; -} - int wsclient_handshake() { char request_header[1024]; char recv_buf[1024]; @@ -1210,8 +1175,12 @@ int wsclient_handshake() { } ssize_t n = send(args.socket, request_header, strlen(request_header), 0); - if (n == 0) { - fprintf(stderr, "web socket handshake error\n"); + if (n <= 0) { +#ifdef WINDOWS + fprintf(stderr, "send failed with error: %d\n", WSAGetLastError()); +#else + fprintf(stderr, "web socket handshake error\n"); +#endif return -1; } n = recv(args.socket, recv_buf, 1023, 0); diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index 9e8edaa2bb..b9a8005ec7 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -53,8 +53,8 @@ static struct argp_option options[] = { {"pktlen", 'l', "PKTLEN", 0, "Packet length used for net test, default is 1000 bytes."}, {"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"}, + {"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}}; static error_t parse_opt(int key, char *arg, struct argp_state *state) { @@ -594,3 +594,35 @@ void exitShell() { taos_cleanup(); exit(EXIT_SUCCESS); } + +int tcpConnect() { + struct sockaddr_in serv_addr; + if (args.port == 0) { + args.port = 6041; + } + if (NULL == args.host) { + args.host = "localhost"; + } + + struct hostent *server = gethostbyname(args.host); + if ((server == NULL) || (server->h_addr == NULL)) { + fprintf(stderr, "no such host: %s\n", args.host); + return -1; + } + memset(&serv_addr, 0, sizeof(struct sockaddr_in)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(args.port); + memcpy(&(serv_addr.sin_addr.s_addr), server->h_addr, server->h_length); + args.socket = socket(AF_INET, SOCK_STREAM, 0); + if (args.socket < 0) { + fprintf(stderr, "failed to create socket\n"); + return -1; + } + int retConn = connect(args.socket, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)); + if (retConn < 0) { + fprintf(stderr, "failed to connect\n"); + close(args.socket); + return -1; + } + return 0; +} diff --git a/src/kit/shell/src/shellMain.c b/src/kit/shell/src/shellMain.c index ada90091e3..18edc6bdc0 100644 --- a/src/kit/shell/src/shellMain.c +++ b/src/kit/shell/src/shellMain.c @@ -156,7 +156,7 @@ int main(int argc, char* argv[]) { } if (args.restful) { - if (convertHostToServAddr()) { + if (tcpConnect()) { exit(EXIT_FAILURE); } } diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index f3f6c2b2e6..a3aa7a6fe4 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -54,7 +54,7 @@ void printHelp() { printf("%s%s%s\n", indent, indent, "Script to run without enter the shell."); printf("%s%s\n", indent, "-d"); printf("%s%s%s\n", indent, indent, "Database to use when connecting to the server."); - printf("%s%s\n", indent, "-t"); + printf("%s%s\n", indent, "-z"); printf("%s%s%s\n", indent, indent, "Time zone of the shell, default is local."); printf("%s%s\n", indent, "-n"); printf("%s%s%s\n", indent, indent, "Net role when network connectivity test, default is startup, options: client|server|rpc|startup|sync|speed|fqdn."); @@ -62,11 +62,14 @@ void printHelp() { printf("%s%s%s\n", indent, indent, "Packet length used for net test, default is 1000 bytes."); printf("%s%s\n", indent, "-N"); 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, "-S"); printf("%s%s%s\n", indent, indent, "Packet type used for net test, default is TCP."); printf("%s%s\n", indent, "-V"); printf("%s%s%s\n", indent, indent, "Print program version."); - exit(EXIT_SUCCESS); } @@ -77,7 +80,15 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { // for host if (strcmp(argv[i], "-h") == 0) { if (i < argc - 1) { - arguments->host = argv[++i]; + 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); @@ -172,11 +183,11 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { } } // For time zone - else if (strcmp(argv[i], "-t") == 0) { + else if (strcmp(argv[i], "-z") == 0) { if (i < argc - 1) { arguments->timezone = argv[++i]; } else { - fprintf(stderr, "option -t requires an argument\n"); + fprintf(stderr, "option -z requires an argument\n"); exit(EXIT_FAILURE); } } @@ -212,6 +223,20 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { exit(EXIT_FAILURE); } } + + else if (strcmp(argv[i], "-R") == 0) { + arguments->restful = true; + } + + else if (strcmp(argv[i], "-t") == 0) { + if (i < argc - 1) { + arguments->token = argv[++i]; + } else { + fprintf(stderr, "options -t requires an argument\n"); + exit(EXIT_FAILURE); + } + } + else if (strcmp(argv[i], "-V") == 0) { printVersion(); exit(EXIT_SUCCESS); @@ -337,3 +362,62 @@ void get_history_path(char *history) { } void exitShell() { exit(EXIT_SUCCESS); } + +int tcpConnect() { + int iResult; + WSADATA wsaData; + struct addrinfo *aResult = NULL, + *ptr = NULL, + hints; + if (args.port == 0) { + args.port = 6041; + } + if (NULL == args.host) { + args.host = "localhost"; + } + char port[10] = {0}; + + sprintf_s(port, 10, "%d", args.port); + + iResult = WSAStartup(MAKEWORD(2,2), &wsaData); + if (iResult != 0) { + printf("WSAStartup failed with error: %d\n", iResult); + return 1; + } + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + iResult = getaddrinfo(args.host, port, &hints, &aResult); + if ( iResult != 0 ) { + printf("getaddrinfo failed with error: %d\n", iResult); + WSACleanup(); + return 1; + } + + for(ptr=aResult; ptr != NULL ; ptr=ptr->ai_next) { + // Create a SOCKET for connecting to server + args.socket = socket(ptr->ai_family, ptr->ai_socktype, + ptr->ai_protocol); + if (args.socket == INVALID_SOCKET) { + printf("socket failed with error: %ld\n", WSAGetLastError()); + WSACleanup(); + return 1; + } + + // Connect to server. + iResult = connect( args.socket, ptr->ai_addr, (int)ptr->ai_addrlen); + if (iResult == SOCKET_ERROR) { + closesocket(args.socket); + args.socket = INVALID_SOCKET; + continue; + } + break; + } + if (args.socket == INVALID_SOCKET) { + printf("Unable to connect to server!\n"); + WSACleanup(); + return 1; + } + return 0; +} \ No newline at end of file -- GitLab