sdk-hwV1.3/lichee/xr806/appos/project/common/cmd/cmd_nopoll.c

949 lines
29 KiB
C
Executable File

/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if PRJCONF_NET_EN
#include "cmd_util.h"
#include "net/nopoll/nopoll.h"
static const char websockets_ca_cert[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIC6zCCAdMCFELncsTSBAsyNRBc/4V2/QXlLdQ8MA0GCSqGSIb3DQEBBQUAMDIx\r\n"
"MDAuBgNVBAoMJ1RMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0\r\n"
"eTAeFw0xOTA3MTUwNjMzMzhaFw0zMzAzMjMwNjMzMzhaMDIxMDAuBgNVBAoMJ1RM\r\n"
"UyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZI\r\n"
"hvcNAQEBBQADggEPADCCAQoCggEBAKXfNjrZaQgbQgHnf+8fnkVou9g6iRofZcjy\r\n"
"HT97qUQrInSUo062+2nqFyfhsrDJU5oGHRUPaCXS9SyEregqa+6XqbMRLvL9Qf/8\r\n"
"NO0rsroqz+fQIIW8i6kxE/9s9/4csJDk7WPxV/ncG2bcHoYf9wiN6AR6hA+h4bZj\r\n"
"Cjt4qGQ23BhwIOLWrIBHq9yTfgQ2Nys01m35FvIjzSwzjQXaEcMJNy20fcmhvAr9\r\n"
"CXhPCm8np7zhbgs6SS7jUpg+9tmLypJ6JUB4GeSIAk62VlixJe+9ku4SxP9beO1/\r\n"
"YpxbcKE9Ubl01z1A6KDOzox7XReqv9iAgu03x+nDv5j9p+0SEi8CAwEAATANBgkq\r\n"
"hkiG9w0BAQUFAAOCAQEAoBYa7wGU5buBQbXRW7HYsu47mOAd2gd/ezMunV+L/ENQ\r\n"
"9IAfFJy9p816fpHShoQuQsf7RV6R/UTu/2c272/clfqanyEDFL1MupvQ7SDY+lyK\r\n"
"ofwz1H7ajWVeGBtPKtFc5btsgW6xtQIwOlHKRNI8BPP5qOrsvcwfipJ4jYlEBSGS\r\n"
"l+tIr0xpuBO0hEcG97jdoe3KpFZ0APW2C4xh8ctW1CArRVnezdCULnWFdKpdhQAY\r\n"
"ssuB2CL76qRa8l6ZZj5gUEa3IgRCj3UisBvNCMV63EhfJd/0mLv1OWqx9GPwQgMa\r\n"
"A3VSOLvHqch6Da88e6wE5irwZoCZLrUMCuS5mrOQTQ==\r\n"
"-----END CERTIFICATE-----\r\n";
/* use for two-phase verification */
static const char websockets_client_cert[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIC/DCCAeQCFFk4HVa42niSzTZbbPwh49UZW3rHMA0GCSqGSIb3DQEBBQUAMDIx\r\n"
"MDAuBgNVBAoMJ1RMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0\r\n"
"eTAeFw0xOTA3MTUwNjMzMzhaFw0zMzAzMjMwNjMzMzhaMEMxJzAlBgNVBAoMHlRM\r\n"
"UyBQcm9qZWN0IERldmljZSBDZXJ0aWZpY2F0ZTEYMBYGA1UEAwwPMTkyLjE2OC4x\r\n"
"MTEuMTAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxY05JdapYr6B\r\n"
"ohID4gFxh5ANvqGtTqTdfmeZSQIPzA3b6kTHF+HbMw0FGaKCd2Minah4IlWHq5mE\r\n"
"9jpggj3UxqEcdmCDzBV2bbj+ZA8XdtB7oqeb+6Bt+Gqxi83RDEQpDI/nwwWrGahu\r\n"
"6YXF+PXlJQC3YasW/JrQDJY9VMf1nyGf3FN5TJQ4HJ6eHWsXhwNUCSwE6e4ol+V6\r\n"
"GO2coFukOmQDQ2KgK7MYMKF9YTbusvaSIx1AbmJCfszoudUolbnlVIYIh98g2z7X\r\n"
"p1ki0Vtr0UnrK3qBYVlPXWq+d4hbtgL9rNoR4mSrp9k4QvdChwkZ4szblwkMZ7Xf\r\n"
"wB2qBYO2LwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAl0ui4I0cCtZ9q1el7ACS4\r\n"
"y9ph8aD0WsosQlHl6sjIQOMIU0dH9xSyELaST7UzGauOXx4sWnxWb6NhtB1huC0l\r\n"
"eRZgHqnHMqioxDTb2LPB1rA/B4ntzVkOBzoi44xuL3LFhQap8UMm+1oYJi+WSGsF\r\n"
"3qwIkju1VmL6b85P6xKBoC8N9jLKGVVUFBZ0gCUT+vCsb8fcoiQWqAGXkrz1RWEp\r\n"
"9CEFH1AQYHiRlZOb0lIPizI5Zo29GsPWbj0yai4/vI+q7uYs67Q3Yjd6V8tSu8AC\r\n"
"npskXlMqLl76F1SkD4SEBj57eB40Llm7WSfXPx182naZdHzsKpFzDkjod6MlCWCS\r\n"
"-----END CERTIFICATE-----\r\n";
/* use for two-phase verification */
static const char websockets_client_key[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEpAIBAAKCAQEAxY05JdapYr6BohID4gFxh5ANvqGtTqTdfmeZSQIPzA3b6kTH\r\n"
"F+HbMw0FGaKCd2Minah4IlWHq5mE9jpggj3UxqEcdmCDzBV2bbj+ZA8XdtB7oqeb\r\n"
"+6Bt+Gqxi83RDEQpDI/nwwWrGahu6YXF+PXlJQC3YasW/JrQDJY9VMf1nyGf3FN5\r\n"
"TJQ4HJ6eHWsXhwNUCSwE6e4ol+V6GO2coFukOmQDQ2KgK7MYMKF9YTbusvaSIx1A\r\n"
"bmJCfszoudUolbnlVIYIh98g2z7Xp1ki0Vtr0UnrK3qBYVlPXWq+d4hbtgL9rNoR\r\n"
"4mSrp9k4QvdChwkZ4szblwkMZ7XfwB2qBYO2LwIDAQABAoIBAQCtbkjwdh7oqHTo\r\n"
"EsbD4B6KM6ZNaGTcuRIWyd6hYKT7sGMTrOPYjJjCnbiPg8LkCu012dP12H6t4K4A\r\n"
"+MkHLj8hTgnNxveN8H2y4Ai9UR55WZhg+KKQ6owA3bIXGU5gZWpgM+n0pYJLmTod\r\n"
"2yotYbqUnKdhoDEi/MqPckpPpuh0lSVXOGBf88Cl1A3WGqhPn/fvMAGAMEuayCU9\r\n"
"NxsK9K05OBox9+CuJX9Gfhx0vcC4cB0HQfLzpAOe5j6W/FhYb39sZCalNSx/9sKt\r\n"
"uxTGiiQrmPJ9mGtY6x0ksPvmZGIKmh6YdNIZ+MQlE5iDf1mYr4SuzuLBpuU6rDEI\r\n"
"1zKV6Ih5AoGBAPL5cNV9QZNSGg/bS5hBzKnyOdubSg0nkFXPA2lqfz2uwQ9c0DYl\r\n"
"5TF2JExGy7YpUWiJCuXjmcNO6ck5QTo8K3M17zikcthOxEtM0cZDHnSWcWLz+EiO\r\n"
"XiK9VMyJZqb2ZivEHPyzjxffE6rvPVN/vYMaKt5Mdw6Jzh8cGPzZjIqFAoGBANAk\r\n"
"Z6rXzrEwbNv9YGiXFj9gnbLTcfVLDlropL9Hf/dxWP8PQxBeyvZ3XfvFxpWI/MU5\r\n"
"hdj3c+AvkB//5AUcHU0K5vE8Sv+M2e7bsFxyMYuVybXlpvqwt9zOpzw5x7xlreRE\r\n"
"/xVpKbUO3YKCjrqeOsJtVOeEhYwK4hAcygD/y44jAoGAAKYX3goSlcEfXrF4NzTd\r\n"
"xgpmiyaUAQr9AK2n1a06H8EKtO7Lg4mAXixxll6OBrN/iybqh4ifDX11dFsZyH0G\r\n"
"pK0dMWqG//rd3VGcMcpWF3ubW+dI33C54Z/dzRoE0ydPSIiihy43kJnA5LD02fc6\r\n"
"W1JDkQplOv21NjIOAwbVsD0CgYBeG0efz8kNBecCI/I197HAX++NDdrlW9UWtz7d\r\n"
"mPc7qkzhrUXWHfXIL7oXfplFvNUEWviwW1lR0E9qmGjBArAgyEAYa/lAx681NrDr\r\n"
"a1oJUWUMz9OKXuISfIDSUxGClbpkjemDBbQsv5bZTiw4JhhNFd+geaNj6PvC6zFN\r\n"
"+FlRXwKBgQDBWxw6FPL/q+AP+B+RNde9pueVHQFx0hZM57K7jjddoVOTo1f98TM/\r\n"
"51b2QXR65Rl08c4tkvDqtf3jT3LeRsvgazfXNyDTp0C2BQ+ocXhyvQ2Har8z+ujs\r\n"
"0h9L+vHw1lUzfFrda7igD2XZDvJEgOlTQ4FQRcTxRSu7A5QSi8WQOg==\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
static const char websockets_server_cert[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIC6DCCAdACFFk4HVa42niSzTZbbPwh49UZW3rGMA0GCSqGSIb3DQEBBQUAMDIx\r\n"
"MDAuBgNVBAoMJ1RMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0\r\n"
"eTAeFw0xOTA3MTUwNjMzMzhaFw0zMzAzMjMwNjMzMzhaMC8xFDASBgNVBAoMC1RM\r\n"
"UyBQcm9qZWN0MRcwFQYDVQQDDA4xOTIuMTY4LjUxLjEwMDCCASIwDQYJKoZIhvcN\r\n"
"AQEBBQADggEPADCCAQoCggEBANdysGO5RWrQnzmBQbA7GfopxWXrdtNGMqOp4410\r\n"
"jGVyAd8r5Md8JVK2uUBAZrOEiiFj8LcSaR1T5oPnE5pOEWCxD3wziGNJCjEAeeQx\r\n"
"MASL5Ua2YUk5164qiUqOJcNIJHMXfQ+5BDCIfDCRAqAdJBHFcw6r0c+HKd9FTWMU\r\n"
"JyFHrAemcfCJFbZqPSFej/oYesqV06bP1ox30X31qM1hLn0olUnIEkFAU2p4jL7u\r\n"
"rJfWT3GgEpwjp0FXq8ByMg7ib/zzh8A/JruboHk4wj5uFhbsdDluCXD25AjCtJDI\r\n"
"N/DnnmHMFcvM/KVP0t98iNkOPy50vrErMEKTefA/WqGYpecCAwEAATANBgkqhkiG\r\n"
"9w0BAQUFAAOCAQEAJiGCUmrBTc0GnxIM3VmZEKK64uUHyhndLE1lSDO/gAi6S7Di\r\n"
"5Sh2Q7OQ9d8h/vV8B31BeYZKA0tLSRYWznbYtvGVszVnCJpQ1rBnq+Wk670F/4iM\r\n"
"Nihae7FHHAZ3tHUhL5NPMjK/m+0fp19KvNYIEBecm/E7Am06nCzKV7rDgLPMmWNC\r\n"
"CW07/ViXCQSYUOQoSijaxcjxzD+mCCf38vD0qQ3XR2un/+Ny9tZwzqj6VcaDSvy+\r\n"
"JVaFJFwMIe0P+hHbOTSrpaJ8C0H+Tem72UNRImwe5KX6SP+VFlOQV31HFj3G5rKb\r\n"
"zT81oxV8CdSZSxbsWWXDtiaCEGr6ioq78t7Kqw==\r\n"
"-----END CERTIFICATE-----\r\n";
static const char websockets_server_key[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEpAIBAAKCAQEA13KwY7lFatCfOYFBsDsZ+inFZet200Yyo6njjXSMZXIB3yvk\r\n"
"x3wlUra5QEBms4SKIWPwtxJpHVPmg+cTmk4RYLEPfDOIY0kKMQB55DEwBIvlRrZh\r\n"
"STnXriqJSo4lw0gkcxd9D7kEMIh8MJECoB0kEcVzDqvRz4cp30VNYxQnIUesB6Zx\r\n"
"8IkVtmo9IV6P+hh6ypXTps/WjHfRffWozWEufSiVScgSQUBTaniMvu6sl9ZPcaAS\r\n"
"nCOnQVerwHIyDuJv/POHwD8mu5ugeTjCPm4WFux0OW4JcPbkCMK0kMg38OeeYcwV\r\n"
"y8z8pU/S33yI2Q4/LnS+sSswQpN58D9aoZil5wIDAQABAoIBAFOr6u0PyvHMy8md\r\n"
"dVFn4pLRHiSS6bbrkEcXd5Q8KzpKqIdvmI4QnL4e0JsvZ7NYSfzlv1qZ/9CwANpB\r\n"
"J8/Jed4/ZXAq41EL0LVvJeeFYsyhOA3aTrYNjMHLKz6VLf1FS0KXYK52gDYJC5Ig\r\n"
"/xAHwTZVpHWSLQ2XxJ89XuyXqwq1AKJ3dLK8RdDAeIbaZ50cR4OfLUU04uuBJ6zC\r\n"
"QKpfiDjf0BM4VGLJZP1uMTvfHFZhUU8b/FQjaHZ7My1EBSffpCnVy0edJnkxKn3E\r\n"
"xs++0nb7xjDhUrp9CkTTfMxrvRmUWSni09P1SCD26TUnBXqjQ9QX3DewAGKLOJaT\r\n"
"JbeMDOECgYEA7MPT6d6f2iBOr3qdx9VREQsbljXtGSCxlwWnfCS5nrC93csXZ95e\r\n"
"5NDd4S9hf328FTYszT7Z+HjJvL8az1owT8IFhLDwa62N1c0rlcwuLNGkzX5WsxgF\r\n"
"5Hzn38u3nUzOVV7ltFeVeMrVobrXf8p5IegAiARjzi/JWnyHlSRWxlsCgYEA6POE\r\n"
"aIFtEcY+OJD1LhkShWOE2jk46rgN+KufbhIaKIRwvftoNev5sczeZSII7fZHXx8I\r\n"
"dYWF56c+x4hKH+u52aW6Qvmod/aur11ncyE0bDWlqb3fQcpcAmJRLdh95pY+g1N8\r\n"
"ZAqDwUQY99nuMSb0uPELFSpsS7f9EOj1UwpqbGUCgYAFsnyh7wp3rDlYfaHYUii+\r\n"
"OT8zsR6AcUn0sV0jXprc17Hp6V4p0K8F4ITGS2aUM8lX1VLkqXODSBzKnuqdPLVW\r\n"
"5ftOAxf171ovX92BoEUoLO9DRpv9eUGDCwJlXziO329DnKH4YfclzfOwDZfr6kpZ\r\n"
"54RDwZ9JMdstgzub+iDgawKBgQCusWfbYyvjB3LDwtlK75x3EZGggQcQ5mP71uBh\r\n"
"kAuz1NYjcrTMsyD2WDdzShm+MlGFoOUcFLy9YytuQOOtmn4uHN1Yupa/F+waMIaS\r\n"
"zRTeDUEl0PDrCpEDbK2KHu8TjBpnK6V99HCn76R1wiWhEKC3THRONBkwk1KhasIG\r\n"
"uyniDQKBgQDFL9bjpQFUoJLn07Cs5gkdDSupScohz1RNjTGKq+6cT7ARL3yh+kyU\r\n"
"lE6MWCw9iONopE6I+hShP2+s+t6DqyTgnrVK1l7EWyE59Ei4g9QLYMLcOaKayyum\r\n"
"3zcjhbjyyfgmnsDSi9hFpjIaNw9pZKmyLrSHnsQzd1HEqeGuaRJ8KQ==\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
#define CMD_NOPOLL_MSG_EXIT (0)
#define CMD_NOPOLL_MSG_OPEN (1)
#define CMD_NOPOLL_MSG_SEND (2)
#define CMD_NOPOLL_MSG_RECV (3)
#define CMD_NOPOLL_MSG_CLOSE (4)
struct cmd_nopoll_open_data {
uint32_t tls;
uint32_t verify;
uint32_t cer;
};
struct cmd_nopoll_send_data {
uint8_t *buf;
uint32_t size;
};
struct cmd_nopoll_msg {
uint32_t type;
void *data;
};
#define CMD_NOPOLL_QUEUE_WAIT_TIME (5000)
#define CMD_NOPOLL_THREAD_STACK_SIZE (4 * 1024)
static OS_Thread_t g_nopoll_server_thread;
static OS_Thread_t g_nopoll_client_thread;
static char g_server_host[32] = {0};
static char g_server_port[8] = {0};
static noPollCtx *g_server_ctx = NULL;
static noPollConn *g_listener = NULL;
static noPollConnOpts *g_listener_opts = NULL;
static OS_Queue_t g_client_queue;
static char g_client_host[64] = {0};
static char g_client_port[8] = {0};
static char g_client_path[512] = {0};
static noPollCtx *g_client_ctx = NULL;
static noPollConn *g_conn = NULL;
static noPollConnOpts *g_conn_opts = NULL;
static int ag_nopoll_complete_pending_write(noPollConn *conn)
{
int tries = 0;
while (tries < 5 && errno == NOPOLL_EWOULDBLOCK
&& nopoll_conn_pending_write_bytes (conn) > 0) {
nopoll_sleep(50000);
if (nopoll_conn_complete_pending_write (conn) == 0)
return 0;
tries++;
}
return 1;
}
static void cmd_nopoll_server_task(void *arg)
{
nopoll_loop_wait(g_server_ctx, 0);
CMD_DBG("%s() end\n", __func__);
OS_ThreadDelete(&g_nopoll_server_thread);
}
static void cmd_nopoll_server_on_close(noPollCtx *ctx, noPollConn *conn,
noPollPtr user_data)
{
CMD_LOG(1, "called connection close\n");
}
static nopoll_bool cmd_nopoll_server_on_open(noPollCtx *ctx, noPollConn *conn,
noPollPtr user_data)
{
CMD_LOG(1, "called connection open\n");
nopoll_conn_set_on_close(conn, cmd_nopoll_server_on_close, NULL);
if (!nopoll_conn_set_sock_block(nopoll_conn_socket(conn), nopoll_false)) {
CMD_ERR("ERROR: failed to configure non-blocking state to "
"connection..\n");
return nopoll_false;
}
return nopoll_true;
}
static void cmd_nopoll_server_on_message(noPollCtx *ctx, noPollConn *conn,
noPollMsg *msg, noPollPtr user_data)
{
int ret;
int size = nopoll_msg_get_payload_size(msg);
const char *content = (const char *)nopoll_msg_get_payload(msg);
CMD_LOG(1, "server receive message:\n");
CMD_LOG(1, "%s\n", content);
ret = nopoll_conn_send_text(conn, content, size);
if (ret != size) {
if (ag_nopoll_complete_pending_write(conn))
CMD_ERR("size = %u, but nopoll_conn_send_text ret = %d\n", size,
ret);
}
if (nopoll_cmp(content, "nopoll test stop running")) {
nopoll_loop_stop(g_server_ctx);
}
}
static enum cmd_status cmd_nopoll_server_init_exec(char *cmd)
{
int cnt;
uint32_t dbg;
cnt = cmd_sscanf(cmd, "d=%u", &dbg);
if (cnt != 1) {
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (g_server_ctx != NULL) {
CMD_ERR("already init\n");
return CMD_STATUS_FAIL;
}
g_server_ctx = nopoll_ctx_new();
if (g_server_ctx == NULL) {
CMD_ERR("nopoll_ctx_new failed\n");
return CMD_STATUS_FAIL;
}
if (dbg == 0)
nopoll_log_enable(g_server_ctx, nopoll_false);
else
nopoll_log_enable(g_server_ctx, nopoll_true);
/* set on open */
nopoll_ctx_set_on_open(g_server_ctx, cmd_nopoll_server_on_open, NULL);
/* set on message received */
nopoll_ctx_set_on_msg(g_server_ctx, cmd_nopoll_server_on_message, NULL);
OS_ThreadSetInvalid(&g_nopoll_server_thread);
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_server_open_exec(char *cmd)
{
int cnt;
uint32_t tls;
uint32_t verify;
cnt = cmd_sscanf(cmd, "h=%s p=%s t=%u v=%u", g_server_host, g_server_port,
&tls, &verify);
if (cnt != 4) {
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (g_server_ctx == NULL) {
CMD_ERR("without init\n");
return CMD_STATUS_FAIL;
}
if ((g_listener != NULL) || (g_listener_opts != NULL)) {
CMD_ERR("already open\n");
return CMD_STATUS_FAIL;
}
g_listener_opts = nopoll_conn_opts_new();
if (g_listener_opts == NULL) {
CMD_ERR("nopoll_conn_opts_new failed\n");
return CMD_STATUS_FAIL;
}
if (tls == 0)
g_listener = nopoll_listener_new_opts(g_server_ctx, g_listener_opts,
g_server_host, g_server_port);
else {
if (!nopoll_conn_opts_set_ssl_certs(g_listener_opts,
websockets_server_cert, sizeof(websockets_server_cert),
websockets_server_key, sizeof(websockets_server_key),
websockets_ca_cert, sizeof(websockets_ca_cert),
websockets_ca_cert, sizeof(websockets_ca_cert))) {
CMD_ERR("nopoll_conn_opts_set_ssl_certs failed\n");
nopoll_conn_opts_free(g_listener_opts);
g_listener_opts = NULL;
return CMD_STATUS_FAIL;
}
if (verify == 0)
nopoll_conn_opts_ssl_peer_verify(g_listener_opts, nopoll_false);
else
nopoll_conn_opts_ssl_peer_verify(g_listener_opts, nopoll_true);
g_listener = nopoll_listener_tls_new_opts(g_server_ctx, g_listener_opts,
g_server_host, g_server_port);
}
if (g_listener == NULL) {
CMD_ERR("nopoll_listener(_tls)_new_opts failed\n");
nopoll_conn_opts_free(g_listener_opts);
g_listener_opts = NULL;
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_server_start_exec(char *cmd)
{
if ((g_listener == NULL) || (g_listener_opts == NULL)) {
CMD_ERR("without open\n");
return CMD_STATUS_FAIL;
}
if (OS_ThreadIsValid(&g_nopoll_server_thread)) {
CMD_ERR("already start\n");
return CMD_STATUS_FAIL;
}
if (OS_ThreadCreate(&g_nopoll_server_thread,
"cmd_nopoll_serv",
cmd_nopoll_server_task,
NULL,
OS_THREAD_PRIO_CONSOLE,
CMD_NOPOLL_THREAD_STACK_SIZE) != OS_OK) {
CMD_ERR("thread create failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_server_stop_exec(char *cmd)
{
if (!OS_ThreadIsValid(&g_nopoll_server_thread)) {
CMD_ERR("without start\n");
return CMD_STATUS_FAIL;
}
nopoll_loop_stop(g_server_ctx);
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_server_close_exec(char *cmd)
{
if ((g_listener == NULL) || (g_listener_opts == NULL)) {
CMD_ERR("without open\n");
return CMD_STATUS_FAIL;
}
if (OS_ThreadIsValid(&g_nopoll_server_thread)) {
CMD_ERR("without stop\n");
return CMD_STATUS_FAIL;
}
nopoll_conn_close(g_listener);
g_listener = NULL;
g_listener_opts = NULL;
cmd_memset(g_server_host, 0, sizeof(g_server_host));
cmd_memset(g_server_port, 0, sizeof(g_server_port));
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_server_deinit_exec(char *cmd)
{
if (g_server_ctx == NULL) {
CMD_ERR("without init\n");
return CMD_STATUS_FAIL;
}
nopoll_ctx_unref(g_server_ctx);
nopoll_cleanup_library();
g_server_ctx = NULL;
return CMD_STATUS_OK;
}
static void cmd_nopoll_client_open_task(struct cmd_nopoll_open_data *data)
{
g_conn_opts = nopoll_conn_opts_new();
if (g_conn_opts == NULL) {
CMD_ERR("nopoll_conn_opts_new failed\n");
goto open_task_exit;
}
char *host_ip;
struct hostent *host_entry;
host_entry = gethostbyname(g_client_host);
host_ip = inet_ntoa(*(struct in_addr *)host_entry->h_addr);
if (data->tls == 0)
g_conn = nopoll_conn_new_opts(g_client_ctx, g_conn_opts, host_ip,
g_client_port, g_client_host, g_client_path, NULL, NULL);
else {
if (data->cer != 0) {
if (!nopoll_conn_opts_set_ssl_certs(g_conn_opts,
websockets_client_cert, sizeof(websockets_client_cert),
websockets_client_key, sizeof(websockets_client_key),
NULL, 0,
websockets_ca_cert, sizeof(websockets_ca_cert))) {
CMD_ERR("nopoll_conn_opts_set_ssl_certs failed\n");
nopoll_conn_opts_free(g_conn_opts);
g_conn_opts = NULL;
goto open_task_exit;
}
}
if (data->verify == 0)
nopoll_conn_opts_ssl_peer_verify (g_conn_opts, nopoll_false);
else
nopoll_conn_opts_ssl_peer_verify (g_conn_opts, nopoll_true);
g_conn = nopoll_conn_tls_new(g_client_ctx, g_conn_opts, host_ip,
g_client_port, g_client_host, g_client_path, NULL, NULL);
}
if (g_conn == NULL) {
CMD_ERR("nopoll_conn(_tls)_new(_opts) failed\n");
goto open_task_exit;
}
if (nopoll_conn_wait_until_connection_ready(g_conn, 10))
CMD_LOG(1, "the connection is ready\n");
else
CMD_ERR("connection timeout\n");
open_task_exit:
cmd_free(data);
data = NULL;
return;
}
static void cmd_nopoll_client_send_task(struct cmd_nopoll_send_data *data)
{
int ret = nopoll_conn_send_text(g_conn, (char *)data->buf, data->size);
if (ret != (int)data->size) {
if (ag_nopoll_complete_pending_write(g_conn))
CMD_ERR("size = %u, but nopoll_conn_send_text ret = %d\n",
data->size, ret);
}
cmd_free(data->buf);
data->buf = NULL;
cmd_free(data);
data = NULL;
return;
}
static void cmd_nopoll_client_recv_task(void *data)
{
uint32_t msec = 10 * 1000;
noPollMsg *msg;
const char *content;
while (1) {
if (!nopoll_conn_is_ok(g_conn)) {
CMD_DBG("received websocket connection close\n");
break;
}
msg = nopoll_conn_get_msg(g_conn);
if (msg) {
content = (const char *)nopoll_msg_get_payload(msg);
CMD_LOG(1, "receive message:\n");
CMD_LOG(1, "%s\n", content);
nopoll_msg_unref (msg);
} else {
if (msec == 0) {
CMD_ERR("get message timeout\n");
break;
}
nopoll_sleep(100000);
msec -= 100;
}
}
}
static void cmd_nopoll_client_close_task(void *data)
{
nopoll_conn_close(g_conn);
g_conn = NULL;
g_conn_opts = NULL;
cmd_memset(g_client_host, 0, sizeof(g_client_host));
cmd_memset(g_client_port, 0, sizeof(g_client_port));
return;
}
static void cmd_nopoll_client_task(void *arg)
{
uint8_t task_exit = 0;
struct cmd_nopoll_msg *msg;
while (task_exit == 0) {
if (OS_MsgQueueReceive(&g_client_queue, (void **)&msg, OS_WAIT_FOREVER) != OS_OK) {
CMD_ERR("msg queue receive failed\n");
break;
}
//CMD_DBG("recv msg type %u\n", msg->type);
switch (msg->type) {
case CMD_NOPOLL_MSG_EXIT:
task_exit = 1;
break;
case CMD_NOPOLL_MSG_OPEN:
cmd_nopoll_client_open_task(msg->data);
break;
case CMD_NOPOLL_MSG_SEND:
cmd_nopoll_client_send_task(msg->data);
break;
case CMD_NOPOLL_MSG_RECV:
cmd_nopoll_client_recv_task(msg->data);
break;
case CMD_NOPOLL_MSG_CLOSE:
cmd_nopoll_client_close_task(msg->data);
break;
default:
CMD_WRN("unknown msg\n");
break;
}
cmd_free(msg);
msg = NULL;
}
CMD_DBG("%s() end\n", __func__);
OS_ThreadDelete(&g_nopoll_client_thread);
}
static enum cmd_status cmd_nopoll_client_init_exec(char *cmd)
{
int cnt;
uint32_t dbg;
cnt = cmd_sscanf(cmd, "d=%u", &dbg);
if (cnt != 1) {
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (g_client_ctx != NULL) {
CMD_ERR("already init\n");
return CMD_STATUS_FAIL;
}
g_client_ctx = nopoll_ctx_new();
if (g_client_ctx == NULL) {
CMD_ERR("nopoll_ctx_new failed\n");
return CMD_STATUS_FAIL;
}
if (dbg == 0)
nopoll_log_enable(g_client_ctx, nopoll_false);
else
nopoll_log_enable(g_client_ctx, nopoll_true);
OS_ThreadSetInvalid(&g_nopoll_client_thread);
if (OS_MsgQueueCreate(&g_client_queue, 1) != OS_OK) {
CMD_ERR("msg queue create failed\n");
return CMD_STATUS_FAIL;
}
if (OS_ThreadCreate(&g_nopoll_client_thread,
"cmd_nopoll_cli",
cmd_nopoll_client_task,
NULL,
OS_THREAD_PRIO_CONSOLE,
CMD_NOPOLL_THREAD_STACK_SIZE) != OS_OK) {
CMD_ERR("thread create failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_client_open_exec(char *cmd)
{
int cnt;
uint32_t tls;
uint32_t verify;
uint32_t cer;
struct cmd_nopoll_open_data *data;
struct cmd_nopoll_msg *msg;
cnt = cmd_sscanf(cmd, "h=%s p=%s u=%s t=%u v=%u c=%u", g_client_host,
g_client_port, g_client_path, &tls, &verify, &cer);
if (cnt != 6) {
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (g_client_ctx == NULL) {
CMD_ERR("without init\n");
return CMD_STATUS_FAIL;
}
if ((g_conn != NULL) || (g_conn_opts != NULL)) {
CMD_ERR("already open\n");
return CMD_STATUS_FAIL;
}
msg = cmd_malloc(sizeof(struct cmd_nopoll_msg));
data = cmd_malloc(sizeof(struct cmd_nopoll_open_data));
if ((msg == NULL) || (data == NULL)) {
CMD_ERR("malloc failed\n");
if (msg)
cmd_free(msg);
if (data)
cmd_free(data);
return CMD_STATUS_FAIL;
}
data->tls = tls;
data->verify = verify;
data->cer = cer;
msg->type = CMD_NOPOLL_MSG_OPEN;
msg->data = data;
if (OS_MsgQueueSend(&g_client_queue, msg, CMD_NOPOLL_QUEUE_WAIT_TIME) != OS_OK) {
CMD_ERR("msg queue send failed\n");
if (msg)
cmd_free(msg);
if (data)
cmd_free(data);
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_client_send_exec(char *cmd)
{
int cnt;
int ret;
uint32_t size;
uint8_t *buf;
struct cmd_nopoll_send_data *data;
struct cmd_nopoll_msg *msg;
cnt = cmd_sscanf(cmd, "s=%u", &size);
if (cnt != 1) {
CMD_ERR("cmd_sscanf return: cnt = %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (size == 0) {
CMD_ERR("size = 0\n");
return CMD_STATUS_INVALID_ARG;
}
if ((g_conn == NULL) || (g_conn_opts == NULL)) {
CMD_ERR("without open\n");
return CMD_STATUS_FAIL;
}
msg = cmd_malloc(sizeof(struct cmd_nopoll_msg));
data = cmd_malloc(sizeof(struct cmd_nopoll_send_data));
buf = cmd_malloc(size);
if ((msg == NULL) || (data == NULL) || (buf == NULL)) {
CMD_ERR("malloc failed\n");
if (msg)
cmd_free(msg);
if (data)
cmd_free(data);
if (buf)
cmd_free(buf);
return CMD_STATUS_FAIL;
}
cmd_write_respond(CMD_STATUS_OK, "OK");
cmd_raw_mode_enable();
ret = cmd_raw_mode_read(buf, size, 10000);
if (ret != (int)size) {
CMD_ERR("size = %u, but cmd_raw_mode_read ret = %d\n", size, ret);
cmd_free(msg);
cmd_free(data);
cmd_free(buf);
cmd_raw_mode_write((uint8_t *)"FAIL\n", 5);
cmd_raw_mode_disable();
return CMD_STATUS_ACKED;
}
cmd_raw_mode_disable();
data->buf = buf;
data->size = size;
msg->type = CMD_NOPOLL_MSG_SEND;
msg->data = data;
if (OS_MsgQueueSend(&g_client_queue, msg, CMD_NOPOLL_QUEUE_WAIT_TIME) != OS_OK) {
CMD_ERR("msg queue send failed\n");
if (msg)
cmd_free(msg);
if (data)
cmd_free(data);
if (buf)
cmd_free(buf);
return CMD_STATUS_ACKED;
}
return CMD_STATUS_ACKED;
}
static enum cmd_status cmd_nopoll_client_recv_exec(char *cmd)
{
struct cmd_nopoll_msg *msg;
if ((g_conn == NULL) || (g_conn_opts == NULL)) {
CMD_ERR("without open\n");
return CMD_STATUS_FAIL;
}
msg = cmd_malloc(sizeof(struct cmd_nopoll_msg));
if (msg == NULL) {
CMD_ERR("msg queue send failed\n");
return CMD_STATUS_FAIL;
}
msg->type = CMD_NOPOLL_MSG_RECV;
msg->data = NULL;
if (OS_MsgQueueSend(&g_client_queue, msg, CMD_NOPOLL_QUEUE_WAIT_TIME) != OS_OK) {
CMD_ERR("msg queue send failed\n");
if (msg)
cmd_free(msg);
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_client_close_exec(char *cmd)
{
struct cmd_nopoll_msg *msg;
if ((g_conn == NULL) || (g_conn_opts == NULL)) {
CMD_ERR("without open\n");
return CMD_STATUS_FAIL;
}
msg = cmd_malloc(sizeof(struct cmd_nopoll_msg));
if (msg == NULL) {
CMD_ERR("msg queue send failed\n");
return CMD_STATUS_FAIL;
}
msg->type = CMD_NOPOLL_MSG_CLOSE;
msg->data = NULL;
if (OS_MsgQueueSend(&g_client_queue, msg, CMD_NOPOLL_QUEUE_WAIT_TIME) != OS_OK) {
CMD_ERR("msg queue send failed\n");
if (msg)
cmd_free(msg);
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_nopoll_client_deinit_exec(char *cmd)
{
struct cmd_nopoll_msg *msg;
if (g_client_ctx == NULL) {
CMD_ERR("without init\n");
return CMD_STATUS_FAIL;
}
nopoll_ctx_unref(g_client_ctx);
g_client_ctx = NULL;
msg = cmd_malloc(sizeof(struct cmd_nopoll_msg));
if (msg == NULL) {
CMD_ERR("msg queue send failed\n");
return CMD_STATUS_FAIL;
}
msg->type = CMD_NOPOLL_MSG_EXIT;
msg->data = NULL;
if (OS_MsgQueueSend(&g_client_queue, msg, CMD_NOPOLL_QUEUE_WAIT_TIME) != OS_OK) {
CMD_ERR("msg queue send failed\n");
if (msg)
cmd_free(msg);
return CMD_STATUS_FAIL;
}
OS_MSleep(100);
if (OS_MsgQueueDelete(&g_client_queue) != OS_OK) {
CMD_ERR("msg queue delete failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
#if CMD_DESCRIBE
#define np_ser_init_help_info "init d=<debug>, 0:debug off, 1:debug on, init the server"
#define np_ser_open_help_info "open h=<host_ip> p=<host_port> t=<tls> v=<verify>, open the server"
#define np_ser_start_help_info "start the server"
#define np_ser_stop_help_info "stop the server"
#define np_ser_close_help_info "close the server"
#define np_ser_deinit_help_info "deinit the server"
#endif
static enum cmd_status cmd_nopoll_server_help_exec(char *cmd);
static const struct cmd_data g_nopoll_server_cmds[] = {
{ "init", cmd_nopoll_server_init_exec, CMD_DESC(np_ser_init_help_info) },
{ "open", cmd_nopoll_server_open_exec, CMD_DESC(np_ser_open_help_info) },
{ "start", cmd_nopoll_server_start_exec, CMD_DESC(np_ser_start_help_info) },
{ "stop", cmd_nopoll_server_stop_exec, CMD_DESC(np_ser_stop_help_info) },
{ "close", cmd_nopoll_server_close_exec, CMD_DESC(np_ser_close_help_info) },
{ "deinit", cmd_nopoll_server_deinit_exec, CMD_DESC(np_ser_deinit_help_info) },
{ "help", cmd_nopoll_server_help_exec, CMD_DESC(CMD_HELP_DESC) },
};
#if CMD_DESCRIBE
#define np_cli_init_help_info "init d=<debug>, 0:debug off, 1:debug on, init the client"
#define np_cli_open_help_info \
"open h=<server_domain_name or server_ip> p=<server_port> u=<path> t=<tls> v=<verify> c=<cert>, " \
"open the client and connect the server"
#define np_cli_send_help_info \
"send s=<string_len>, send data to server, " \
"need to input data in the serial port after inputting this command, " \
"and the data length must be consistent with the parameter string_len"
#define np_cli_recv_help_info "receive data from server"
#define np_cli_close_help_info "disconnet from server"
#define np_cli_deinit_help_info "deinit the client"
#endif
static enum cmd_status cmd_nopoll_client_help_exec(char *cmd);
static const struct cmd_data g_nopoll_client_cmds[] = {
{ "init", cmd_nopoll_client_init_exec, CMD_DESC(np_cli_init_help_info) },
{ "open", cmd_nopoll_client_open_exec, CMD_DESC(np_cli_open_help_info) },
{ "send", cmd_nopoll_client_send_exec, CMD_DESC(np_cli_send_help_info) },
{ "recv", cmd_nopoll_client_recv_exec, CMD_DESC(np_cli_recv_help_info) },
{ "close", cmd_nopoll_client_close_exec, CMD_DESC(np_cli_close_help_info) },
{ "deinit", cmd_nopoll_client_deinit_exec, CMD_DESC(np_cli_deinit_help_info) },
{ "help", cmd_nopoll_client_help_exec, CMD_DESC(CMD_HELP_DESC) },
};
static enum cmd_status cmd_nopoll_server_help_exec(char *cmd)
{
return cmd_help_exec(g_nopoll_server_cmds, cmd_nitems(g_nopoll_server_cmds), 8);
}
static enum cmd_status cmd_nopoll_server_exec(char *cmd)
{
return cmd_exec(cmd, g_nopoll_server_cmds, cmd_nitems(g_nopoll_server_cmds));
}
static enum cmd_status cmd_nopoll_client_help_exec(char *cmd)
{
return cmd_help_exec(g_nopoll_client_cmds, cmd_nitems(g_nopoll_client_cmds), 8);
}
static enum cmd_status cmd_nopoll_client_exec(char *cmd)
{
return cmd_exec(cmd, g_nopoll_client_cmds, cmd_nitems(g_nopoll_client_cmds));
}
static enum cmd_status cmd_nopoll_help_exec(char *cmd);
static const struct cmd_data g_nopoll_cmds[] = {
{ "srv", cmd_nopoll_server_exec, CMD_DESC("nopoll server command") },
{ "cli", cmd_nopoll_client_exec, CMD_DESC("nopoll client command") },
{ "help", cmd_nopoll_help_exec, CMD_DESC(CMD_HELP_DESC) },
};
static enum cmd_status cmd_nopoll_help_exec(char *cmd)
{
return cmd_help_exec(g_nopoll_cmds, cmd_nitems(g_nopoll_cmds), 8);
}
enum cmd_status cmd_nopoll_exec(char *cmd)
{
return cmd_exec(cmd, g_nopoll_cmds, cmd_nitems(g_nopoll_cmds));
}
#endif /* PRJCONF_NET_EN */