mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 20:04:50 +00:00
websocket / pjsip: Increase maximum packet size.
When dealing with a lot of video streams on WebRTC the resulting SDPs can grow to be quite large. This effectively doubles the maximum size to allow more streams to exist. The res_http_websocket module has also been changed to use a buffer on the session for reading in packets to ensure that the stack space usage is not excessive. Change-Id: I31d4351d70c8e2c11564807a7528b984f3fbdd01
This commit is contained in:
committed by
Joshua Colp
parent
7a43bedd72
commit
af70bbb13a
@@ -63,15 +63,15 @@
|
|||||||
#define MAXIMUM_RECONSTRUCTION_CEILING 8192
|
#define MAXIMUM_RECONSTRUCTION_CEILING 8192
|
||||||
#else
|
#else
|
||||||
/*! \brief Size of the pre-determined buffer for WebSocket frames */
|
/*! \brief Size of the pre-determined buffer for WebSocket frames */
|
||||||
#define MAXIMUM_FRAME_SIZE 32768
|
#define MAXIMUM_FRAME_SIZE 65535
|
||||||
|
|
||||||
/*! \brief Default reconstruction size for multi-frame payload reconstruction. If exceeded the next frame will start a
|
/*! \brief Default reconstruction size for multi-frame payload reconstruction. If exceeded the next frame will start a
|
||||||
* payload.
|
* payload.
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_RECONSTRUCTION_CEILING 32768
|
#define DEFAULT_RECONSTRUCTION_CEILING MAXIMUM_FRAME_SIZE
|
||||||
|
|
||||||
/*! \brief Maximum reconstruction size for multi-frame payload reconstruction. */
|
/*! \brief Maximum reconstruction size for multi-frame payload reconstruction. */
|
||||||
#define MAXIMUM_RECONSTRUCTION_CEILING 32768
|
#define MAXIMUM_RECONSTRUCTION_CEILING MAXIMUM_FRAME_SIZE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! \brief Maximum size of a websocket frame header
|
/*! \brief Maximum size of a websocket frame header
|
||||||
@@ -100,6 +100,7 @@ struct ast_websocket {
|
|||||||
struct websocket_client *client; /*!< Client object when connected as a client websocket */
|
struct websocket_client *client; /*!< Client object when connected as a client websocket */
|
||||||
char session_id[AST_UUID_STR_LEN]; /*!< The identifier for the websocket session */
|
char session_id[AST_UUID_STR_LEN]; /*!< The identifier for the websocket session */
|
||||||
uint16_t close_status_code; /*!< Status code sent in a CLOSE frame upon shutdown */
|
uint16_t close_status_code; /*!< Status code sent in a CLOSE frame upon shutdown */
|
||||||
|
char buf[MAXIMUM_FRAME_SIZE]; /*!< Fixed buffer for reading data into */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief Hashing function for protocols */
|
/*! \brief Hashing function for protocols */
|
||||||
@@ -600,7 +601,6 @@ static inline int ws_safe_read(struct ast_websocket *session, char *buf, size_t
|
|||||||
|
|
||||||
int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented)
|
int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented)
|
||||||
{
|
{
|
||||||
char buf[MAXIMUM_FRAME_SIZE] = "";
|
|
||||||
int fin = 0;
|
int fin = 0;
|
||||||
int mask_present = 0;
|
int mask_present = 0;
|
||||||
char *mask = NULL, *new_payload = NULL;
|
char *mask = NULL, *new_payload = NULL;
|
||||||
@@ -610,25 +610,25 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
|
|||||||
*payload_len = 0;
|
*payload_len = 0;
|
||||||
*fragmented = 0;
|
*fragmented = 0;
|
||||||
|
|
||||||
if (ws_safe_read(session, &buf[0], MIN_WS_HDR_SZ, opcode)) {
|
if (ws_safe_read(session, &session->buf[0], MIN_WS_HDR_SZ, opcode)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
frame_size += MIN_WS_HDR_SZ;
|
frame_size += MIN_WS_HDR_SZ;
|
||||||
|
|
||||||
/* ok, now we have the first 2 bytes, so we know some flags, opcode and payload length (or whether payload length extension will be required) */
|
/* ok, now we have the first 2 bytes, so we know some flags, opcode and payload length (or whether payload length extension will be required) */
|
||||||
*opcode = buf[0] & 0xf;
|
*opcode = session->buf[0] & 0xf;
|
||||||
*payload_len = buf[1] & 0x7f;
|
*payload_len = session->buf[1] & 0x7f;
|
||||||
if (*opcode == AST_WEBSOCKET_OPCODE_TEXT || *opcode == AST_WEBSOCKET_OPCODE_BINARY || *opcode == AST_WEBSOCKET_OPCODE_CONTINUATION ||
|
if (*opcode == AST_WEBSOCKET_OPCODE_TEXT || *opcode == AST_WEBSOCKET_OPCODE_BINARY || *opcode == AST_WEBSOCKET_OPCODE_CONTINUATION ||
|
||||||
*opcode == AST_WEBSOCKET_OPCODE_PING || *opcode == AST_WEBSOCKET_OPCODE_PONG || *opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
|
*opcode == AST_WEBSOCKET_OPCODE_PING || *opcode == AST_WEBSOCKET_OPCODE_PONG || *opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
|
||||||
fin = (buf[0] >> 7) & 1;
|
fin = (session->buf[0] >> 7) & 1;
|
||||||
mask_present = (buf[1] >> 7) & 1;
|
mask_present = (session->buf[1] >> 7) & 1;
|
||||||
|
|
||||||
/* Based on the mask flag and payload length, determine how much more we need to read before start parsing the rest of the header */
|
/* Based on the mask flag and payload length, determine how much more we need to read before start parsing the rest of the header */
|
||||||
options_len += mask_present ? 4 : 0;
|
options_len += mask_present ? 4 : 0;
|
||||||
options_len += (*payload_len == 126) ? 2 : (*payload_len == 127) ? 8 : 0;
|
options_len += (*payload_len == 126) ? 2 : (*payload_len == 127) ? 8 : 0;
|
||||||
if (options_len) {
|
if (options_len) {
|
||||||
/* read the rest of the header options */
|
/* read the rest of the header options */
|
||||||
if (ws_safe_read(session, &buf[frame_size], options_len, opcode)) {
|
if (ws_safe_read(session, &session->buf[frame_size], options_len, opcode)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
frame_size += options_len;
|
frame_size += options_len;
|
||||||
@@ -636,19 +636,19 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
|
|||||||
|
|
||||||
if (*payload_len == 126) {
|
if (*payload_len == 126) {
|
||||||
/* Grab the 2-byte payload length */
|
/* Grab the 2-byte payload length */
|
||||||
*payload_len = ntohs(get_unaligned_uint16(&buf[2]));
|
*payload_len = ntohs(get_unaligned_uint16(&session->buf[2]));
|
||||||
mask = &buf[4];
|
mask = &session->buf[4];
|
||||||
} else if (*payload_len == 127) {
|
} else if (*payload_len == 127) {
|
||||||
/* Grab the 8-byte payload length */
|
/* Grab the 8-byte payload length */
|
||||||
*payload_len = ntohl(get_unaligned_uint64(&buf[2]));
|
*payload_len = ntohll(get_unaligned_uint64(&session->buf[2]));
|
||||||
mask = &buf[10];
|
mask = &session->buf[10];
|
||||||
} else {
|
} else {
|
||||||
/* Just set the mask after the small 2-byte header */
|
/* Just set the mask after the small 2-byte header */
|
||||||
mask = &buf[2];
|
mask = &session->buf[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now read the rest of the payload */
|
/* Now read the rest of the payload */
|
||||||
*payload = &buf[frame_size]; /* payload will start here, at the end of the options, if any */
|
*payload = &session->buf[frame_size]; /* payload will start here, at the end of the options, if any */
|
||||||
frame_size = frame_size + (*payload_len); /* final frame size is header + optional headers + payload data */
|
frame_size = frame_size + (*payload_len); /* final frame size is header + optional headers + payload data */
|
||||||
if (frame_size > MAXIMUM_FRAME_SIZE) {
|
if (frame_size > MAXIMUM_FRAME_SIZE) {
|
||||||
ast_log(LOG_WARNING, "Cannot fit huge websocket frame of %zu bytes\n", frame_size);
|
ast_log(LOG_WARNING, "Cannot fit huge websocket frame of %zu bytes\n", frame_size);
|
||||||
|
@@ -146,8 +146,8 @@
|
|||||||
that a server has to process.</para>
|
that a server has to process.</para>
|
||||||
<note>
|
<note>
|
||||||
<para>Current limitations limit the size of SIP NOTIFY requests that Asterisk sends
|
<para>Current limitations limit the size of SIP NOTIFY requests that Asterisk sends
|
||||||
to 64000 bytes. If your resource list notifications are larger than this maximum, you
|
to double that of the PJSIP maximum packet length. If your resource list notifications
|
||||||
will need to make adjustments.</para>
|
are larger than this maximum, you will need to make adjustments.</para>
|
||||||
</note>
|
</note>
|
||||||
</description>
|
</description>
|
||||||
<configOption name="type">
|
<configOption name="type">
|
||||||
@@ -1950,15 +1950,7 @@ struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_sub
|
|||||||
* we instead take the strategy of pre-allocating the buffer, testing for ourselves
|
* we instead take the strategy of pre-allocating the buffer, testing for ourselves
|
||||||
* if the message will fit, and resizing the buffer as required.
|
* if the message will fit, and resizing the buffer as required.
|
||||||
*
|
*
|
||||||
* RFC 3261 says that a SIP UDP request can be up to 65535 bytes long. We're capping
|
* The limit we impose is double that of the maximum packet length.
|
||||||
* it at 64000 for a couple of reasons:
|
|
||||||
* 1) Allocating more than 64K at a time is hard to justify
|
|
||||||
* 2) If the message goes through proxies, those proxies will want to add Via and
|
|
||||||
* Record-Route headers, making the message even larger. Giving some space for
|
|
||||||
* those headers is a nice thing to do.
|
|
||||||
*
|
|
||||||
* RFC 3261 does not place an upper limit on the size of TCP requests, but we are
|
|
||||||
* going to impose the same 64K limit as a memory savings.
|
|
||||||
*
|
*
|
||||||
* \param tdata The tdata onto which to allocate a buffer
|
* \param tdata The tdata onto which to allocate a buffer
|
||||||
* \retval 0 Success
|
* \retval 0 Success
|
||||||
@@ -1970,7 +1962,7 @@ static int allocate_tdata_buffer(pjsip_tx_data *tdata)
|
|||||||
int size = -1;
|
int size = -1;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
for (buf_size = PJSIP_MAX_PKT_LEN; size == -1 && buf_size < 64000; buf_size *= 2) {
|
for (buf_size = PJSIP_MAX_PKT_LEN; size == -1 && buf_size < (PJSIP_MAX_PKT_LEN * 2); buf_size *= 2) {
|
||||||
buf = pj_pool_alloc(tdata->pool, buf_size);
|
buf = pj_pool_alloc(tdata->pool, buf_size);
|
||||||
size = pjsip_msg_print(tdata->msg, buf, buf_size);
|
size = pjsip_msg_print(tdata->msg, buf, buf_size);
|
||||||
}
|
}
|
||||||
|
2
third-party/pjproject/patches/config_site.h
vendored
2
third-party/pjproject/patches/config_site.h
vendored
@@ -65,7 +65,7 @@
|
|||||||
Enabling it will result in SEGFAULTS when URIs containing escape sequences are encountered.
|
Enabling it will result in SEGFAULTS when URIs containing escape sequences are encountered.
|
||||||
*/
|
*/
|
||||||
#undef PJSIP_UNESCAPE_IN_PLACE
|
#undef PJSIP_UNESCAPE_IN_PLACE
|
||||||
#define PJSIP_MAX_PKT_LEN 32000
|
#define PJSIP_MAX_PKT_LEN 65535
|
||||||
|
|
||||||
#undef PJ_TODO
|
#undef PJ_TODO
|
||||||
#define PJ_TODO(x)
|
#define PJ_TODO(x)
|
||||||
|
Reference in New Issue
Block a user