summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2017-11-13 13:14:23 +0000
committerJoshua Colp <jcolp@digium.com>2017-11-14 11:53:07 -0500
commit29e0add14f8db9ea28a7fbb32c2efec8c9738196 (patch)
tree461927c17793f96b09ef923f1f362881f079f987
parenta6d2926e5dc1c8216ee207c1f11460587a6abe93 (diff)
pjsip / hep: Provide correct local address for Websockets.
Previously for PJSIP the local address of WebSocket connections was set to the remote address. For logging purposes this is not particularly useful. The WebSocket API has been extended to allow the local address to be queried and this is used in PJSIP to set the local address to the correct value. The PJSIP HEP support has also been tweaked so that reliable transports always use the local address on the transport and do not try to (wrongly) guess. As they are connection based it is impossible for the source to be anything else. ASTERISK-26758 ASTERISK-27363 Change-Id: Icd305fd038ad755e2682ab2786e381f6bf29e8ca
-rw-r--r--include/asterisk/http_websocket.h9
-rw-r--r--res/res_hep_pjsip.c90
-rw-r--r--res/res_http_websocket.c50
-rw-r--r--res/res_pjsip_transport_websocket.c12
4 files changed, 98 insertions, 63 deletions
diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h
index cd49dbe48..2180ef46b 100644
--- a/include/asterisk/http_websocket.h
+++ b/include/asterisk/http_websocket.h
@@ -345,6 +345,15 @@ AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { errno
AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct ast_websocket *session), {return NULL;});
/*!
+ * \brief Get the local address for a WebSocket connection session.
+ *
+ * \retval ast_sockaddr Local address
+ *
+ * \since 13.19.0
+ */
+AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_local_address, (struct ast_websocket *session), {return NULL;});
+
+/*!
* \brief Get whether the WebSocket session is using a secure transport or not.
*
* \retval 0 if unsecure
diff --git a/res/res_hep_pjsip.c b/res/res_hep_pjsip.c
index 13efbfa6a..b5be4a102 100644
--- a/res/res_hep_pjsip.c
+++ b/res/res_hep_pjsip.c
@@ -89,35 +89,44 @@ static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
pjsip_cid_hdr *cid_hdr;
pjsip_from_hdr *from_hdr;
pjsip_to_hdr *to_hdr;
- pjsip_tpmgr_fla2_param prm;
capture_info = hepv3_create_capture_info(tdata->buf.start, (size_t)(tdata->buf.cur - tdata->buf.start));
if (!capture_info) {
return PJ_SUCCESS;
}
- /* Attempt to determine what IP address will we send this packet out of */
- pjsip_tpmgr_fla2_param_default(&prm);
- prm.tp_type = tdata->tp_info.transport->key.type;
- pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);
- prm.local_if = PJ_TRUE;
+ if (!(tdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
+ pjsip_tpmgr_fla2_param prm;
- /* If we can't get the local address use what we have already */
- if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
- pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
- } else {
- if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
- snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ /* Attempt to determine what IP address will we send this packet out of */
+ pjsip_tpmgr_fla2_param_default(&prm);
+ prm.tp_type = tdata->tp_info.transport->key.type;
+ pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);
+ prm.local_if = PJ_TRUE;
+
+ /* If we can't get the local address use what we have already */
+ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
+ pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
} else {
- snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
+ snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ } else {
+ snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ }
}
+ } else {
+ /* For reliable transports they can only ever come from the transport
+ * local address.
+ */
+ pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
}
+
pj_sockaddr_print(&tdata->tp_info.dst_addr, remote_buf, sizeof(remote_buf), 3);
cid_hdr = PJSIP_MSG_CID_HDR(tdata->msg);
@@ -150,7 +159,6 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
char remote_buf[256];
char *uuid;
struct hepv3_capture_info *capture_info;
- pjsip_tpmgr_fla2_param prm;
capture_info = hepv3_create_capture_info(&rdata->pkt_info.packet, rdata->pkt_info.len);
if (!capture_info) {
@@ -162,27 +170,33 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
}
pj_sockaddr_print(&rdata->pkt_info.src_addr, remote_buf, sizeof(remote_buf), 3);
- /* Attempt to determine what IP address we probably received this packet on */
- pjsip_tpmgr_fla2_param_default(&prm);
- prm.tp_type = rdata->tp_info.transport->key.type;
- pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);
- prm.local_if = PJ_TRUE;
+ if (!(rdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
+ pjsip_tpmgr_fla2_param prm;
- /* If we can't get the local address use what we have already */
- if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {
- pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
- } else {
- if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
- snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ /* Attempt to determine what IP address we probably received this packet on */
+ pjsip_tpmgr_fla2_param_default(&prm);
+ prm.tp_type = rdata->tp_info.transport->key.type;
+ pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);
+ prm.local_if = PJ_TRUE;
+
+ /* If we can't get the local address use what we have already */
+ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {
+ pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
} else {
- snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
+ snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ } else {
+ snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ }
}
+ } else {
+ pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
}
uuid = assign_uuid(&rdata->msg_info.cid->id, &rdata->msg_info.to->tag, &rdata->msg_info.from->tag);
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index 8e9aae9dd..c1f9a29d6 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -86,18 +86,19 @@
/*! \brief Structure definition for session */
struct ast_websocket {
- struct ast_iostream *stream; /*!< iostream of the connection */
- struct ast_sockaddr address; /*!< Address of the remote client */
- enum ast_websocket_opcode opcode; /*!< Cached opcode for multi-frame messages */
- size_t payload_len; /*!< Length of the payload */
- char *payload; /*!< Pointer to the payload */
- size_t reconstruct; /*!< Number of bytes before a reconstructed payload will be returned and a new one started */
- int timeout; /*!< The timeout for operations on the socket */
- unsigned int secure:1; /*!< Bit to indicate that the transport is secure */
- unsigned int closing:1; /*!< Bit to indicate that the session is in the process of being closed */
- unsigned int close_sent:1; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
- 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 */
+ struct ast_iostream *stream; /*!< iostream of the connection */
+ struct ast_sockaddr remote_address; /*!< Address of the remote client */
+ struct ast_sockaddr local_address; /*!< Our local address */
+ enum ast_websocket_opcode opcode; /*!< Cached opcode for multi-frame messages */
+ size_t payload_len; /*!< Length of the payload */
+ char *payload; /*!< Pointer to the payload */
+ size_t reconstruct; /*!< Number of bytes before a reconstructed payload will be returned and a new one started */
+ int timeout; /*!< The timeout for operations on the socket */
+ unsigned int secure:1; /*!< Bit to indicate that the transport is secure */
+ unsigned int closing:1; /*!< Bit to indicate that the session is in the process of being closed */
+ unsigned int close_sent:1; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
+ 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 */
};
/*! \brief Hashing function for protocols */
@@ -183,7 +184,7 @@ static void session_destroy_fn(void *obj)
ast_iostream_close(session->stream);
session->stream = NULL;
ast_verb(2, "WebSocket connection %s '%s' closed\n", session->client ? "to" : "from",
- ast_sockaddr_stringify(&session->address));
+ ast_sockaddr_stringify(&session->remote_address));
}
}
@@ -318,7 +319,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_close)(struct ast_websocket *session, ui
ast_iostream_close(session->stream);
session->stream = NULL;
ast_verb(2, "WebSocket connection %s '%s' forcefully closed due to fatal write error\n",
- session->client ? "to" : "from", ast_sockaddr_stringify(&session->address));
+ session->client ? "to" : "from", ast_sockaddr_stringify(&session->remote_address));
}
ao2_unlock(session);
@@ -432,7 +433,12 @@ int AST_OPTIONAL_API_NAME(ast_websocket_fd)(struct ast_websocket *session)
struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_remote_address)(struct ast_websocket *session)
{
- return &session->address;
+ return &session->remote_address;
+}
+
+struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_local_address)(struct ast_websocket *session)
+{
+ return &session->local_address;
}
int AST_OPTIONAL_API_NAME(ast_websocket_is_secure)(struct ast_websocket *session)
@@ -899,11 +905,21 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
return 0;
}
+ /* Get our local address for the connected socket */
+ if (ast_getsockname(ast_iostream_get_fd(ser->stream), &session->local_address)) {
+ ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - failed to get local address\n",
+ ast_sockaddr_stringify(&ser->remote_address));
+ websocket_bad_request(ser);
+ ao2_ref(session, -1);
+ ao2_ref(protocol_handler, -1);
+ return 0;
+ }
+
ast_verb(2, "WebSocket connection from '%s' for protocol '%s' accepted using version '%d'\n", ast_sockaddr_stringify(&ser->remote_address), protocol ? : "", version);
/* Populate the session with all the needed details */
session->stream = ser->stream;
- ast_sockaddr_copy(&session->address, &ser->remote_address);
+ ast_sockaddr_copy(&session->remote_address, &ser->remote_address);
session->opcode = -1;
session->reconstruct = DEFAULT_RECONSTRUCTION_CEILING;
session->secure = ast_iostream_get_ssl(ser->stream) ? 1 : 0;
@@ -1357,7 +1373,7 @@ static enum ast_websocket_result websocket_client_connect(struct ast_websocket *
ws->stream = ws->client->ser->stream;
ws->secure = ast_iostream_get_ssl(ws->stream) ? 1 : 0;
ws->client->ser->stream = NULL;
- ast_sockaddr_copy(&ws->address, &ws->client->ser->remote_address);
+ ast_sockaddr_copy(&ws->remote_address, &ws->client->ser->remote_address);
return WS_OK;
}
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index 22ec19540..b5b6a3e0a 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -206,20 +206,16 @@ static int transport_create(void *data)
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);
if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) {
newtransport->transport.key.type = transport_type_wss_ipv6;
- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN);
- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0);
} else {
newtransport->transport.key.type = transport_type_wss;
- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN);
- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0);
}
newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);
- pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);
-
- newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
- newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);
+ ws_addr_str = ast_sockaddr_stringify(ast_websocket_local_address(newtransport->ws_session));
+ pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.local_addr);
+ pj_strdup2(pool, &newtransport->transport.local_name.host, ast_sockaddr_stringify_host(ast_websocket_local_address(newtransport->ws_session)));
+ newtransport->transport.local_name.port = ast_sockaddr_port(ast_websocket_local_address(newtransport->ws_session));
newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);
newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);