ameba micropython sdk first commit

This commit is contained in:
xidameng 2020-07-31 22:16:12 +08:00
commit 8508ee6139
5619 changed files with 1874619 additions and 0 deletions

View file

@ -0,0 +1,130 @@
#ifndef EASYWSCLIENT_H
#define EASYWSCLIENT_H
#include <platform/platform_stdlib.h>
#include "FreeRTOS.h"
#include "queue.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;
}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[128];
char path[128];
char origin[200];
int port;
uint8_t use_ssl;
int sockfd;
readyStateValues readyState;
int tx_len;
int rx_len;
void *tls;
int maxQueueSize;
int queueItemNum;
xQueueHandle ready_send_buf; //tx message ready to send
xQueueHandle 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;
}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

View file

@ -0,0 +1,45 @@
#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
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, ws_conn *conn);
void ws_server_dispatchBinary(ws_conn *conn);
void ws_server_conn_remove(ws_conn *conn);
#endif

View file

@ -0,0 +1,117 @@
#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_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);
#endif

View file

@ -0,0 +1,239 @@
#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) { \
taskENTER_CRITICAL(); \
printf("\n\r[WS_SERVER] "); \
printf(__VA_ARGS__); \
printf("\n\r"); \
taskEXIT_CRITICAL(); \
} \
} while(0)
#define ws_server_log_verbose(...) \
do { \
if(ws_server_debug == WS_SERVER_DEBUG_VERBOSE) { \
taskENTER_CRITICAL(); \
printf("\n\r[WS_SERVER] "); \
printf(__VA_ARGS__); \
printf("\n\r"); \
taskEXIT_CRITICAL(); \
} \
} 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.
* @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.
* @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 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_ */