<p>Joshua Colp <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/14709">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  George Joseph: 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 ffb6dbc..acf476e 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>@@ -600,7 +601,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>@@ -610,25 +610,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>@@ -636,19 +636,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 be1eb39..1142bbd 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>@@ -1950,15 +1950,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>@@ -1970,7 +1962,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/+/14709">change 14709</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/+/14709"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I31d4351d70c8e2c11564807a7528b984f3fbdd01 </div>
<div style="display:none"> Gerrit-Change-Number: 14709 </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-MessageType: merged </div>