<p>Joshua Colp <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/14712">View Change</a></p><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, but someone else must approve
Kevin Harwell: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">websocket / pjsip: Increase maximum packet size.<br><br>When dealing with a lot of video streams on WebRTC<br>the resulting SDPs can grow to be quite large. This<br>effectively doubles the maximum size to allow more<br>streams to exist.<br><br>The res_http_websocket module has also been changed<br>to use a buffer on the session for reading in packets<br>to ensure that the stack space usage is not excessive.<br><br>Change-Id: I31d4351d70c8e2c11564807a7528b984f3fbdd01<br>---<br>M res/res_http_websocket.c<br>M res/res_pjsip_pubsub.c<br>M third-party/pjproject/patches/config_site.h<br>3 files changed, 21 insertions(+), 29 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c</span><br><span>index 63fccdd..0e7b89f 100644</span><br><span>--- a/res/res_http_websocket.c</span><br><span>+++ b/res/res_http_websocket.c</span><br><span>@@ -63,15 +63,15 @@</span><br><span> #define MAXIMUM_RECONSTRUCTION_CEILING 8192</span><br><span> #else</span><br><span> /*! \brief Size of the pre-determined buffer for WebSocket frames */</span><br><span style="color: hsl(0, 100%, 40%);">-#define MAXIMUM_FRAME_SIZE 32768</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAXIMUM_FRAME_SIZE 65535</span><br><span> </span><br><span> /*! \brief Default reconstruction size for multi-frame payload reconstruction. If exceeded the next frame will start a</span><br><span> * payload.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-#define DEFAULT_RECONSTRUCTION_CEILING 32768</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEFAULT_RECONSTRUCTION_CEILING MAXIMUM_FRAME_SIZE</span><br><span> </span><br><span> /*! \brief Maximum reconstruction size for multi-frame payload reconstruction. */</span><br><span style="color: hsl(0, 100%, 40%);">-#define MAXIMUM_RECONSTRUCTION_CEILING 32768</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAXIMUM_RECONSTRUCTION_CEILING MAXIMUM_FRAME_SIZE</span><br><span> #endif</span><br><span> </span><br><span> /*! \brief Maximum size of a websocket frame header</span><br><span>@@ -100,6 +100,7 @@</span><br><span> struct websocket_client *client; /*!< Client object when connected as a client websocket */</span><br><span> char session_id[AST_UUID_STR_LEN]; /*!< The identifier for the websocket session */</span><br><span> uint16_t close_status_code; /*!< Status code sent in a CLOSE frame upon shutdown */</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[MAXIMUM_FRAME_SIZE]; /*!< Fixed buffer for reading data into */</span><br><span> };</span><br><span> </span><br><span> /*! \brief Hashing function for protocols */</span><br><span>@@ -565,7 +566,6 @@</span><br><span> </span><br><span> 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)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- char buf[MAXIMUM_FRAME_SIZE] = "";</span><br><span> int fin = 0;</span><br><span> int mask_present = 0;</span><br><span> char *mask = NULL, *new_payload = NULL;</span><br><span>@@ -575,25 +575,25 @@</span><br><span> *payload_len = 0;</span><br><span> *fragmented = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ws_safe_read(session, &buf[0], MIN_WS_HDR_SZ, opcode)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ws_safe_read(session, &session->buf[0], MIN_WS_HDR_SZ, opcode)) {</span><br><span> return -1;</span><br><span> }</span><br><span> frame_size += MIN_WS_HDR_SZ;</span><br><span> </span><br><span> /* 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) */</span><br><span style="color: hsl(0, 100%, 40%);">- *opcode = buf[0] & 0xf;</span><br><span style="color: hsl(0, 100%, 40%);">- *payload_len = buf[1] & 0x7f;</span><br><span style="color: hsl(120, 100%, 40%);">+ *opcode = session->buf[0] & 0xf;</span><br><span style="color: hsl(120, 100%, 40%);">+ *payload_len = session->buf[1] & 0x7f;</span><br><span> if (*opcode == AST_WEBSOCKET_OPCODE_TEXT || *opcode == AST_WEBSOCKET_OPCODE_BINARY || *opcode == AST_WEBSOCKET_OPCODE_CONTINUATION ||</span><br><span> *opcode == AST_WEBSOCKET_OPCODE_PING || *opcode == AST_WEBSOCKET_OPCODE_PONG || *opcode == AST_WEBSOCKET_OPCODE_CLOSE) {</span><br><span style="color: hsl(0, 100%, 40%);">- fin = (buf[0] >> 7) & 1;</span><br><span style="color: hsl(0, 100%, 40%);">- mask_present = (buf[1] >> 7) & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ fin = (session->buf[0] >> 7) & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ mask_present = (session->buf[1] >> 7) & 1;</span><br><span> </span><br><span> /* Based on the mask flag and payload length, determine how much more we need to read before start parsing the rest of the header */</span><br><span> options_len += mask_present ? 4 : 0;</span><br><span> options_len += (*payload_len == 126) ? 2 : (*payload_len == 127) ? 8 : 0;</span><br><span> if (options_len) {</span><br><span> /* read the rest of the header options */</span><br><span style="color: hsl(0, 100%, 40%);">- if (ws_safe_read(session, &buf[frame_size], options_len, opcode)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ws_safe_read(session, &session->buf[frame_size], options_len, opcode)) {</span><br><span> return -1;</span><br><span> }</span><br><span> frame_size += options_len;</span><br><span>@@ -601,19 +601,19 @@</span><br><span> </span><br><span> if (*payload_len == 126) {</span><br><span> /* Grab the 2-byte payload length */</span><br><span style="color: hsl(0, 100%, 40%);">- *payload_len = ntohs(get_unaligned_uint16(&buf[2]));</span><br><span style="color: hsl(0, 100%, 40%);">- mask = &buf[4];</span><br><span style="color: hsl(120, 100%, 40%);">+ *payload_len = ntohs(get_unaligned_uint16(&session->buf[2]));</span><br><span style="color: hsl(120, 100%, 40%);">+ mask = &session->buf[4];</span><br><span> } else if (*payload_len == 127) {</span><br><span> /* Grab the 8-byte payload length */</span><br><span style="color: hsl(0, 100%, 40%);">- *payload_len = ntohl(get_unaligned_uint64(&buf[2]));</span><br><span style="color: hsl(0, 100%, 40%);">- mask = &buf[10];</span><br><span style="color: hsl(120, 100%, 40%);">+ *payload_len = ntohll(get_unaligned_uint64(&session->buf[2]));</span><br><span style="color: hsl(120, 100%, 40%);">+ mask = &session->buf[10];</span><br><span> } else {</span><br><span> /* Just set the mask after the small 2-byte header */</span><br><span style="color: hsl(0, 100%, 40%);">- mask = &buf[2];</span><br><span style="color: hsl(120, 100%, 40%);">+ mask = &session->buf[2];</span><br><span> }</span><br><span> </span><br><span> /* Now read the rest of the payload */</span><br><span style="color: hsl(0, 100%, 40%);">- *payload = &buf[frame_size]; /* payload will start here, at the end of the options, if any */</span><br><span style="color: hsl(120, 100%, 40%);">+ *payload = &session->buf[frame_size]; /* payload will start here, at the end of the options, if any */</span><br><span> frame_size = frame_size + (*payload_len); /* final frame size is header + optional headers + payload data */</span><br><span> if (frame_size > MAXIMUM_FRAME_SIZE) {</span><br><span> ast_log(LOG_WARNING, "Cannot fit huge websocket frame of %zu bytes\n", frame_size);</span><br><span>diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c</span><br><span>index bfa3dc9..2dbe874 100644</span><br><span>--- a/res/res_pjsip_pubsub.c</span><br><span>+++ b/res/res_pjsip_pubsub.c</span><br><span>@@ -146,8 +146,8 @@</span><br><span> that a server has to process.</para></span><br><span> <note></span><br><span> <para>Current limitations limit the size of SIP NOTIFY requests that Asterisk sends</span><br><span style="color: hsl(0, 100%, 40%);">- to 64000 bytes. If your resource list notifications are larger than this maximum, you</span><br><span style="color: hsl(0, 100%, 40%);">- will need to make adjustments.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ to double that of the PJSIP maximum packet length. If your resource list notifications</span><br><span style="color: hsl(120, 100%, 40%);">+ are larger than this maximum, you will need to make adjustments.</para></span><br><span> </note></span><br><span> </description></span><br><span> <configOption name="type"></span><br><span>@@ -1948,15 +1948,7 @@</span><br><span> * we instead take the strategy of pre-allocating the buffer, testing for ourselves</span><br><span> * if the message will fit, and resizing the buffer as required.</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * RFC 3261 says that a SIP UDP request can be up to 65535 bytes long. We're capping</span><br><span style="color: hsl(0, 100%, 40%);">- * it at 64000 for a couple of reasons:</span><br><span style="color: hsl(0, 100%, 40%);">- * 1) Allocating more than 64K at a time is hard to justify</span><br><span style="color: hsl(0, 100%, 40%);">- * 2) If the message goes through proxies, those proxies will want to add Via and</span><br><span style="color: hsl(0, 100%, 40%);">- * Record-Route headers, making the message even larger. Giving some space for</span><br><span style="color: hsl(0, 100%, 40%);">- * those headers is a nice thing to do.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * RFC 3261 does not place an upper limit on the size of TCP requests, but we are</span><br><span style="color: hsl(0, 100%, 40%);">- * going to impose the same 64K limit as a memory savings.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The limit we impose is double that of the maximum packet length.</span><br><span> *</span><br><span> * \param tdata The tdata onto which to allocate a buffer</span><br><span> * \retval 0 Success</span><br><span>@@ -1968,7 +1960,7 @@</span><br><span> int size = -1;</span><br><span> char *buf;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- for (buf_size = PJSIP_MAX_PKT_LEN; size == -1 && buf_size < 64000; buf_size *= 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (buf_size = PJSIP_MAX_PKT_LEN; size == -1 && buf_size < (PJSIP_MAX_PKT_LEN * 2); buf_size *= 2) {</span><br><span> buf = pj_pool_alloc(tdata->pool, buf_size);</span><br><span> size = pjsip_msg_print(tdata->msg, buf, buf_size);</span><br><span> }</span><br><span>diff --git a/third-party/pjproject/patches/config_site.h b/third-party/pjproject/patches/config_site.h</span><br><span>index aea7d0d..5884108 100644</span><br><span>--- a/third-party/pjproject/patches/config_site.h</span><br><span>+++ b/third-party/pjproject/patches/config_site.h</span><br><span>@@ -65,7 +65,7 @@</span><br><span> Enabling it will result in SEGFAULTS when URIs containing escape sequences are encountered.</span><br><span> */</span><br><span> #undef PJSIP_UNESCAPE_IN_PLACE</span><br><span style="color: hsl(0, 100%, 40%);">-#define PJSIP_MAX_PKT_LEN 32000</span><br><span style="color: hsl(120, 100%, 40%);">+#define PJSIP_MAX_PKT_LEN 65535</span><br><span> </span><br><span> #undef PJ_TODO</span><br><span> #define PJ_TODO(x)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/14712">change 14712</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/14712"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: certified/16.8 </div>
<div style="display:none"> Gerrit-Change-Id: I31d4351d70c8e2c11564807a7528b984f3fbdd01 </div>
<div style="display:none"> Gerrit-Change-Number: 14712 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>