mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge 14ca432a2b
into 46acfdce96
This commit is contained in:
commit
da08931e03
@ -127,7 +127,7 @@ static ssize_t tcp_read(esp_tls_t *tls, char *data, size_t datalen)
|
|||||||
|
|
||||||
static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen)
|
static ssize_t tcp_write(esp_tls_t *tls, const char *data, size_t datalen)
|
||||||
{
|
{
|
||||||
return send(tls->sockfd, data, datalen, 0);
|
return send(tls->sockfd, data, datalen, MSG_MORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen)
|
ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen)
|
||||||
|
@ -56,7 +56,7 @@ int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct httpd_req_aux *ra = r->aux;
|
struct httpd_req_aux *ra = r->aux;
|
||||||
int ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0);
|
int ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, MSG_MORE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
||||||
return ret;
|
return ret;
|
||||||
@ -70,7 +70,7 @@ static esp_err_t httpd_send_all(httpd_req_t *r, const char *buf, size_t buf_len)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while (buf_len > 0) {
|
while (buf_len > 0) {
|
||||||
ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, 0);
|
ret = ra->sd->send_fn(ra->sd->handle, ra->sd->fd, buf, buf_len, MSG_MORE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
|
@ -416,14 +416,14 @@ esp_err_t httpd_ws_send_frame_async(httpd_handle_t hd, int fd, httpd_ws_frame_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Send off header */
|
/* Send off header */
|
||||||
if (sess->send_fn(hd, fd, (const char *)header_buf, tx_len, 0) < 0) {
|
if (sess->send_fn(hd, fd, (const char *)header_buf, tx_len, MSG_MORE) < 0) {
|
||||||
ESP_LOGW(TAG, LOG_FMT("Failed to send WS header"));
|
ESP_LOGW(TAG, LOG_FMT("Failed to send WS header"));
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send off payload */
|
/* Send off payload */
|
||||||
if(frame->len > 0 && frame->payload != NULL) {
|
if(frame->len > 0 && frame->payload != NULL) {
|
||||||
if (sess->send_fn(hd, fd, (const char *)frame->payload, frame->len, 0) < 0) {
|
if (sess->send_fn(hd, fd, (const char *)frame->payload, frame->len, MSG_MORE) < 0) {
|
||||||
ESP_LOGW(TAG, LOG_FMT("Failed to send WS payload"));
|
ESP_LOGW(TAG, LOG_FMT("Failed to send WS payload"));
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// this define will also be used for optimized websocket sends with the
|
||||||
|
// optimized version to prepend the required space for the websocket
|
||||||
|
// header
|
||||||
|
#define MAX_WEBSOCKET_HEADER_SIZE 16
|
||||||
|
|
||||||
typedef enum ws_transport_opcodes {
|
typedef enum ws_transport_opcodes {
|
||||||
WS_TRANSPORT_OPCODES_CONT = 0x00,
|
WS_TRANSPORT_OPCODES_CONT = 0x00,
|
||||||
WS_TRANSPORT_OPCODES_TEXT = 0x01,
|
WS_TRANSPORT_OPCODES_TEXT = 0x01,
|
||||||
@ -139,6 +144,37 @@ esp_err_t esp_transport_ws_set_config(esp_transport_handle_t t, const esp_transp
|
|||||||
*/
|
*/
|
||||||
int esp_transport_ws_send_raw(esp_transport_handle_t t, ws_transport_opcodes_t opcode, const char *b, int len, int timeout_ms);
|
int esp_transport_ws_send_raw(esp_transport_handle_t t, ws_transport_opcodes_t opcode, const char *b, int len, int timeout_ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends websocket raw message with custom opcode and payload in a optimized way
|
||||||
|
*
|
||||||
|
* This method is similar to esp_transport_ws_send_raw(), but
|
||||||
|
* it assumes, that the first MAX_WEBSOCKET_HEADER_SIZE bytes
|
||||||
|
* of the buffer should not be sent and should rather be used
|
||||||
|
* for the required websocket header itself. This is done to
|
||||||
|
* have a single TCP packet for header and payload and to avoid
|
||||||
|
* copying and allocating additional resources. The first
|
||||||
|
* MAX_WEBSOCKET_HEADER_SIZE bytes should not be initialized in
|
||||||
|
* any specific way, and the return value (length) will also
|
||||||
|
* include the MAX_WEBSOCKET_HEADER_SIZE byte extra buffer.
|
||||||
|
*
|
||||||
|
* Note that generic esp_transport_write for ws handle sends
|
||||||
|
* binary massages by default if size is > 0 and
|
||||||
|
* ping message if message size is set to 0.
|
||||||
|
* This API is provided to support explicit messages with arbitrary opcode,
|
||||||
|
* should it be PING, PONG or TEXT message with arbitrary data.
|
||||||
|
*
|
||||||
|
* @param[in] t Websocket transport handle
|
||||||
|
* @param[in] opcode ws operation code
|
||||||
|
* @param[in] buffer The buffer
|
||||||
|
* @param[in] len The length
|
||||||
|
* @param[in] timeout_ms The timeout milliseconds (-1 indicates block forever)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - Number of bytes was written
|
||||||
|
* - (-1) if there are any errors, should check errno
|
||||||
|
*/
|
||||||
|
int esp_transport_ws_send_raw_optimized(esp_transport_handle_t t, ws_transport_opcodes_t opcode, const char *b, int len, int timeout_ms);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns websocket fin flag for last received data
|
* @brief Returns websocket fin flag for last received data
|
||||||
*
|
*
|
||||||
|
@ -246,7 +246,7 @@ static int tcp_write(esp_transport_handle_t t, const char *buffer, int len, int
|
|||||||
ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->sockfd, timeout_ms);
|
ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->sockfd, timeout_ms);
|
||||||
return poll;
|
return poll;
|
||||||
}
|
}
|
||||||
int ret = send(ssl->sockfd, (const unsigned char *) buffer, len, 0);
|
int ret = send(ssl->sockfd, (const unsigned char *) buffer, len, MSG_MORE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ESP_LOGE(TAG, "tcp_write error, errno=%s", strerror(errno));
|
ESP_LOGE(TAG, "tcp_write error, errno=%s", strerror(errno));
|
||||||
esp_transport_capture_errno(t, errno);
|
esp_transport_capture_errno(t, errno);
|
||||||
|
@ -36,7 +36,6 @@ static const char *TAG = "transport_ws";
|
|||||||
#define WS_MASK 0x80
|
#define WS_MASK 0x80
|
||||||
#define WS_SIZE16 126
|
#define WS_SIZE16 126
|
||||||
#define WS_SIZE64 127
|
#define WS_SIZE64 127
|
||||||
#define MAX_WEBSOCKET_HEADER_SIZE 16
|
|
||||||
#define WS_RESPONSE_OK 101
|
#define WS_RESPONSE_OK 101
|
||||||
#define WS_TRANSPORT_MAX_CONTROL_FRAME_BUFFER_LEN 125
|
#define WS_TRANSPORT_MAX_CONTROL_FRAME_BUFFER_LEN 125
|
||||||
|
|
||||||
@ -415,6 +414,92 @@ static int _ws_write(esp_transport_handle_t t, int opcode, int mask_flag, const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is similar to _ws_write() but it assumes, that the first 16 bytes of the buffer should not be sent and
|
||||||
|
// should rather be used for the required websocket header itself. This is done to have a single TCP packet for header
|
||||||
|
// and payload and to avoid copying and allocating additional resources. The first 16 bytes should not be initialized
|
||||||
|
// in any specific way, and the return value (length) will also include the 16 byte extra buffer.
|
||||||
|
static int _ws_write_optimized(esp_transport_handle_t t, int opcode, int mask_flag, const char *b, int len, int timeout_ms)
|
||||||
|
{
|
||||||
|
assert(len >= MAX_WEBSOCKET_HEADER_SIZE);
|
||||||
|
|
||||||
|
transport_ws_t *ws = esp_transport_get_context_data(t);
|
||||||
|
char *buffer = (char *)b;
|
||||||
|
char *ws_header;
|
||||||
|
// char *mask;
|
||||||
|
int header_len = 0; //, i;
|
||||||
|
|
||||||
|
int poll_write;
|
||||||
|
if ((poll_write = esp_transport_poll_write(ws->parent, timeout_ms)) <= 0) {
|
||||||
|
ESP_LOGE(TAG, "Error transport_poll_write");
|
||||||
|
return poll_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len2 = len - MAX_WEBSOCKET_HEADER_SIZE;
|
||||||
|
if (len2 <= 125) {
|
||||||
|
ws_header = buffer+MAX_WEBSOCKET_HEADER_SIZE-2-4;
|
||||||
|
ws_header[header_len++] = opcode;
|
||||||
|
ws_header[header_len++] = (uint8_t)(len2 | mask_flag);
|
||||||
|
} else if (len2 < 65536) {
|
||||||
|
ws_header = buffer+MAX_WEBSOCKET_HEADER_SIZE-4-4;
|
||||||
|
ws_header[header_len++] = opcode;
|
||||||
|
ws_header[header_len++] = WS_SIZE16 | mask_flag;
|
||||||
|
ws_header[header_len++] = (uint8_t)(len2 >> 8);
|
||||||
|
ws_header[header_len++] = (uint8_t)(len2 & 0xFF);
|
||||||
|
} else {
|
||||||
|
ws_header = buffer+MAX_WEBSOCKET_HEADER_SIZE-10-4;
|
||||||
|
ws_header[header_len++] = opcode;
|
||||||
|
ws_header[header_len++] = WS_SIZE64 | mask_flag;
|
||||||
|
/* Support maximum 4 bytes length */
|
||||||
|
ws_header[header_len++] = 0; //(uint8_t)((len >> 56) & 0xFF);
|
||||||
|
ws_header[header_len++] = 0; //(uint8_t)((len >> 48) & 0xFF);
|
||||||
|
ws_header[header_len++] = 0; //(uint8_t)((len >> 40) & 0xFF);
|
||||||
|
ws_header[header_len++] = 0; //(uint8_t)((len >> 32) & 0xFF);
|
||||||
|
ws_header[header_len++] = (uint8_t)((len2 >> 24) & 0xFF);
|
||||||
|
ws_header[header_len++] = (uint8_t)((len2 >> 16) & 0xFF);
|
||||||
|
ws_header[header_len++] = (uint8_t)((len2 >> 8) & 0xFF);
|
||||||
|
ws_header[header_len++] = (uint8_t)((len2 >> 0) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask_flag) {
|
||||||
|
ws_header[header_len++] = 0;
|
||||||
|
ws_header[header_len++] = 0;
|
||||||
|
ws_header[header_len++] = 0;
|
||||||
|
ws_header[header_len++] = 0;
|
||||||
|
// mask = &ws_header[header_len];
|
||||||
|
// mask = 0;
|
||||||
|
// ssize_t rc;
|
||||||
|
// if ((rc = getrandom(ws_header + header_len, 4, 0)) < 0) {
|
||||||
|
// ESP_LOGD(TAG, "getrandom() returned %zd", rc);
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
// header_len += 4;
|
||||||
|
|
||||||
|
// for (i = MAX_WEBSOCKET_HEADER_SIZE; i < len; ++i) {
|
||||||
|
// buffer[i] = (buffer[i] ^ mask[i % 4]);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (esp_transport_write(ws->parent, ws_header, len - MAX_WEBSOCKET_HEADER_SIZE + header_len, timeout_ms) != header_len) {
|
||||||
|
// ESP_LOGE(TAG, "Error write header");
|
||||||
|
// return -1;
|
||||||
|
// }
|
||||||
|
// if (len == 0) {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
int ret = esp_transport_write(ws->parent, ws_header, len - MAX_WEBSOCKET_HEADER_SIZE + header_len, timeout_ms);
|
||||||
|
ESP_LOGI(TAG, "len=%d header_len=%d total_size=%d sent=%d", len, header_len, len - MAX_WEBSOCKET_HEADER_SIZE + header_len, ret);
|
||||||
|
// in case of masked transport we have to revert back to the original data, as ws layer
|
||||||
|
// does not create its own copy of data to be sent
|
||||||
|
if (mask_flag) {
|
||||||
|
// mask = &ws_header[header_len - 4];
|
||||||
|
// for (i = 0; i < len; ++i) {
|
||||||
|
// buffer[i] = (buffer[i] ^ mask[i % 4]);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
return ret + (ws_header - buffer);
|
||||||
|
}
|
||||||
|
|
||||||
int esp_transport_ws_send_raw(esp_transport_handle_t t, ws_transport_opcodes_t opcode, const char *b, int len, int timeout_ms)
|
int esp_transport_ws_send_raw(esp_transport_handle_t t, ws_transport_opcodes_t opcode, const char *b, int len, int timeout_ms)
|
||||||
{
|
{
|
||||||
uint8_t op_code = ws_get_bin_opcode(opcode);
|
uint8_t op_code = ws_get_bin_opcode(opcode);
|
||||||
@ -426,6 +511,17 @@ int esp_transport_ws_send_raw(esp_transport_handle_t t, ws_transport_opcodes_t o
|
|||||||
return _ws_write(t, op_code, WS_MASK, b, len, timeout_ms);
|
return _ws_write(t, op_code, WS_MASK, b, len, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int esp_transport_ws_send_raw_optimized(esp_transport_handle_t t, ws_transport_opcodes_t opcode, const char *b, int len, int timeout_ms)
|
||||||
|
{
|
||||||
|
uint8_t op_code = ws_get_bin_opcode(opcode);
|
||||||
|
if (t == NULL) {
|
||||||
|
ESP_LOGE(TAG, "Transport must be a valid ws handle");
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "Sending raw ws message with opcode %d", op_code);
|
||||||
|
return _ws_write_optimized(t, op_code, WS_MASK, b, len, timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
static int ws_write(esp_transport_handle_t t, const char *b, int len, int timeout_ms)
|
static int ws_write(esp_transport_handle_t t, const char *b, int len, int timeout_ms)
|
||||||
{
|
{
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user