/**
* @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.
* 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.
* 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.
* 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
#include <apps/netutils/websocket.h>
#include <apps/netutils/wslay/wslay.h>
-#include <tinyara/wqueue.h>
-
/****************************************************************************
* Definitions
****************************************************************************/
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) {
return WEBSOCKET_SUCCESS;
}
-int websocket_make_block(int fd)
+websocket_return_t websocket_config_socket(int fd)
{
int r;
int flags;
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;
}
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);
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);
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) {
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");
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");
}
}
- if (WEBSOCKET_HANDLER_TIMEOUT == 0) {
- work_cancel(WEBSOCKET_WQ, &websocket->time_worker);
- }
-
return WEBSOCKET_SUCCESS;
}
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)
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));
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) {
}
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;
}
}
- 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);
}
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) {
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);
}
}
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;
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];
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;
}
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;
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) {
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;
}
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;
}
mbedtls_ssl_free(server->tls_ssl);
free(server->tls_ssl);
}
+
if (server->ctx) {
wslay_event_context_free(server->ctx);
server->ctx = NULL;
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;
}
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;
}
}
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);
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;
}
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;
}