<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/7223">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, approved
Jenkins2: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">pjsip / hep: Provide correct local address for Websockets.<br><br>Previously for PJSIP the local address of WebSocket connections<br>was set to the remote address. For logging purposes this is<br>not particularly useful.<br><br>The WebSocket API has been extended to allow the local<br>address to be queried and this is used in PJSIP to set the<br>local address to the correct value.<br><br>The PJSIP HEP support has also been tweaked so that reliable<br>transports always use the local address on the transport<br>and do not try to (wrongly) guess. As they are connection<br>based it is impossible for the source to be anything else.<br><br>ASTERISK-26758<br>ASTERISK-27363<br><br>Change-Id: Icd305fd038ad755e2682ab2786e381f6bf29e8ca<br>---<br>M include/asterisk/http_websocket.h<br>M res/res_hep_pjsip.c<br>M res/res_http_websocket.c<br>M res/res_pjsip_transport_websocket.c<br>4 files changed, 98 insertions(+), 63 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h<br>index d8e7d06..83d5d4f 100644<br>--- a/include/asterisk/http_websocket.h<br>+++ b/include/asterisk/http_websocket.h<br>@@ -344,6 +344,15 @@<br> AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct ast_websocket *session), {return NULL;});<br> <br> /*!<br>+ * \brief Get the local address for a WebSocket connection session.<br>+ *<br>+ * \retval ast_sockaddr Local address<br>+ *<br>+ * \since 13.19.0<br>+ */<br>+AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_local_address, (struct ast_websocket *session), {return NULL;});<br>+<br>+/*!<br> * \brief Get whether the WebSocket session is using a secure transport or not.<br> *<br> * \retval 0 if unsecure<br>diff --git a/res/res_hep_pjsip.c b/res/res_hep_pjsip.c<br>index 1614b43..1d99fcc 100644<br>--- a/res/res_hep_pjsip.c<br>+++ b/res/res_hep_pjsip.c<br>@@ -91,35 +91,44 @@<br> pjsip_cid_hdr *cid_hdr;<br> pjsip_from_hdr *from_hdr;<br> pjsip_to_hdr *to_hdr;<br>- pjsip_tpmgr_fla2_param prm;<br> <br> capture_info = hepv3_create_capture_info(tdata->buf.start, (size_t)(tdata->buf.cur - tdata->buf.start));<br> if (!capture_info) {<br> return PJ_SUCCESS;<br> }<br> <br>- /* Attempt to determine what IP address will we send this packet out of */<br>- pjsip_tpmgr_fla2_param_default(&prm);<br>- prm.tp_type = tdata->tp_info.transport->key.type;<br>- pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);<br>- prm.local_if = PJ_TRUE;<br>+ if (!(tdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {<br>+ pjsip_tpmgr_fla2_param prm;<br> <br>- /* If we can't get the local address use what we have already */<br>- if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {<br>- pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);<br>- } else {<br>- if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {<br>- snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",<br>- (int)pj_strlen(&prm.ret_addr),<br>- pj_strbuf(&prm.ret_addr),<br>- prm.ret_port);<br>+ /* Attempt to determine what IP address will we send this packet out of */<br>+ pjsip_tpmgr_fla2_param_default(&prm);<br>+ prm.tp_type = tdata->tp_info.transport->key.type;<br>+ pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);<br>+ prm.local_if = PJ_TRUE;<br>+<br>+ /* If we can't get the local address use what we have already */<br>+ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {<br>+ pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);<br> } else {<br>- snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",<br>- (int)pj_strlen(&prm.ret_addr),<br>- pj_strbuf(&prm.ret_addr),<br>- prm.ret_port);<br>+ if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {<br>+ snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",<br>+ (int)pj_strlen(&prm.ret_addr),<br>+ pj_strbuf(&prm.ret_addr),<br>+ prm.ret_port);<br>+ } else {<br>+ snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",<br>+ (int)pj_strlen(&prm.ret_addr),<br>+ pj_strbuf(&prm.ret_addr),<br>+ prm.ret_port);<br>+ }<br> }<br>+ } else {<br>+ /* For reliable transports they can only ever come from the transport<br>+ * local address.<br>+ */<br>+ pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);<br> }<br>+<br> pj_sockaddr_print(&tdata->tp_info.dst_addr, remote_buf, sizeof(remote_buf), 3);<br> <br> cid_hdr = PJSIP_MSG_CID_HDR(tdata->msg);<br>@@ -152,7 +161,6 @@<br> char remote_buf[256];<br> char *uuid;<br> struct hepv3_capture_info *capture_info;<br>- pjsip_tpmgr_fla2_param prm;<br> <br> capture_info = hepv3_create_capture_info(&rdata->pkt_info.packet, rdata->pkt_info.len);<br> if (!capture_info) {<br>@@ -164,27 +172,33 @@<br> }<br> pj_sockaddr_print(&rdata->pkt_info.src_addr, remote_buf, sizeof(remote_buf), 3);<br> <br>- /* Attempt to determine what IP address we probably received this packet on */<br>- pjsip_tpmgr_fla2_param_default(&prm);<br>- prm.tp_type = rdata->tp_info.transport->key.type;<br>- pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);<br>- prm.local_if = PJ_TRUE;<br>+ if (!(rdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {<br>+ pjsip_tpmgr_fla2_param prm;<br> <br>- /* If we can't get the local address use what we have already */<br>- if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {<br>- pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);<br>- } else {<br>- if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {<br>- snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",<br>- (int)pj_strlen(&prm.ret_addr),<br>- pj_strbuf(&prm.ret_addr),<br>- prm.ret_port);<br>+ /* Attempt to determine what IP address we probably received this packet on */<br>+ pjsip_tpmgr_fla2_param_default(&prm);<br>+ prm.tp_type = rdata->tp_info.transport->key.type;<br>+ pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);<br>+ prm.local_if = PJ_TRUE;<br>+<br>+ /* If we can't get the local address use what we have already */<br>+ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {<br>+ pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);<br> } else {<br>- snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",<br>- (int)pj_strlen(&prm.ret_addr),<br>- pj_strbuf(&prm.ret_addr),<br>- prm.ret_port);<br>+ if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {<br>+ snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",<br>+ (int)pj_strlen(&prm.ret_addr),<br>+ pj_strbuf(&prm.ret_addr),<br>+ prm.ret_port);<br>+ } else {<br>+ snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",<br>+ (int)pj_strlen(&prm.ret_addr),<br>+ pj_strbuf(&prm.ret_addr),<br>+ prm.ret_port);<br>+ }<br> }<br>+ } else {<br>+ pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);<br> }<br> <br> uuid = assign_uuid(&rdata->msg_info.cid->id, &rdata->msg_info.to->tag, &rdata->msg_info.from->tag);<br>diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c<br>index 2baccc0..75a6eba 100644<br>--- a/res/res_http_websocket.c<br>+++ b/res/res_http_websocket.c<br>@@ -87,18 +87,19 @@<br> <br> /*! \brief Structure definition for session */<br> struct ast_websocket {<br>- FILE *f; /*!< Pointer to the file instance used for writing and reading */<br>- int fd; /*!< File descriptor for the session, only used for polling */<br>- struct ast_sockaddr address; /*!< Address of the remote client */<br>- enum ast_websocket_opcode opcode; /*!< Cached opcode for multi-frame messages */<br>- size_t payload_len; /*!< Length of the payload */<br>- char *payload; /*!< Pointer to the payload */<br>- size_t reconstruct; /*!< Number of bytes before a reconstructed payload will be returned and a new one started */<br>- int timeout; /*!< The timeout for operations on the socket */<br>- unsigned int secure:1; /*!< Bit to indicate that the transport is secure */<br>- unsigned int closing:1; /*!< Bit to indicate that the session is in the process of being closed */<br>- unsigned int close_sent:1; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */<br>- struct websocket_client *client; /*!< Client object when connected as a client websocket */<br>+ FILE *f; /*!< Pointer to the file instance used for writing and reading */<br>+ int fd; /*!< File descriptor for the session, only used for polling */<br>+ struct ast_sockaddr remote_address; /*!< Address of the remote client */<br>+ struct ast_sockaddr local_address; /*!< Our local address */<br>+ enum ast_websocket_opcode opcode; /*!< Cached opcode for multi-frame messages */<br>+ size_t payload_len; /*!< Length of the payload */<br>+ char *payload; /*!< Pointer to the payload */<br>+ size_t reconstruct; /*!< Number of bytes before a reconstructed payload will be returned and a new one started */<br>+ int timeout; /*!< The timeout for operations on the socket */<br>+ unsigned int secure:1; /*!< Bit to indicate that the transport is secure */<br>+ unsigned int closing:1; /*!< Bit to indicate that the session is in the process of being closed */<br>+ unsigned int close_sent:1; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */<br>+ struct websocket_client *client; /*!< Client object when connected as a client websocket */<br> };<br> <br> /*! \brief Hashing function for protocols */<br>@@ -183,7 +184,7 @@<br> if (session->f) {<br> fclose(session->f);<br> ast_verb(2, "WebSocket connection %s '%s' closed\n", session->client ? "to" : "from",<br>- ast_sockaddr_stringify(&session->address));<br>+ ast_sockaddr_stringify(&session->remote_address));<br> }<br> }<br> <br>@@ -316,7 +317,7 @@<br> fclose(session->f);<br> session->f = NULL;<br> ast_verb(2, "WebSocket connection %s '%s' forcefully closed due to fatal write error\n",<br>- session->client ? "to" : "from", ast_sockaddr_stringify(&session->address));<br>+ session->client ? "to" : "from", ast_sockaddr_stringify(&session->remote_address));<br> }<br> <br> ao2_unlock(session);<br>@@ -429,7 +430,12 @@<br> <br> struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_remote_address)(struct ast_websocket *session)<br> {<br>- return &session->address;<br>+ return &session->remote_address;<br>+}<br>+<br>+struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_local_address)(struct ast_websocket *session)<br>+{<br>+ return &session->local_address;<br> }<br> <br> int AST_OPTIONAL_API_NAME(ast_websocket_is_secure)(struct ast_websocket *session)<br>@@ -890,12 +896,22 @@<br> return 0;<br> }<br> <br>+ /* Get our local address for the connected socket */<br>+ if (ast_getsockname(ser->fd, &session->local_address)) {<br>+ ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - failed to get local address\n",<br>+ ast_sockaddr_stringify(&ser->remote_address));<br>+ websocket_bad_request(ser);<br>+ ao2_ref(session, -1);<br>+ ao2_ref(protocol_handler, -1);<br>+ return 0;<br>+ }<br>+<br> ast_verb(2, "WebSocket connection from '%s' for protocol '%s' accepted using version '%d'\n", ast_sockaddr_stringify(&ser->remote_address), protocol ? : "", version);<br> <br> /* Populate the session with all the needed details */<br> session->f = ser->f;<br> session->fd = ser->fd;<br>- ast_sockaddr_copy(&session->address, &ser->remote_address);<br>+ ast_sockaddr_copy(&session->remote_address, &ser->remote_address);<br> session->opcode = -1;<br> session->reconstruct = DEFAULT_RECONSTRUCTION_CEILING;<br> session->secure = ser->ssl ? 1 : 0;<br>@@ -1350,7 +1366,7 @@<br> ws->f = ws->client->ser->f;<br> ws->fd = ws->client->ser->fd;<br> ws->secure = ws->client->ser->ssl ? 1 : 0;<br>- ast_sockaddr_copy(&ws->address, &ws->client->ser->remote_address);<br>+ ast_sockaddr_copy(&ws->remote_address, &ws->client->ser->remote_address);<br> return WS_OK;<br> }<br> <br>diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c<br>index c04594f..b1f560c 100644<br>--- a/res/res_pjsip_transport_websocket.c<br>+++ b/res/res_pjsip_transport_websocket.c<br>@@ -206,20 +206,16 @@<br> pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);<br> if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) {<br> newtransport->transport.key.type = transport_type_wss_ipv6;<br>- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN);<br>- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0);<br> } else {<br> newtransport->transport.key.type = transport_type_wss;<br>- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN);<br>- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0);<br> }<br> <br> newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);<br> <br>- pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);<br>-<br>- newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);<br>- newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);<br>+ ws_addr_str = ast_sockaddr_stringify(ast_websocket_local_address(newtransport->ws_session));<br>+ pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.local_addr);<br>+ pj_strdup2(pool, &newtransport->transport.local_name.host, ast_sockaddr_stringify_host(ast_websocket_local_address(newtransport->ws_session)));<br>+ newtransport->transport.local_name.port = ast_sockaddr_port(ast_websocket_local_address(newtransport->ws_session));<br> <br> newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);<br> newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7223">change 7223</a>. To unsubscribe, 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/7223"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Icd305fd038ad755e2682ab2786e381f6bf29e8ca </div>
<div style="display:none"> Gerrit-Change-Number: 7223 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>