netutils/websocket: organizing code
authorbossjisu <jisuu.kim@samsung.com>
Tue, 30 May 2017 11:12:46 +0000 (04:12 -0700)
committerEunBong Song <eunb.song@samsung.com>
Tue, 11 Jul 2017 01:26:57 +0000 (10:26 +0900)
1. Deleted Unused wqueue function code
2. Added guide line for websocket handler timeout value. It is not supposed
to be 0 becaust it makes busy waiting.
3. Added definition on checking a NULL parameter
4. Changed Inappropriate names:
   websocket_ping_timer() -> websocket_ping_counter()
   websocket_make_block() -> websocket_config_socket()
   WEBSOCKET_SERVER_CHECK_INTERVAL -> WEBSOCKET_ACCEPT_TIMEOUT

Change-Id: I742f5f0a3c6b50252d7a38fe8a10e927b341837a
Signed-off-by: bossjisu <jisuu.kim@samsung.com>
apps/include/netutils/websocket.h
apps/netutils/websocket/websocket.c

index 54eee9f..ad0e0d7 100644 (file)
 /**
  * @brief Websocket accept server select() timeout value, msec.
  */
-#define WEBSOCKET_SERVER_CHECK_INTERVAL              (500)     //mili second
+#define WEBSOCKET_ACCEPT_TIMEOUT              (500)    //mili second
 /**
  * @brief Websocket accept server select() timeout limit, msec.
  */
 
 /**
  * @brief Websocket event handler select() timeout value, msec.
+                 Don't set this 0, it will be busy waiting.
  */
 #define WEBSOCKET_HANDLER_TIMEOUT                    (100)     //mili second
 
 #define WEBSOCKET_PING_INTERVAL                      (20 * 100)        //MSEC_PER_TICK
 
 /**
- * @brief The maximum amount of websocket messages to be stored in queue.
+ * @brief The maximum length of websocket messages to be stored in queue.
  */
 #define WEBSOCKET_MAX_LENGTH_QUEUE                      (100 * 1024)
 /**
 #define WEBSOCKET_MAX_NUMBER_QUEUE                      (20)
 
 /**
- * @brief The maximum amount of client to accept from server.
+ * @brief The maximum amount of client to be accepted in server.
  */
 #define WEBSOCKET_MAX_CLIENT                         (3)
 
 /**
  * @brief Enable and disable the Server name indication(SNI)
  */
-#define WEBSOCKET_CONF_CHECK_TLS_HOSTNAME            (0)   // 0- disable, 1- enable
+#define WEBSOCKET_CONF_CHECK_TLS_HOSTNAME            (0)       // 0- disable, 1- enable
 
 /*
  *  Pre-definition variables from wslay below.
@@ -484,10 +485,10 @@ websocket_return_t websocket_server_init(websocket_t *server);
  *        but users can change callbacks with this function.
  * @param[in] websocket websocket structure to store callbacks.
  * @param[in] cb callbacks structure pointer to change
- * @return none
+ * @return On success, return WEBSOCKET_SUCCESS. On failure, return values defined in websocket_return_t.
  * @since Tizen RT v1.0
  */
-void websocket_register_cb(websocket_t *websocket, websocket_cb_t *cb);
+websocket_return_t websocket_register_cb(websocket_t *websocket, websocket_cb_t *cb);
 
 /*
  * @brief websocket_queue_msg() queues a message into websocket context.
@@ -532,10 +533,10 @@ websocket_return_t websocket_queue_close(websocket_t *websocket, const char *clo
  *        websocket state are defined at websocket_state.
  * @param[in] websocket websocket structure.
  * @param[in] state websocket state.
- * @return none
+ * @return On success, return WEBSOCKET_SUCCESS. On failure, return values defined in websocket_return_t.
  * @since Tizen RT v1.0
  */
-void websocket_update_state(websocket_t *websocket, int state);
+websocket_return_t websocket_update_state(websocket_t *websocket, int state);
 
 /**
  * @brief websocket_set_error() sets an error number to websocket context.
@@ -544,10 +545,10 @@ void websocket_update_state(websocket_t *websocket, int state);
  *        After this function triggered, websocket context will be closed.
  * @param[in] websocket websocket structure manages websocket context.
  * @param[in] val error value to be set.
- * @return none
+ * @return On success, return WEBSOCKET_SUCCESS. On failure, return values defined in websocket_return_t.
  * @since Tizen RT v1.0
  */
-void websocket_set_error(websocket_t *websocket, int val);
+websocket_return_t websocket_set_error(websocket_t *websocket, int val);
 
 #undef EXTERN
 #undef EXTERN
index f555a9d..dc0db1e 100644 (file)
@@ -44,8 +44,6 @@
 #include <apps/netutils/websocket.h>
 #include <apps/netutils/wslay/wslay.h>
 
-#include <tinyara/wqueue.h>
-
 /****************************************************************************
  * Definitions
  ****************************************************************************/
@@ -86,7 +84,6 @@ int websocket_tls_handshake(websocket_t *data, char *hostname, int auth_mode)
                WEBSOCKET_DEBUG("Error: mbedtls_ssl_setup returned %d\n", r);
                return -1;
        }
-
 #if WEBSOCKET_CONF_CHECK_TLS_HOSTNAME
        if (hostname != NULL) {
                if ((r = mbedtls_ssl_set_hostname(data->tls_ssl, hostname)) != 0) {
@@ -112,7 +109,7 @@ int websocket_tls_handshake(websocket_t *data, char *hostname, int auth_mode)
        return WEBSOCKET_SUCCESS;
 }
 
-int websocket_make_block(int fd)
+websocket_return_t websocket_config_socket(int fd)
 {
        int r;
        int flags;
@@ -127,7 +124,7 @@ int websocket_make_block(int fd)
 
        tv.tv_sec = (WEBSOCKET_SOCK_RCV_TIMEOUT / 1000);
        tv.tv_usec = ((WEBSOCKET_SOCK_RCV_TIMEOUT % 1000) * 1000);
-       if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (FAR const void *)&tv, (socklen_t)sizeof(struct timeval)) == -1) {
+       if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (FAR const void *)&tv, (socklen_t) sizeof(struct timeval)) == -1) {
                WEBSOCKET_DEBUG("setsockopt fail in server\n");
                return WEBSOCKET_SOCKET_ERROR;
        }
@@ -135,25 +132,31 @@ int websocket_make_block(int fd)
        return WEBSOCKET_SUCCESS;
 }
 
-void websocket_wait_state(websocket_t *websocket, int state, int utime)
+websocket_return_t websocket_wait_state(websocket_t *websocket, int state, int utime)
 {
        if (websocket == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
-       } else if (!(state >= WEBSOCKET_STOP && state <= WEBSOCKET_MAX_STATE)) {
-               WEBSOCKET_DEBUG("function returned for invalid parameter\n");
-       } else {
+               WEBSOCKET_DEBUG("NULL parameter\n");
+               return WEBSOCKET_ALLOCATION_ERROR;
+       }
+
+       if (state >= WEBSOCKET_STOP && state < WEBSOCKET_MAX_STATE) {
                while ((websocket->state) != state) {
                        usleep(utime);
                }
+       } else {
+               WEBSOCKET_DEBUG("function returned for invalid parameter\n");
        }
+
+       return WEBSOCKET_SUCCESS;
 }
 
-void websocket_ping_timer(FAR void *arg)
+void websocket_ping_counter(FAR void *arg)
 {
        websocket_t *websocket = arg;
 
        if (websocket->state != WEBSOCKET_STOP) {
                websocket->ping_cnt++;
+
                if (websocket->ping_cnt >= WEBSOCKET_MAX_PING_IGNORE) {
                        WEBSOCKET_DEBUG("ping messages couldn't receive pong messages for %d times, closing.\n", WEBSOCKET_MAX_PING_IGNORE);
                        websocket_update_state(websocket, WEBSOCKET_STOP);
@@ -174,10 +177,6 @@ int websocket_handler(websocket_t *websocket)
        wslay_event_context_ptr ctx = (wslay_event_context_ptr) websocket->ctx;
        struct timeval tv;
 
-       if (WEBSOCKET_HANDLER_TIMEOUT == 0) {
-               work_queue(WEBSOCKET_WQ, &websocket->time_worker, websocket_ping_timer, websocket, WEBSOCKET_PING_INTERVAL);
-       }
-
        while (websocket->state != WEBSOCKET_STOP) {
                FD_ZERO(&read_fds);
                FD_ZERO(&write_fds);
@@ -196,9 +195,11 @@ int websocket_handler(websocket_t *websocket)
                                websocket_update_state(websocket, WEBSOCKET_STOP);
                                return WEBSOCKET_SOCKET_ERROR;
                        }
+
                        if (errno == EAGAIN || errno == EBUSY || errno == EINTR) {
                                continue;
                        }
+
                        WEBSOCKET_DEBUG("select function returned errno == %d\n", errno);
                        continue;
                } else if (r == 0) {
@@ -206,12 +207,14 @@ int websocket_handler(websocket_t *websocket)
                                timeout++;
                                if ((WEBSOCKET_HANDLER_TIMEOUT * timeout) >= (WEBSOCKET_PING_INTERVAL * 10)) {
                                        timeout = 0;
-                                       websocket_ping_timer((void *)websocket);
+                                       websocket_ping_counter((void *)websocket);
                                }
                        }
+
                        continue;
                } else {
                        timeout = 0;
+
                        if (FD_ISSET(fd, &read_fds)) {
                                if (wslay_event_recv(ctx) != WEBSOCKET_SUCCESS) {
                                        WEBSOCKET_DEBUG("fail to process recv event\n");
@@ -219,6 +222,7 @@ int websocket_handler(websocket_t *websocket)
                                        return WEBSOCKET_SOCKET_ERROR;
                                }
                        }
+
                        if (FD_ISSET(fd, &write_fds)) {
                                if (wslay_event_send(ctx) != WEBSOCKET_SUCCESS) {
                                        WEBSOCKET_DEBUG("fail to process send event\n");
@@ -229,10 +233,6 @@ int websocket_handler(websocket_t *websocket)
                }
        }
 
-       if (WEBSOCKET_HANDLER_TIMEOUT == 0) {
-               work_cancel(WEBSOCKET_WQ, &websocket->time_worker);
-       }
-
        return WEBSOCKET_SUCCESS;
 }
 
@@ -336,16 +336,19 @@ EXIT_WEBSOCKET_HANDSHAKE_ERROR:
        return WEBSOCKET_HANDSHAKE_ERROR;
 }
 
-void websocket_socket_free(websocket_t *ctx)
+websocket_return_t websocket_socket_free(websocket_t *ctx)
 {
        if (ctx == NULL) {
-               return;
+               WEBSOCKET_DEBUG("NULL parameter\n");
+               return WEBSOCKET_ALLOCATION_ERROR;
        }
 
        if (ctx->fd >= 0) {
                close(ctx->fd);
                ctx->fd = -1;
        }
+
+       return WEBSOCKET_SUCCESS;
 }
 
 int connect_socket(websocket_t *client, const char *host, const char *port)
@@ -406,16 +409,14 @@ TLS_HS_RETRY:
 
        websocket_update_state(client, WEBSOCKET_RUNNING);
 
-       if (websocket_make_block(client->fd) != WEBSOCKET_SUCCESS) {
+       if (websocket_config_socket(client->fd) != WEBSOCKET_SUCCESS) {
                websocket_socket_free(client);
                return WEBSOCKET_SOCKET_ERROR;
        }
 
        if (client->tls_enabled) {
                if ((r = websocket_tls_handshake(client, host, client->auth_mode)) != WEBSOCKET_SUCCESS) {
-                       if (r == MBEDTLS_ERR_NET_SEND_FAILED ||
-                               r == MBEDTLS_ERR_NET_RECV_FAILED ||
-                               r == MBEDTLS_ERR_SSL_CONN_EOF) {
+                       if (r == MBEDTLS_ERR_NET_SEND_FAILED || r == MBEDTLS_ERR_NET_RECV_FAILED || r == MBEDTLS_ERR_SSL_CONN_EOF) {
                                if (tls_hs_retry-- > 0) {
                                        WEBSOCKET_DEBUG("Handshake again.... \n");
                                        mbedtls_net_free(&(client->tls_net));
@@ -576,8 +577,8 @@ int websocket_accept_loop(websocket_t *init_server)
                FD_ZERO(&init_server_read_fds);
                FD_SET(listen_fd, &init_server_read_fds);
 
-               tv.tv_sec = WEBSOCKET_SERVER_CHECK_INTERVAL / 1000;
-               tv.tv_usec = (WEBSOCKET_SERVER_CHECK_INTERVAL & 1000) * 1000;
+               tv.tv_sec = WEBSOCKET_ACCEPT_TIMEOUT / 1000;
+               tv.tv_usec = (WEBSOCKET_ACCEPT_TIMEOUT & 1000) * 1000;
                r = select(listen_fd + 1, &init_server_read_fds, NULL, NULL, &tv);
                if (r == -1) {
                        if (errno == EINVAL) {
@@ -597,7 +598,7 @@ int websocket_accept_loop(websocket_t *init_server)
                        }
                        if (i == WEBSOCKET_MAX_CLIENT) {
                                timeout_cnt++;
-                               if (timeout_cnt * WEBSOCKET_SERVER_CHECK_INTERVAL >= WEBSOCKET_SERVER_TIMEOUT) {
+                               if (timeout_cnt * WEBSOCKET_ACCEPT_TIMEOUT >= WEBSOCKET_SERVER_TIMEOUT) {
                                        WEBSOCKET_DEBUG("websocket server is inactive for %d msec, closing.\n", WEBSOCKET_SERVER_TIMEOUT);
                                        r = WEBSOCKET_SUCCESS;
                                        goto EXIT_INIT_SERVER;
@@ -633,7 +634,7 @@ int websocket_accept_loop(websocket_t *init_server)
                                }
                        }
 
-                       if (websocket_make_block(accept_fd) != WEBSOCKET_SUCCESS) {
+                       if (websocket_config_socket(accept_fd) != WEBSOCKET_SUCCESS) {
                                if (server_handler->tls_ssl) {
                                        free(server_handler->tls_ssl);
                                }
@@ -651,7 +652,7 @@ int websocket_accept_loop(websocket_t *init_server)
                        ws_sparam.sched_priority = WEBSOCKET_PRI;
                        pthread_attr_setschedparam(&server_handler->thread_attr, &ws_sparam);
                        pthread_attr_setschedpolicy(&server_handler->thread_attr, WEBSOCKET_SCHED_POLICY);
-                       if (pthread_create(&server_handler->thread_id, &server_handler->thread_attr, (pthread_startroutine_t)websocket_server_start, (pthread_addr_t)server_handler) != 0) {
+                       if (pthread_create(&server_handler->thread_id, &server_handler->thread_attr, (pthread_startroutine_t) websocket_server_start, (pthread_addr_t) server_handler) != 0) {
                                WEBSOCKET_DEBUG("fail to create thread, fd == %d\n", accept_fd);
                                close(accept_fd);
                                if (server_handler->tls_ssl) {
@@ -661,7 +662,7 @@ int websocket_accept_loop(websocket_t *init_server)
                                continue;
                        }
                        pthread_setname_np(server_handler->thread_id, "websocket server handler");
-                               /* Detach thread in order to avoid memory leaks. */
+                       /* Detach thread in order to avoid memory leaks. */
                        pthread_detach(server_handler->thread_id);
                }
        }
@@ -683,7 +684,7 @@ int websocket_listen(int *listen_fd, int port)
                return WEBSOCKET_SOCKET_ERROR;
        }
 
-       if (setsockopt(*listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, (socklen_t)sizeof(int)) == -1) {
+       if (setsockopt(*listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, (socklen_t) sizeof(int)) == -1) {
                WEBSOCKET_DEBUG("setsockopt fail\n");
                close(*listen_fd);
                return WEBSOCKET_SOCKET_ERROR;
@@ -748,10 +749,12 @@ websocket_t *websocket_find_table(void)
                        break;
                }
        }
+
        if (i == WEBSOCKET_MAX_CLIENT) {
                WEBSOCKET_DEBUG("websocket clients are too many. limit : %d\n", WEBSOCKET_MAX_CLIENT);
                return NULL;
        }
+
        websocket_update_state(&ws_srv_table[i], WEBSOCKET_RUNNING);
 
        return &ws_srv_table[i];
@@ -765,7 +768,7 @@ websocket_return_t websocket_client_open(websocket_t *client, char *host, char *
        struct sched_param ws_sparam;
 
        if (client == NULL || host == NULL || port == NULL || path == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
                return WEBSOCKET_ALLOCATION_ERROR;
        }
 
@@ -805,7 +808,7 @@ websocket_return_t websocket_client_open(websocket_t *client, char *host, char *
        ws_sparam.sched_priority = WEBSOCKET_PRI;
        pthread_attr_setschedparam(&client->thread_attr, &ws_sparam);
        pthread_attr_setschedpolicy(&client->thread_attr, WEBSOCKET_SCHED_POLICY);
-       if (pthread_create(&client->thread_id, &client->thread_attr, (pthread_startroutine_t)websocket_handler, (pthread_addr_t)client) != 0) {
+       if (pthread_create(&client->thread_id, &client->thread_attr, (pthread_startroutine_t) websocket_handler, (pthread_addr_t) client) != 0) {
                WEBSOCKET_DEBUG("fail to create websocket client thread\n");
                r = WEBSOCKET_ALLOCATION_ERROR;
                goto EXIT_CLIENT_OPEN;
@@ -835,9 +838,10 @@ websocket_return_t websocket_server_open(websocket_t *init_server)
        int r = WEBSOCKET_SUCCESS;
 
        if (init_server == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
                return WEBSOCKET_ALLOCATION_ERROR;
        }
+
        port = init_server->tls_enabled ? 443 : 80;
 
        if (websocket_listen(&(init_server->fd), port) != WEBSOCKET_SUCCESS) {
@@ -859,7 +863,7 @@ websocket_return_t websocket_server_init(websocket_t *server)
        struct websocket_info_t *socket_data = NULL;
 
        if (server == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
                return WEBSOCKET_ALLOCATION_ERROR;
        }
 
@@ -880,7 +884,7 @@ websocket_return_t websocket_server_init(websocket_t *server)
                goto EXIT_SERVER_INIT;
        }
 
-       if (websocket_make_block(server->fd) != WEBSOCKET_SUCCESS) {
+       if (websocket_config_socket(server->fd) != WEBSOCKET_SUCCESS) {
                r = WEBSOCKET_SOCKET_ERROR;
                goto EXIT_SERVER_INIT;
        }
@@ -896,6 +900,7 @@ EXIT_SERVER_INIT:
                mbedtls_ssl_free(server->tls_ssl);
                free(server->tls_ssl);
        }
+
        if (server->ctx) {
                wslay_event_context_free(server->ctx);
                server->ctx = NULL;
@@ -906,19 +911,22 @@ EXIT_SERVER_INIT:
        return r;
 }
 
-void websocket_register_cb(websocket_t *websocket, websocket_cb_t *cb)
+websocket_return_t websocket_register_cb(websocket_t *websocket, websocket_cb_t *cb)
 {
        if (websocket == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
-       } else {
-               wslay_event_config_set_callbacks(websocket->ctx, cb);
+               WEBSOCKET_DEBUG("NULL parameter\n");
+               return WEBSOCKET_ALLOCATION_ERROR;
        }
+
+       wslay_event_config_set_callbacks(websocket->ctx, cb);
+
+       return WEBSOCKET_SUCCESS;
 }
 
 websocket_return_t websocket_queue_msg(websocket_t *websocket, websocket_frame_t *tx_frame)
 {
        if (websocket == NULL || tx_frame == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
                return WEBSOCKET_ALLOCATION_ERROR;
        }
 
@@ -935,7 +943,7 @@ websocket_return_t websocket_queue_ping(websocket_t *websocket)
        websocket_frame_t tx_frame;
 
        if (websocket == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
                return WEBSOCKET_ALLOCATION_ERROR;
        }
 
@@ -945,7 +953,7 @@ websocket_return_t websocket_queue_ping(websocket_t *websocket)
        }
 
        tx_frame.opcode = WEBSOCKET_PING;
-       tx_frame.msg = (uint8_t *)"\0";
+       tx_frame.msg = (uint8_t *) "\0";
        tx_frame.msg_length = strlen((const char *)tx_frame.msg);
 
        return wslay_event_queue_msg(websocket->ctx, &tx_frame);
@@ -954,7 +962,7 @@ websocket_return_t websocket_queue_ping(websocket_t *websocket)
 websocket_return_t websocket_queue_close(websocket_t *websocket, const char *close_message)
 {
        if (websocket == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
                return WEBSOCKET_ALLOCATION_ERROR;
        }
 
@@ -983,24 +991,30 @@ websocket_return_t websocket_queue_close(websocket_t *websocket, const char *clo
        return WEBSOCKET_SUCCESS;
 }
 
-void websocket_update_state(websocket_t *websocket, int state)
+websocket_return_t websocket_update_state(websocket_t *websocket, int state)
 {
        if (websocket == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
+               WEBSOCKET_DEBUG("NULL parameter\n");
+               return WEBSOCKET_ALLOCATION_ERROR;
+       }
+
+       if (state >= WEBSOCKET_STOP && state < WEBSOCKET_MAX_STATE) {
+               websocket->state = state;
        } else {
-               if (WEBSOCKET_STOP <= state && state < WEBSOCKET_MAX_STATE) {
-                       websocket->state = state;
-               } else {
-                       WEBSOCKET_DEBUG("function returned for invalid parameter\n");
-               }
+               WEBSOCKET_DEBUG("function returned for invalid parameter\n");
        }
+
+       return WEBSOCKET_SUCCESS;
 }
 
-void websocket_set_error(websocket_t *websocket, int val)
+websocket_return_t websocket_set_error(websocket_t *websocket, int val)
 {
        if (websocket == NULL) {
-               WEBSOCKET_DEBUG("function returned for null parameter\n");
-       } else {
-               wslay_event_set_error(websocket->ctx, val);
+               WEBSOCKET_DEBUG("NULL parameter\n");
+               return WEBSOCKET_ALLOCATION_ERROR;
        }
+
+       wslay_event_set_error(websocket->ctx, val);
+
+       return WEBSOCKET_SUCCESS;
 }