initial commit
This commit is contained in:
141
lib/amb1_sdk/common/network/websocket/libwsclient.h
Normal file
141
lib/amb1_sdk/common/network/websocket/libwsclient.h
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifndef EASYWSCLIENT_H
|
||||
#define EASYWSCLIENT_H
|
||||
#include <platform/platform_stdlib.h>
|
||||
#include "osdep_service.h"
|
||||
|
||||
|
||||
#define WSCLIENT_TLS_POLARSSL 0 /*!< Use PolarSSL for TLS when WSCLIENT */
|
||||
#define WSCLIENT_TLS_MBEDTLS 1 /*!< Use mbedTLS for TLS when WSCLIENT */
|
||||
|
||||
#if CONFIG_USE_POLARSSL
|
||||
#define WSCLIENT_USE_TLS WSCLIENT_TLS_POLARSSL
|
||||
#elif CONFIG_USE_MBEDTLS
|
||||
#define WSCLIENT_USE_TLS WSCLIENT_TLS_MBEDTLS
|
||||
#endif
|
||||
|
||||
/****************Define the debug message level*********************/
|
||||
#define DEBUG_WSCLIENT 1
|
||||
|
||||
#define WSCLIENT_LOG(level, fmt, ...) printf("\n\r[WSCLIENT %s] %s: " fmt "\n", level, __FUNCTION__, ##__VA_ARGS__)
|
||||
#if DEBUG_WSCLIENT == 2
|
||||
#define WSCLIENT_DEBUG(fmt, ...) WSCLIENT_LOG("DEBUG", fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define WSCLIENT_DEBUG(fmt, ...)
|
||||
#endif
|
||||
#if DEBUG_WSCLIENT
|
||||
#define WSCLIENT_ERROR(fmt, ...) WSCLIENT_LOG("ERROR", fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define WSCLIENT_ERROR(fmt, ...)
|
||||
#endif
|
||||
/*******************************************************************/
|
||||
|
||||
/****************Define the structures used*************************/
|
||||
typedef enum{
|
||||
CLOSING,
|
||||
CLOSED,
|
||||
CONNECTING,
|
||||
OPEN
|
||||
} readyStateValues;
|
||||
|
||||
struct wsheader_type{
|
||||
unsigned header_size;
|
||||
int fin;
|
||||
int mask;
|
||||
enum opcode_type {
|
||||
CONTINUATION = 0x0,
|
||||
TEXT_FRAME = 0x1,
|
||||
BINARY_FRAME = 0x2,
|
||||
CLOSE = 8,
|
||||
PING = 9,
|
||||
PONG = 0xa,
|
||||
} opcode;
|
||||
int N0;
|
||||
uint64_t N;
|
||||
uint8_t masking_key[4];
|
||||
};
|
||||
|
||||
struct rsv_bits_field{
|
||||
uint8_t RSV1 : 1;
|
||||
uint8_t RSV2 : 1;
|
||||
uint8_t RSV3 : 1;
|
||||
};
|
||||
|
||||
typedef struct send_buf_t{
|
||||
uint8_t *txbuf;
|
||||
int tx_len;
|
||||
int send_offset;
|
||||
}send_buf;
|
||||
|
||||
struct _wsclient_context;
|
||||
|
||||
struct ws_fun_ops{
|
||||
int (*hostname_connect)(struct _wsclient_context *wsclient);
|
||||
void (*client_close)(struct _wsclient_context *wsclient);
|
||||
int (*client_send)(struct _wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
int (*client_read)(struct _wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
};
|
||||
|
||||
typedef struct _wsclient_context{
|
||||
char *host;
|
||||
char *path;
|
||||
char *origin;
|
||||
int port;
|
||||
char *protocol;
|
||||
int protocol_len;
|
||||
char *version;
|
||||
int version_len;
|
||||
char *custom_token;
|
||||
int custom_token_len;
|
||||
uint8_t use_ssl;
|
||||
int sockfd;
|
||||
readyStateValues readyState;
|
||||
int tx_len;
|
||||
int rx_len;
|
||||
void *tls;
|
||||
int max_queue_size;
|
||||
int wsclient_reallength;
|
||||
int stable_buf_num;
|
||||
int ready_send_buf_num;
|
||||
int recycle_send_buf_num;
|
||||
_xqueue ready_send_buf; //tx message ready to send
|
||||
_xqueue recycle_send_buf; //usable buf to load tx message
|
||||
uint8_t *txbuf;
|
||||
struct rsv_bits_field txRsvBits;
|
||||
uint8_t *rxbuf;
|
||||
struct rsv_bits_field rxRsvBits;
|
||||
uint8_t *receivedData;
|
||||
struct ws_fun_ops fun_ops;
|
||||
_mutex queue_mutex;
|
||||
}wsclient_context;
|
||||
/*******************************************************************/
|
||||
|
||||
/****************General functions used by wsclient*****************/
|
||||
void ws_get_random_bytes(void *buf, size_t len);
|
||||
void* ws_malloc(unsigned int size);
|
||||
void ws_free(void *buf);
|
||||
int ws_client_handshake(wsclient_context *wsclient);
|
||||
int ws_check_handshake(wsclient_context *wsclient);
|
||||
int ws_sendData(uint8_t type, size_t message_size, uint8_t* message, int useMask, wsclient_context *wsclient);
|
||||
/*******************************************************************/
|
||||
|
||||
/*************Functions used by wsclient without SSL****************/
|
||||
|
||||
int ws_hostname_connect(wsclient_context *wsclient);
|
||||
int ws_client_read(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
int ws_client_send(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
void ws_client_close(wsclient_context *wsclient);
|
||||
/*******************************************************************/
|
||||
|
||||
/***************Functions used by wsclient with SSL*****************/
|
||||
int wss_hostname_connect(wsclient_context *wsclient);
|
||||
int wss_client_read(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
int wss_client_send(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
void wss_client_close(wsclient_context *wsclient);
|
||||
void *wss_tls_connect(int *sock , char *host, int port);
|
||||
int wss_tls_handshake(void *tls_in);
|
||||
void wss_tls_close(void *tls_in,int *sock);
|
||||
int wss_tls_write(void *tls_in, char *request, int request_len);
|
||||
int wss_tls_read(void *tls_in, char *buffer, int buf_len);
|
||||
/*******************************************************************/
|
||||
|
||||
#endif
|
||||
48
lib/amb1_sdk/common/network/websocket/ws_server_msg.h
Normal file
48
lib/amb1_sdk/common/network/websocket/ws_server_msg.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _WS_SERVER_MSG_H_
|
||||
#define _WS_SERVER_MSG_H_
|
||||
#include <websocket/wsserver_api.h>
|
||||
|
||||
struct ws_data_header_type{
|
||||
size_t header_size;
|
||||
int fin;
|
||||
int mask;
|
||||
enum opcode_type opcode;
|
||||
int N0;
|
||||
uint64_t N;
|
||||
uint8_t masking_key[4];
|
||||
};
|
||||
|
||||
#define WS_SERVER_TLS_POLARSSL 0 /*!< Use PolarSSL for TLS when WSCLIENT */
|
||||
#define WS_SERVER_TLS_MBEDTLS 1 /*!< Use mbedTLS for TLS when WSCLIENT */
|
||||
#if CONFIG_USE_POLARSSL
|
||||
#define WS_SERVER_USE_TLS WS_SERVER_TLS_POLARSSL
|
||||
#elif CONFIG_USE_MBEDTLS
|
||||
#define WS_SERVER_USE_TLS WS_SERVER_TLS_MBEDTLS
|
||||
#endif
|
||||
|
||||
#define WS_SERVER_SEND_BY_POLL 0 /*!< WS server send data when polling */
|
||||
#define WS_SERVER_SEND_DIRECTLY 1 /*!< WS server send data directly */
|
||||
|
||||
void *ws_server_malloc(size_t size);
|
||||
|
||||
void ws_server_free(void *ptr);
|
||||
|
||||
int ws_server_write(ws_conn *conn, uint8_t *buf, size_t buf_len);
|
||||
|
||||
int ws_server_read(ws_conn *conn, uint8_t *buf, size_t buf_len);
|
||||
|
||||
void ws_server_response_too_many_requests(ws_conn *conn, char *msg);
|
||||
|
||||
void ws_server_response_bad_request(ws_conn *conn, char *msg);
|
||||
|
||||
int ws_server_handshake_read_header(ws_conn *conn);
|
||||
|
||||
int ws_server_handshake_response(ws_conn *conn);
|
||||
|
||||
void ws_server_sendData(uint8_t type, size_t message_size, uint8_t* message, int useMask, uint8_t send_mode, ws_conn *conn);
|
||||
|
||||
void ws_server_dispatchBinary(ws_conn *conn);
|
||||
|
||||
void ws_server_conn_remove(ws_conn *conn);
|
||||
|
||||
#endif
|
||||
166
lib/amb1_sdk/common/network/websocket/wsclient_api.h
Normal file
166
lib/amb1_sdk/common/network/websocket/wsclient_api.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef WSCLIENT_H
|
||||
#define WSCLIENT_H
|
||||
#include <websocket/libwsclient.h>
|
||||
|
||||
/****************Define if using the polarssl*******************/
|
||||
#define USING_SSL
|
||||
|
||||
/******************Define the function used*********************/
|
||||
#ifdef USING_SSL
|
||||
int wss_set_fun_ops(wsclient_context *wsclient);
|
||||
#define wsclient_set_fun_ops(wsclient) wss_set_fun_ops(wsclient)
|
||||
#else
|
||||
int ws_set_fun_ops(wsclient_context *wsclient);
|
||||
#define wsclient_set_fun_ops(wsclient) ws_set_fun_ops(wsclient)
|
||||
#endif
|
||||
/***************************************************************/
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : create_wsclient
|
||||
** Description : Creating the websocket client context structure
|
||||
** Input : url:websocket server's url
|
||||
** port:websocket server's port, if not given, default 80 for "ws", 443 for "wss"
|
||||
** origin: the address or url of your self
|
||||
** buf_len: the length of tx/rx/received buffer. It determine the maximum bytes of data send and receive.
|
||||
** max_queue_size: max size of queue to buffer messages which are going to send to webserver.
|
||||
** Return : Created: websocket client context structure
|
||||
** Failed: NULL
|
||||
**************************************************************************************************/
|
||||
wsclient_context *create_wsclient(char *url, int port,char *path, char* origin, int buf_len, int max_queue_size);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_connect_url
|
||||
** Description : Connecting to the websocket server
|
||||
** Input : wsclient: the websocket client context created by create_wsclientfunction
|
||||
** Return : Connected: the socket value
|
||||
** Failed: -1
|
||||
**************************************************************************************************/
|
||||
int ws_connect_url(wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_setsockopt_keepalive
|
||||
** Description : Set global value for KeepAlive socket option. These options will be set within ws_connect_url(), so the api must be invoked before ws_connect_url() or it would not take effect.
|
||||
** Input : keepalive_idle: value for TCP_KEEPIDLE option
|
||||
** keepalive_interval: value for TCP_KEEPINTVL option
|
||||
** keepalive_count: value for TCP_KEEPCNT option
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_setsockopt_keepalive(uint32_t keepalive_idle, uint32_t keepalive_interval, uint32_t keepalive_count);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_setsockopt_connect_timeout
|
||||
** Description : Set global value for RCVTO/SNDTO socket option. These options will be set within ws_connect_url() and take effect in connect process, so the api must be invoked before ws_connect_url() or it would not take effect.
|
||||
** Input : recv_timeout: value for SO_RCVTIMEO option
|
||||
** send_timeout: value for SO_SNDTIMEO option
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_setsockopt_timeout(uint32_t recv_timeout, uint32_t send_timeout);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_send
|
||||
** Description : Create the sending string data and copy to queue
|
||||
** Input : message: the string that send to server(cannot exceeding the MAX_DATA_LEN
|
||||
** message_len: the length of the string
|
||||
** use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : 0:send message to queue successfully
|
||||
-1:fail to send message to queue
|
||||
**************************************************************************************************/
|
||||
int ws_send(char* message, int message_len, int use_mask, wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_sendBinary
|
||||
** Description : Create the sending binary data and copy to queue
|
||||
** Input : message: the binary that send to server(cannot exceeding the MAX_DATA_LEN
|
||||
** message_len: the length of the binary
|
||||
** use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : 0:send message to queue successfully
|
||||
-1:fail to send message to queue
|
||||
**************************************************************************************************/
|
||||
int ws_sendBinary(uint8_t* message, int message_len, int use_mask, wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_sendPing
|
||||
** Description : Sending Ping to websocket server
|
||||
** Input : use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : 0:send message to queue successfully
|
||||
-1:fail to send message to queue
|
||||
**************************************************************************************************/
|
||||
int ws_sendPing(int use_mask, wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_poll
|
||||
** Description : Receicing data from server and send the data in tx_buf
|
||||
** Input : timeout(in milliseconds)
|
||||
wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_poll(int timeout, wsclient_context **wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_dispatch
|
||||
** Description : callback function when getting message from server
|
||||
** Input : function that resolve the message received and the message length
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_dispatch(void (*callback)(wsclient_context **, int)) ;
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_getReadyState
|
||||
** Description : Getting the connection status
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : readyStateValues(3 types:CLOSING, CLOSED, OPEN)
|
||||
**************************************************************************************************/
|
||||
readyStateValues ws_getReadyState(wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_close
|
||||
** Description : Closing the connection with websocket server
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_close(wsclient_context **wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_handshake_header_set_protocol
|
||||
** Description : set Sec-WebSocket-Protocol of handshake header
|
||||
** Input : wsclient: the websocket client context
|
||||
** pro: the protocol, eg: "chat, superchat"
|
||||
** len: length of string pro
|
||||
** Return : result(0:ok, -1:fail)
|
||||
**************************************************************************************************/
|
||||
int ws_handshake_header_set_protocol(wsclient_context *wsclient, char *pro, int len);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_handshake_header_set_version
|
||||
** Description : set Sec-WebSocket-Version of handshake header
|
||||
** Input : wsclient: the websocket client context
|
||||
** ver: the version, eg: "13"
|
||||
** len: length of string ver
|
||||
** Return : result(0:ok, -1:fail)
|
||||
**************************************************************************************************/
|
||||
int ws_handshake_header_set_version(wsclient_context *wsclient, char *ver, int len);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_handshake_header_custom_token
|
||||
** Description : add custom token to handshake header
|
||||
** Input : wsclient: the websocket client context
|
||||
** cus: the custom token, eg: "custom_token: value\r\n"
|
||||
** len: length of string cus
|
||||
** Return : result(0:ok, -1:fail)
|
||||
**************************************************************************************************/
|
||||
int ws_handshake_header_custom_token(wsclient_context *wsclient, char *cus, int len);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_multisend_opts
|
||||
** Description : set multi-send queue options. Called once after create_wsclient() and before ws_poll() started.
|
||||
** Input : wsclient: the websocket client context
|
||||
** stable_buf_num: the stable buffer number in send queue. This should be a positive value and
|
||||
should not exceed max_queue_size in create_wsclient(). If free buffers exceed
|
||||
the stable_buf_num, it will be dynamically free.
|
||||
** Return : result(0:ok, -1:fail)
|
||||
**************************************************************************************************/
|
||||
int ws_multisend_opts(wsclient_context *wsclient, int stable_buf_num);
|
||||
#endif
|
||||
255
lib/amb1_sdk/common/network/websocket/wsclient_tls.c
Normal file
255
lib/amb1_sdk/common/network/websocket/wsclient_tls.c
Normal file
@@ -0,0 +1,255 @@
|
||||
#include "platform_opts.h"
|
||||
#include <websocket/libwsclient.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#if (WSCLIENT_USE_TLS == WSCLIENT_TLS_POLARSSL)
|
||||
#include "polarssl/net.h"
|
||||
#include "polarssl/ssl.h"
|
||||
#include <polarssl/memory.h>
|
||||
|
||||
struct wss_tls{
|
||||
ssl_context ctx;
|
||||
};
|
||||
|
||||
#elif (WSCLIENT_USE_TLS == WSCLIENT_TLS_MBEDTLS)
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
|
||||
struct wss_tls{
|
||||
mbedtls_ssl_context ctx;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_net_context socket;
|
||||
};
|
||||
|
||||
static void* my_calloc(size_t nelements, size_t elementSize){
|
||||
size_t size;
|
||||
void *ptr = NULL;
|
||||
|
||||
size = nelements * elementSize;
|
||||
ptr = pvPortMalloc(size);
|
||||
|
||||
if(ptr)
|
||||
memset(ptr, 0, size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static char *ws_itoa(int value){
|
||||
char *val_str;
|
||||
int tmp = value, len = 1;
|
||||
|
||||
while((tmp /= 10) > 0)
|
||||
len ++;
|
||||
|
||||
val_str = (char *) pvPortMalloc(len + 1);
|
||||
sprintf(val_str, "%d", value);
|
||||
|
||||
return val_str;
|
||||
}
|
||||
#endif /* WSCLIENT_USE_TLS */
|
||||
|
||||
int ws_random(void *p_rng, unsigned char *output, size_t output_len);
|
||||
extern int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), void (*free_func)( void * ) );
|
||||
void *wss_tls_connect(int *sock , char *host, int port){
|
||||
#if (WSCLIENT_USE_TLS == WSCLIENT_TLS_POLARSSL)
|
||||
int ret;
|
||||
struct wss_tls *tls =NULL;
|
||||
|
||||
memory_set_own(pvPortMalloc, vPortFree);
|
||||
tls = (struct wss_tls *) malloc(sizeof(struct wss_tls));
|
||||
|
||||
if(tls){
|
||||
ssl_context *ssl = &tls->ctx;
|
||||
memset(tls, 0, sizeof(struct wss_tls));
|
||||
|
||||
if((ret = net_connect(sock, host, port)) != 0){
|
||||
printf("\n[WSCLIENT] ERROR: net_connect %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if((ret = ssl_init(ssl)) != 0){
|
||||
printf("\n[WSCLIENT] ERROR: ssl_init %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ssl_set_endpoint(ssl, 0);
|
||||
ssl_set_authmode(ssl, 0);
|
||||
ssl_set_rng(ssl, ws_random, NULL);
|
||||
ssl_set_bio(ssl, net_recv, sock, net_send, sock);
|
||||
}
|
||||
else{
|
||||
printf("\n[WSCLIENT] ERROR: malloc\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
exit:
|
||||
if(ret && tls) {
|
||||
net_close(*sock);
|
||||
ssl_free(&tls->ctx);
|
||||
free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
return (void *) tls;
|
||||
|
||||
#elif (WSCLIENT_USE_TLS == WSCLIENT_TLS_MBEDTLS)
|
||||
int ret;
|
||||
struct wss_tls *tls =NULL;
|
||||
|
||||
mbedtls_platform_set_calloc_free(my_calloc, vPortFree);
|
||||
tls = (struct wss_tls *) malloc(sizeof(struct wss_tls));
|
||||
|
||||
if(tls){
|
||||
mbedtls_ssl_context *ssl = &tls->ctx;
|
||||
mbedtls_ssl_config *conf = &tls->conf;
|
||||
mbedtls_net_context *server_fd = &tls->socket;
|
||||
memset(tls, 0, sizeof(struct wss_tls));
|
||||
|
||||
server_fd->fd = *sock;
|
||||
char *port_str = ws_itoa (port);
|
||||
|
||||
if((ret = mbedtls_net_connect(server_fd, host, port_str, MBEDTLS_NET_PROTO_TCP)) != 0){
|
||||
printf("\n[WSCLIENT] ERROR: net_connect %d\n", ret);
|
||||
free(port_str);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
free(port_str);
|
||||
*sock = server_fd->fd;
|
||||
mbedtls_ssl_init(ssl);
|
||||
mbedtls_ssl_config_init(conf);
|
||||
mbedtls_ssl_set_bio(ssl, server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
if((ret = mbedtls_ssl_config_defaults(conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
printf("\n[WSCLIENT] ERROR: ssl_config %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
mbedtls_ssl_conf_rng(conf, ws_random, NULL);
|
||||
|
||||
#if MBEDTLS_SSL_MAX_CONTENT_LEN == 4096
|
||||
if(ret = mbedtls_ssl_conf_max_frag_len(conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) {
|
||||
printf("\n[WSCLIENT] ERROR: mbedtls_ssl_conf_max_frag_len %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if((ret = mbedtls_ssl_setup(ssl, conf)) != 0) {
|
||||
printf("\n[WSCLIENT] ERROR: ssl_setup %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
else{
|
||||
printf("\n[WSCLIENT] ERROR: malloc\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
exit:
|
||||
if(ret && tls){
|
||||
mbedtls_net_free(&tls->socket);
|
||||
mbedtls_ssl_free(&tls->ctx);
|
||||
mbedtls_ssl_config_free(&tls->conf);
|
||||
free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
return (void *) tls;
|
||||
#endif /* WSCLIENT_USE_TLS */
|
||||
}
|
||||
|
||||
int wss_tls_handshake(void *tls_in){
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WSCLIENT_USE_TLS == WSCLIENT_TLS_POLARSSL)
|
||||
int ret;
|
||||
|
||||
if((ret = ssl_handshake(&tls->ctx)) != 0) {
|
||||
printf("\n[WSCLIENT] ERROR: ssl_handshake %d\n", ret);
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
printf("\n[WSCLIENT] Use ciphersuite %s\n", ssl_get_ciphersuite(&tls->ctx));
|
||||
}
|
||||
|
||||
return ret;
|
||||
#elif (WSCLIENT_USE_TLS == WSCLIENT_TLS_MBEDTLS)
|
||||
int ret;
|
||||
|
||||
if((ret = mbedtls_ssl_handshake(&tls->ctx)) != 0) {
|
||||
printf("\n[WSCLIENT] ERROR: ssl_handshake -0x%x\n", -ret);
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
printf("\n[WSCLIENT] Use ciphersuite %s\n", mbedtls_ssl_get_ciphersuite(&tls->ctx));
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif /* WSCLIENT_USE_TLS */
|
||||
}
|
||||
|
||||
|
||||
void wss_tls_close(void *tls_in,int *sock){
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WSCLIENT_USE_TLS == WSCLIENT_TLS_POLARSSL)
|
||||
if(tls)
|
||||
ssl_close_notify(&tls->ctx);
|
||||
|
||||
if(*sock != -1){
|
||||
net_close(*sock);
|
||||
*sock = -1;
|
||||
}
|
||||
ssl_free(&tls->ctx);
|
||||
free(tls);
|
||||
tls = NULL;
|
||||
#elif (WSCLIENT_USE_TLS == WSCLIENT_TLS_MBEDTLS)
|
||||
if(tls)
|
||||
mbedtls_ssl_close_notify(&tls->ctx);
|
||||
|
||||
if(*sock != -1){
|
||||
mbedtls_net_free(&tls->socket);
|
||||
*sock = -1;
|
||||
}
|
||||
mbedtls_ssl_free(&tls->ctx);
|
||||
if(tls)
|
||||
mbedtls_ssl_config_free(&tls->conf);
|
||||
free(tls);
|
||||
tls = NULL;
|
||||
#endif /* WSCLIENT_USE_TLS */
|
||||
}
|
||||
|
||||
int wss_tls_write(void *tls_in, char *request, int request_len){
|
||||
int ret;
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WSCLIENT_USE_TLS == WSCLIENT_TLS_POLARSSL)
|
||||
ret = ssl_write(&tls->ctx, request, request_len);
|
||||
if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE)
|
||||
ret = 0;
|
||||
#elif (WSCLIENT_USE_TLS == WSCLIENT_TLS_MBEDTLS)
|
||||
ret = mbedtls_ssl_write(&tls->ctx, (unsigned char const*)request, request_len);
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
ret = 0;
|
||||
#endif /* WSCLIENT_USE_TLS */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wss_tls_read(void *tls_in, char *buffer, int buf_len){
|
||||
int ret;
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WSCLIENT_USE_TLS == WSCLIENT_TLS_POLARSSL)
|
||||
ret = ssl_read(&tls->ctx, buffer, buf_len);
|
||||
if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE
|
||||
|| ret == POLARSSL_ERR_NET_RECV_FAILED)
|
||||
ret =0;
|
||||
#elif (WSCLIENT_USE_TLS == WSCLIENT_TLS_MBEDTLS)
|
||||
ret = mbedtls_ssl_read(&tls->ctx, (unsigned char*)buffer, buf_len);
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
|| ret == MBEDTLS_ERR_NET_RECV_FAILED)
|
||||
ret =0;
|
||||
#endif /* WSCLIENT_USE_TLS */
|
||||
return ret;
|
||||
}
|
||||
260
lib/amb1_sdk/common/network/websocket/wsserver_api.h
Normal file
260
lib/amb1_sdk/common/network/websocket/wsserver_api.h
Normal file
@@ -0,0 +1,260 @@
|
||||
#ifndef _WS_SERVER_API_H_
|
||||
#define _WS_SERVER_API_H_
|
||||
|
||||
#include "platform_stdlib.h"
|
||||
#include "platform_opts.h"
|
||||
|
||||
|
||||
/********************Define the secure level***************************/
|
||||
#define WS_SERVER_SECURE_NONE 0 /*!< Running with WS server */
|
||||
#define WS_SERVER_SECURE_TLS 1 /*!< Running with WSS server */
|
||||
#define WS_SERVER_SECURE_TLS_VERIFY 2 /*!< Running with WSS server and verify client */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
/*******************Define the debug message level*********************/
|
||||
#define WS_SERVER_DEBUG_OFF 0 /*!< Disable websocket server debug log */
|
||||
#define WS_SERVER_DEBUG_ON 1 /*!< Enable websocket server debug log */
|
||||
#define WS_SERVER_DEBUG_VERBOSE 2 /*!< Enable websocket server verbose debug log */
|
||||
|
||||
|
||||
extern uint8_t ws_server_debug;
|
||||
#define ws_server_log(...) \
|
||||
do { \
|
||||
if(ws_server_debug) { \
|
||||
rtw_enter_critical(NULL, NULL); \
|
||||
printf("\n\r[WS_SERVER] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n\r"); \
|
||||
rtw_exit_critical(NULL, NULL); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define ws_server_log_verbose(...) \
|
||||
do { \
|
||||
if(ws_server_debug == WS_SERVER_DEBUG_VERBOSE) { \
|
||||
rtw_enter_critical(NULL, NULL); \
|
||||
printf("\n\r[WS_SERVER] "); \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n\r"); \
|
||||
rtw_exit_critical(NULL, NULL); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/**********************Define the data structures***************************/
|
||||
|
||||
/**
|
||||
* @brief The enum is the list of client connection status.
|
||||
*/
|
||||
|
||||
typedef enum{
|
||||
CLOSED = 0, /*!< Client Connection closed */
|
||||
CONNECTING, /*!< Client is connecting */
|
||||
CONNECTED1, /*!< Client is connected */
|
||||
CONNECTED2, /*!< Connected and server sent ping to client */
|
||||
CLOSING, /*!< Client will be closed */
|
||||
} ws_conn_state;
|
||||
|
||||
|
||||
/**
|
||||
* @brief The structure is the context used for websocket server handshakes header parsing.
|
||||
* @note Only header string includes string terminator.
|
||||
*/
|
||||
struct ws_request {
|
||||
uint8_t *header; /*!< handshake header string parsed in websocket handshake */
|
||||
size_t header_len; /*!< handshake header string length */
|
||||
uint8_t *path; /*!< Pointer to resource path in the parsed handshake header string */
|
||||
size_t path_len; /*!< Resource path data length */
|
||||
uint8_t *query; /*!< Pointer to query string in the parsed handshake header string */
|
||||
size_t query_len; /*!< Query string data length */
|
||||
uint8_t *version; /*!< Pointer to HTTP version in the parsed handshake header string */
|
||||
size_t version_len; /*!< HTTP version data length */
|
||||
uint8_t *host; /*!< Pointer to Host header field in the parsed handshake header string */
|
||||
size_t host_len; /*!< Host header field data length */
|
||||
uint8_t *ws_key; /*!< Pointer to Sec-WebSocket-Key field in the parsed handshake header string */
|
||||
size_t ws_key_len; /*!< Sec-WebSocket-Key field data length */
|
||||
uint8_t *ws_version; /*!< Pointer to Sec-WebSocket-Versions field in the parsed handshake header string */
|
||||
size_t ws_version_len; /*!< Sec-WebSocket-Key field data length */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The structure is the context used for client connection.
|
||||
*/
|
||||
typedef struct _ws_conn {
|
||||
int sock; /*!< Client socket descriptor for connection */
|
||||
struct ws_request request; /*!< Context for websocket server request */
|
||||
void *tls; /*!< Context for TLS connection */
|
||||
uint8_t *response_header; /*!< Pointer to transmission buffer of ws handshake response header */
|
||||
uint32_t last_ping_sent_time; /*!< Last ping sent time in system ticks */
|
||||
uint32_t last_data_comm_time; /*!< Last data received or sent time in system ticks */
|
||||
int tx_len; /*!< The length of the transmission data */
|
||||
int rx_len; /*!< The length of the received data */
|
||||
uint8_t *txbuf; /*!< Pointer to transmission buffer of ws server will send */
|
||||
uint8_t *rxbuf; /*!< Pointer to receiving buffer which received from client */
|
||||
uint8_t *receivedData; /*!< Pointer to decoded receiving data which received from client */
|
||||
ws_conn_state state; /*!< Connection state */
|
||||
}ws_conn;
|
||||
|
||||
/**
|
||||
* @brief The structure is the context used for websocket opcode.
|
||||
*/
|
||||
enum opcode_type {
|
||||
CONTINUATION = 0x0,
|
||||
TEXT_FRAME = 0x1,
|
||||
BINARY_FRAME = 0x2,
|
||||
CLOSE = 8,
|
||||
PING = 9,
|
||||
PONG = 0xa,
|
||||
};
|
||||
/***************************************************************************/
|
||||
|
||||
/******************Functions of the websocekt server************************/
|
||||
|
||||
/**
|
||||
* @brief This function is used to start an WS or WSS server.
|
||||
* @param[in] port: service port
|
||||
* @param[in] max_conn: max client connections allowed
|
||||
* @param[in] stack_bytes: thread stack size in bytes
|
||||
* @param[in] secure: security mode for WS or WSS. Must be WS_SERVER_SECURE_NONE, WS_SERVER_SECURE_TLS, WS_SERVER_SECURE_TLS_VERIFY.
|
||||
* @return 0 : if successful
|
||||
* @return -1 : if error occurred
|
||||
*/
|
||||
int ws_server_start(uint16_t port, uint8_t max_conn, uint32_t stack_bytes, uint8_t secure);
|
||||
|
||||
/**
|
||||
* @brief This function is used to stop a running server
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_stop(void);
|
||||
|
||||
/**
|
||||
* @brief This function is the callback function when getting message from connections.
|
||||
* @param[in] callback: function that resolve the message received with the opcode type.
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_dispatch(void (*callback)(ws_conn *, int, enum opcode_type)) ;
|
||||
|
||||
/**
|
||||
* @brief This function is used to setup websocket server debug.
|
||||
* @param[in] debug: flag to enable/disable ws_server debug. Must be WS_SERVER_DEBUG_OFF, WS_SERVER_DEBUG_ON, WS_SERVER_DEBUG_VERBOSE.
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_setup_debug(uint8_t debug);
|
||||
|
||||
/**
|
||||
* @brief This function is used to setup certificate and key for server before starting with WSS.
|
||||
* @param[in] server_cert: string of server certificate
|
||||
* @param[in] server_key: string of server private key
|
||||
* @param[in] ca_certs: string including certificates in CA trusted chain
|
||||
* @return 0 : if successful
|
||||
* @return -1 : if error occurred
|
||||
* @note Must be used before ws_server_start() if staring WSS server
|
||||
*/
|
||||
int ws_server_setup_cert(const char *server_cert, const char *server_key, const char *ca_certs);
|
||||
|
||||
/**
|
||||
* @brief This function is used to setup the interval of ping for server.
|
||||
* @param[in] interval_ms: interval in ms
|
||||
* @return None
|
||||
* @note The default value is 30s
|
||||
*/
|
||||
void ws_server_setup_ping_interval(int interval_ms);
|
||||
|
||||
/**
|
||||
* @brief This function is used to setup the timeout if there is no data between server and client.
|
||||
* @param[in] timeout_ms: timeout in ms
|
||||
* @return None
|
||||
* @note The default value is 0 which means disable kick client even there is no data transmission.
|
||||
*/
|
||||
void ws_server_setup_idle_timeout(int timeout_ms);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is used to setup the tx rx buffer size for each connection.
|
||||
* @param[in] tx_size: tx buffer size
|
||||
* @param[in] rx_size: rx_buffer
|
||||
* @return None
|
||||
* @note The default value is 256 bytes
|
||||
*/
|
||||
void ws_server_setup_tx_rx_size(size_t tx_size, size_t rx_size);
|
||||
|
||||
/**
|
||||
* @brief This function is show the current connections and their status.
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_print_status(void);
|
||||
|
||||
/**
|
||||
* @brief This function is used to get connection info.
|
||||
* @param[in] conn_no: the number of connection
|
||||
* @return the ws_conn which contains the detail info of the connection
|
||||
* @note The conn_no should be small than ws_server_max_conn
|
||||
*/
|
||||
ws_conn *ws_server_get_conn_info(int conn_no);
|
||||
|
||||
/**
|
||||
* @brief This function is used to sending Ping to websocket connection.
|
||||
* @param[in] ws_conn: the websocket connection
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_sendPing(ws_conn *conn);
|
||||
|
||||
/**
|
||||
* @brief This function is used to create the sending binary data and copy to tx_bufs. Data will be sent while polling.
|
||||
* @param[in] message: the binary data that will be sent to client
|
||||
* @param[in] message_len: the length of the binary data
|
||||
* @param[in] use_mask: 0/1; 1 means using mask for data
|
||||
* @param[in] ws_conn: the websocket connection
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_sendBinary(uint8_t* message, int message_len, int use_mask, ws_conn *conn);
|
||||
|
||||
/**
|
||||
* @brief This function is used to create the sending text data and copy to tx_bufs. Data will be sent while polling.
|
||||
* @param[in] message: the text data that will be sent to client
|
||||
* @param[in] message_len: the length of the text data
|
||||
* @param[in] use_mask: 0/1; 1 means using mask for data
|
||||
* @param[in] ws_conn: the websocket connection
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_sendText(char* message, int message_len, int use_mask, ws_conn *conn);
|
||||
|
||||
/**
|
||||
* @brief This function is used to create the sending binary data and send directly instead of sending while polling.
|
||||
* @param[in] message: the binary data that will be sent to client
|
||||
* @param[in] message_len: the length of the binary data
|
||||
* @param[in] use_mask: 0/1; 1 means using mask for data
|
||||
* @param[in] ws_conn: the websocket connection
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_direct_sendBinary(uint8_t* message, int message_len, int use_mask, ws_conn *conn);
|
||||
|
||||
/**
|
||||
* @brief This function is used to create the sending text data and send directly instead of sending while polling.
|
||||
* @param[in] message: the text data that will be sent to client
|
||||
* @param[in] message_len: the length of the text data
|
||||
* @param[in] use_mask: 0/1; 1 means using mask for data
|
||||
* @param[in] ws_conn: the websocket connection
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_direct_sendText(char* message, int message_len, int use_mask, ws_conn *conn);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is used to sending close to websocket connection.
|
||||
* @param[in] ws_conn: the websocket connection
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_sendClose(ws_conn *conn);
|
||||
|
||||
/**
|
||||
* @brief This function is used to remove the websocket client connection.
|
||||
* @param[in] ws_conn: the websocket connection which will be removed
|
||||
* @return None
|
||||
*/
|
||||
void ws_server_conn_remove(ws_conn *conn);
|
||||
/***************************************************************************/
|
||||
|
||||
#endif /* _WS_SERVER_API_H_ */
|
||||
407
lib/amb1_sdk/common/network/websocket/wsserver_tls.c
Normal file
407
lib/amb1_sdk/common/network/websocket/wsserver_tls.c
Normal file
@@ -0,0 +1,407 @@
|
||||
#include "platform_opts.h"
|
||||
#include <websocket/wsserver_api.h>
|
||||
#include <websocket/ws_server_msg.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
#include "polarssl/net.h"
|
||||
#include "polarssl/ssl.h"
|
||||
#include "polarssl/base64.h"
|
||||
#include <polarssl/memory.h>
|
||||
#include "osdep_service.h"
|
||||
|
||||
struct wss_tls{
|
||||
ssl_context ctx;
|
||||
};
|
||||
|
||||
static x509_crt wss_certs; /*!< Certificates of server and CA */
|
||||
static pk_context wss_key; /*!< Private key of server */
|
||||
|
||||
static int _verify_func(void *data, x509_crt *crt, int depth, int *flags)
|
||||
{
|
||||
char buf[1024];
|
||||
x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
|
||||
if(*flags)
|
||||
printf("\n[WS_SERVER] ERROR: certificate verify\n%s\n", buf);
|
||||
else
|
||||
printf("\n[WS_SERVER] Certificate verified\n%s\n", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/base64.h"
|
||||
#include "mbedtls/sha1.h"
|
||||
#include "osdep_service.h"
|
||||
|
||||
struct wss_tls{
|
||||
mbedtls_ssl_context ctx;
|
||||
mbedtls_ssl_config conf;
|
||||
};
|
||||
|
||||
static mbedtls_x509_crt wss_certs; /*!< Certificates of server and CA */
|
||||
static mbedtls_pk_context wss_key; /*!< Private key of server */
|
||||
|
||||
static int _verify_func(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
/* To avoid gcc warnings */
|
||||
( void ) data;
|
||||
( void ) depth;
|
||||
|
||||
char buf[1024];
|
||||
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
|
||||
if(*flags)
|
||||
printf("\n[WS_SERVER] ERROR: certificate verify\n%s\n", buf);
|
||||
else
|
||||
printf("\n[WS_SERVER] Certificate verified\n%s\n", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* _calloc_func(size_t nmemb, size_t size)
|
||||
{
|
||||
size_t mem_size;
|
||||
void *ptr = NULL;
|
||||
|
||||
mem_size = nmemb * size;
|
||||
ptr = pvPortMalloc(mem_size);
|
||||
|
||||
if(ptr)
|
||||
memset(ptr, 0, mem_size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#endif /* WS_SERVER_USE_TLS */
|
||||
|
||||
static int _random_func(void *p_rng, unsigned char *output, size_t output_len)
|
||||
{
|
||||
/* To avoid gcc warnings */
|
||||
( void ) p_rng;
|
||||
|
||||
rtw_get_random_bytes(output, output_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ws_server_tls_setup_init(const char *server_cert, const char *server_key, const char *ca_certs)
|
||||
{
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
int ret = 0;
|
||||
|
||||
memory_set_own(pvPortMalloc, vPortFree);
|
||||
memset(&wss_certs, 0, sizeof(x509_crt));
|
||||
memset(&wss_key, 0, sizeof(pk_context));
|
||||
x509_crt_init(&wss_certs);
|
||||
pk_init(&wss_key);
|
||||
|
||||
// set server certificate for the first certificate
|
||||
if((ret = x509_crt_parse(&wss_certs, (const unsigned char *) server_cert, strlen(server_cert))) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: x509_crt_parse %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// set trusted ca certificates next to server certificate
|
||||
if((ret = x509_crt_parse(&wss_certs, (const unsigned char *) ca_certs, strlen(ca_certs))) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: x509_crt_parse %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if((ret = pk_parse_key(&wss_key, (const unsigned char *) server_key, strlen(server_key), NULL, 0)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: pk_parse_key %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if(ret) {
|
||||
x509_crt_free(&wss_certs);
|
||||
pk_free(&wss_key);
|
||||
}
|
||||
|
||||
return ret;
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
int ret = 0;
|
||||
|
||||
mbedtls_platform_set_calloc_free(_calloc_func, vPortFree);
|
||||
memset(&wss_certs, 0, sizeof(mbedtls_x509_crt));
|
||||
memset(&wss_key, 0, sizeof(mbedtls_pk_context));
|
||||
mbedtls_x509_crt_init(&wss_certs);
|
||||
mbedtls_pk_init(&wss_key);
|
||||
|
||||
// set server certificate for the first certificate
|
||||
if((ret = mbedtls_x509_crt_parse(&wss_certs, (const unsigned char *) server_cert, strlen(server_cert) + 1)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_x509_crt_parse %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// set trusted ca certificates next to server certificate
|
||||
if((ret = mbedtls_x509_crt_parse(&wss_certs, (const unsigned char *) ca_certs, strlen(ca_certs) + 1)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_x509_crt_parse %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if((ret = mbedtls_pk_parse_key(&wss_key, (const unsigned char *) server_key, strlen(server_key) + 1, NULL, 0)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_pk_parse_key %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if(ret) {
|
||||
mbedtls_x509_crt_free(&wss_certs);
|
||||
mbedtls_pk_free(&wss_key);
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ws_server_tls_setup_free(void)
|
||||
{
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
x509_crt_free(&wss_certs);
|
||||
pk_free(&wss_key);
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
mbedtls_x509_crt_free(&wss_certs);
|
||||
mbedtls_pk_free(&wss_key);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *ws_server_tls_new_handshake(int *sock, uint8_t secure)
|
||||
{
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
int ret = 0;
|
||||
struct wss_tls *tls = NULL;
|
||||
ssl_context *ssl = NULL;
|
||||
|
||||
if((tls = (struct wss_tls *) malloc(sizeof(struct wss_tls))) != NULL) {
|
||||
memset(tls, 0, sizeof(struct wss_tls));
|
||||
ssl = &tls->ctx;
|
||||
|
||||
if((ret = ssl_init(ssl)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: ssl_init %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ssl_set_endpoint(ssl, SSL_IS_SERVER);
|
||||
ssl_set_authmode(ssl, SSL_VERIFY_NONE);
|
||||
ssl_set_rng(ssl, _random_func, NULL);
|
||||
ssl_set_bio(ssl, net_recv, sock, net_send, sock);
|
||||
ssl_set_ca_chain(ssl, wss_certs.next, NULL, NULL);
|
||||
|
||||
if(secure == WS_SERVER_SECURE_TLS_VERIFY) {
|
||||
ssl_set_authmode(ssl, SSL_VERIFY_REQUIRED);
|
||||
ssl_set_verify(ssl, _verify_func, NULL);
|
||||
}
|
||||
|
||||
if((ret = ssl_set_own_cert(ssl, &wss_certs, &wss_key)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: ssl_set_own_cert %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if((ret = ssl_handshake(ssl)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: ssl_handshake %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
printf("\n[WS_SERVER] Use ciphersuite %s\n", ssl_get_ciphersuite(ssl));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
printf("\n[WS_SERVER] ERROR: wss malloc\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if(ret && tls) {
|
||||
ssl_close_notify(ssl);
|
||||
ssl_free(ssl);
|
||||
free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
|
||||
return (void *) tls;
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
int ret = 0;
|
||||
struct wss_tls *tls = NULL;
|
||||
mbedtls_ssl_context *ssl;
|
||||
mbedtls_ssl_config *conf;
|
||||
|
||||
if((tls = (struct wss_tls *) malloc(sizeof(struct wss_tls))) != NULL) {
|
||||
memset(tls, 0, sizeof(struct wss_tls));
|
||||
ssl = &tls->ctx;
|
||||
conf = &tls->conf;
|
||||
|
||||
mbedtls_ssl_init(ssl);
|
||||
mbedtls_ssl_config_init(conf);
|
||||
|
||||
if((ret = mbedtls_ssl_config_defaults(conf,
|
||||
MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_ssl_config_defaults %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
mbedtls_ssl_conf_rng(conf, _random_func, NULL);
|
||||
mbedtls_ssl_conf_ca_chain(conf, wss_certs.next, NULL);
|
||||
|
||||
if(secure == WS_SERVER_SECURE_TLS_VERIFY) {
|
||||
mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
mbedtls_ssl_conf_verify(conf, _verify_func, NULL);
|
||||
}
|
||||
|
||||
if((ret = mbedtls_ssl_conf_own_cert(conf, &wss_certs, &wss_key)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_ssl_conf_own_cert %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if((ret = mbedtls_ssl_setup(ssl, conf)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_ssl_setup %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio(ssl, sock, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
if((ret = mbedtls_ssl_handshake(ssl)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_ssl_handshake %d\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
printf("\n[WS_SERVER] Use ciphersuite %s\n", mbedtls_ssl_get_ciphersuite(ssl));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
printf("\n[WS_SERVER] ERROR: wss malloc\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if(ret && tls) {
|
||||
mbedtls_ssl_close_notify(ssl);
|
||||
mbedtls_ssl_free(ssl);
|
||||
mbedtls_ssl_config_free(conf);
|
||||
free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
|
||||
return (void *) tls;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ws_server_tls_close(void *tls_in)
|
||||
{
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
ssl_close_notify(&tls->ctx);
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
mbedtls_ssl_close_notify(&tls->ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ws_server_tls_free(void *tls_in)
|
||||
{
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
ssl_free(&tls->ctx);
|
||||
free(tls);
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
mbedtls_ssl_free(&tls->ctx);
|
||||
mbedtls_ssl_config_free(&tls->conf);
|
||||
free(tls);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ws_server_tls_write(void *tls_in, uint8_t *buf, size_t buf_len){
|
||||
int ret;
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
ret = ssl_write(&tls->ctx, buf, buf_len);
|
||||
if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE)
|
||||
ret = 0;
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
ret = mbedtls_ssl_write(&tls->ctx, buf, buf_len);
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
ret = 0;
|
||||
#endif /* WS_SERVER_USE_TLS */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ws_server_tls_read(void *tls_in, uint8_t *buf, size_t buf_len){
|
||||
int ret;
|
||||
struct wss_tls *tls = (struct wss_tls *) tls_in;
|
||||
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
ret = ssl_read(&tls->ctx, buf, buf_len);
|
||||
if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE
|
||||
|| ret == POLARSSL_ERR_NET_RECV_FAILED)
|
||||
ret =0;
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
ret = mbedtls_ssl_read(&tls->ctx, buf, buf_len);
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
|| ret == MBEDTLS_ERR_NET_RECV_FAILED)
|
||||
ret =0;
|
||||
#endif /* WS_SERVER_USE_TLS */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ws_server_base64_encode(uint8_t *data, size_t data_len, char *base64_buf, size_t buf_len)
|
||||
{
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
int ret = 0;
|
||||
|
||||
if((ret = base64_encode((unsigned char*)base64_buf, &buf_len, data, data_len)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: base64_encode %d\n", ret);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
int ret = 0;
|
||||
size_t output_len = 0;
|
||||
|
||||
if((ret = mbedtls_base64_encode((unsigned char *)base64_buf, buf_len, &output_len, data, data_len)) != 0) {
|
||||
printf("\n[WS_SERVER] ERROR: mbedtls_base64_encode %d\n", ret);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ws_server_sha1(const unsigned char *input, size_t ilen, unsigned char output[20])
|
||||
{
|
||||
|
||||
#if (WS_SERVER_USE_TLS == WS_SERVER_TLS_POLARSSL)
|
||||
sha1(input, ilen, output);
|
||||
#elif (WS_SERVER_USE_TLS == WS_SERVER_TLS_MBEDTLS)
|
||||
mbedtls_sha1(input, ilen, output);
|
||||
#endif
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user