mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Less tcp packet fragmentation
This commit is contained in:
parent
52bca70b1a
commit
14ca432a2b
@ -123,7 +123,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)
|
||||
{
|
||||
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)
|
||||
|
@ -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;
|
||||
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) {
|
||||
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
||||
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;
|
||||
|
||||
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) {
|
||||
ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
|
||||
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 */
|
||||
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"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Send off payload */
|
||||
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"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
@ -14,6 +14,11 @@
|
||||
extern "C" {
|
||||
#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 {
|
||||
WS_TRANSPORT_OPCODES_CONT = 0x00,
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
@ -232,7 +232,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);
|
||||
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) {
|
||||
ESP_LOGE(TAG, "tcp_write error, errno=%s", strerror(errno));
|
||||
esp_transport_capture_errno(t, errno);
|
||||
|
@ -36,7 +36,6 @@ static const char *TAG = "transport_ws";
|
||||
#define WS_MASK 0x80
|
||||
#define WS_SIZE16 126
|
||||
#define WS_SIZE64 127
|
||||
#define MAX_WEBSOCKET_HEADER_SIZE 16
|
||||
#define WS_RESPONSE_OK 101
|
||||
#define WS_TRANSPORT_MAX_CONTROL_FRAME_BUFFER_LEN 125
|
||||
|
||||
@ -366,6 +365,92 @@ static int _ws_write(esp_transport_handle_t t, int opcode, int mask_flag, const
|
||||
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)
|
||||
{
|
||||
uint8_t op_code = ws_get_bin_opcode(opcode);
|
||||
@ -377,6 +462,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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (len == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user