[asterisk-commits] qwell: branch qwell/fun_with_transports r385268 - in /team/qwell/fun_with_tra...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Apr 10 16:23:53 CDT 2013
Author: qwell
Date: Wed Apr 10 16:23:52 2013
New Revision: 385268
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=385268
Log:
Change how transport selection is done.
Modified:
team/qwell/fun_with_transports/include/asterisk/res_sip.h
team/qwell/fun_with_transports/res/res_sip.c
team/qwell/fun_with_transports/res/res_sip.exports.in
team/qwell/fun_with_transports/res/res_sip/location.c
team/qwell/fun_with_transports/res/res_sip_registrar.c
team/qwell/fun_with_transports/res/res_sip_session.c
team/qwell/fun_with_transports/res/res_sip_transport_websocket.c
Modified: team/qwell/fun_with_transports/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/include/asterisk/res_sip.h?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/include/asterisk/res_sip.h (original)
+++ team/qwell/fun_with_transports/include/asterisk/res_sip.h Wed Apr 10 16:23:52 2013
@@ -148,8 +148,18 @@
);
/*! Absolute time that this contact is no longer valid after */
struct timeval expiration_time;
- /*! Transport to use for all messages (some transport types require this) */
- pjsip_transport *transport;
+};
+
+/*!
+ * \brief A transport to be used for messages to a contact
+ */
+struct ast_sip_contact_transport {
+ SORCERY_OBJECT(details);
+ AST_DECLARE_STRING_FIELDS(
+ /*! Full URI of the contact */
+ AST_STRING_FIELD(uri);
+ );
+ pjsip_transport *transport;
};
/*!
@@ -572,16 +582,6 @@
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor);
/*!
- * \brief Retrieve a contact for an AOR
- *
- * \param aor Pointer to the AOR
- * \param contact_uri A URI to search for on the AOR
- * \retval NULL if contact not found
- * \retval non-NULL if contact found
- */
-struct ast_sip_contact *ast_sip_location_retrieve_aor_contact(const struct ast_sip_aor *aor, const char *contact_uri);
-
-/*!
* \brief Retrieve all contacts currently available for an AOR
*
* \param aor Pointer to the AOR
@@ -595,11 +595,10 @@
* \brief Retrieve a bound contact from a list of AORs
*
* \param aor_list A comma-separated list of AOR names
- * \param contact_uri Optional contact URI to search for
* \retval NULL if no contacts available
* \retval non-NULL if contacts available
*/
-struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list, const char *contact_uri);
+struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list);
/*!
* \brief Retrieve a named contact
@@ -610,6 +609,26 @@
* \retval non-NULL if found
*/
struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_name);
+
+/*!
+ * \brief Retrieve a contact_transport, by URI
+ *
+ * \param contact_uri URI of the contact
+ *
+ * \retval NULL if not found
+ * \retval non-NULL if found
+ */
+struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_uri(const char *contact_uri);
+
+/*!
+ * \brief Retrieve a contact_transport, by transport
+ *
+ * \param transport transport the contact uses
+ *
+ * \retval NULL if not found
+ * \retval non-NULL if found
+ */
+struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_transport(pjsip_transport *transport);
/*!
* \brief Add a new contact to an AOR
@@ -621,7 +640,7 @@
* \retval -1 failure
* \retval 0 success
*/
-int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, pjsip_transport *transport);
+int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time);
/*!
* \brief Update a contact
Modified: team/qwell/fun_with_transports/res/res_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/res/res_sip.c?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/res/res_sip.c (original)
+++ team/qwell/fun_with_transports/res/res_sip.c Wed Apr 10 16:23:52 2013
@@ -328,6 +328,22 @@
return 0;
}
+static int sip_get_tpselector_from_uri(const char *uri, pjsip_tpselector *selector)
+{
+ RAII_VAR(struct ast_sip_contact_transport *, contact_transport, NULL, ao2_cleanup);
+
+ contact_transport = ast_sip_location_retrieve_contact_transport_by_uri(uri);
+
+ if (!contact_transport) {
+ return -1;
+ }
+
+ selector->type = PJSIP_TPSELECTOR_TRANSPORT;
+ selector->u.transport = contact_transport->transport;
+
+ return 0;
+}
+
pjsip_dialog *ast_sip_create_dialog(const struct ast_sip_endpoint *endpoint, const char *uri, const char *request_user, pjsip_transport *request_transport)
{
pj_str_t local_uri = { "sip:temp at temp", 13 }, remote_uri;
@@ -342,10 +358,7 @@
return NULL;
}
- if (request_transport) {
- /* Force a transport, if we're provided one. */
- selector.type = PJSIP_TPSELECTOR_TRANSPORT;
- selector.u.transport = request_transport;
+ if (!sip_get_tpselector_from_uri(uri, &selector)) {
} else if (sip_get_tpselector_from_endpoint(endpoint, &selector)) {
pjsip_dlg_terminate(dlg);
return NULL;
@@ -444,7 +457,7 @@
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
if (ast_strlen_zero(uri)) {
- contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors, NULL);
+ contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
if (!contact || ast_strlen_zero(contact->uri)) {
ast_log(LOG_ERROR, "Unable to retrieve contact for endpoint %s\n",
ast_sorcery_object_get_id(endpoint));
Modified: team/qwell/fun_with_transports/res/res_sip.exports.in
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/res/res_sip.exports.in?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/res/res_sip.exports.in (original)
+++ team/qwell/fun_with_transports/res/res_sip.exports.in Wed Apr 10 16:23:52 2013
@@ -36,6 +36,8 @@
LINKER_SYMBOL_PREFIXast_sip_location_retrieve_contact_from_aor_list;
LINKER_SYMBOL_PREFIXast_sip_location_retrieve_aor_contacts;
LINKER_SYMBOL_PREFIXast_sip_location_retrieve_contact;
+ LINKER_SYMBOL_PREFIXast_sip_location_retrieve_contact_transport_by_uri;
+ LINKER_SYMBOL_PREFIXast_sip_location_retrieve_contact_transport_by_transport;
LINKER_SYMBOL_PREFIXast_sip_location_add_contact;
LINKER_SYMBOL_PREFIXast_sip_location_update_contact;
LINKER_SYMBOL_PREFIXast_sip_location_delete_contact;
Modified: team/qwell/fun_with_transports/res/res_sip/location.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/res/res_sip/location.c?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/res/res_sip/location.c (original)
+++ team/qwell/fun_with_transports/res/res_sip/location.c Wed Apr 10 16:23:52 2013
@@ -64,6 +64,74 @@
return contact;
}
+/*! \brief Destructor for contact_transport */
+static void contact_transport_destroy(void *obj)
+{
+ struct ast_sip_contact_transport *ct = obj;
+
+ ast_string_field_free_memory(ct);
+}
+
+static void *contact_transport_alloc(const char *name)
+{
+ struct ast_sip_contact_transport *ct = ao2_alloc_options(sizeof(*ct), contact_transport_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+
+ if (!ct) {
+ return NULL;
+ }
+
+ if (ast_string_field_init(ct, 256)) {
+ ao2_cleanup(ct);
+ return NULL;
+ }
+
+ return ct;
+}
+
+/*! \brief Callback function for finding a contact_transport by URI */
+static int contact_transport_find_by_uri(void *obj, void *arg, int flags)
+{
+ struct ast_sip_contact_transport *ct = obj;
+ const char *contact_uri = arg;
+
+ return (!strcmp(ct->uri, contact_uri)) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+/*! \brief Callback function for finding a contact_transport by transport */
+static int contact_transport_find_by_transport(void *obj, void *arg, int flags)
+{
+ struct ast_sip_contact_transport *ct = obj;
+ pjsip_transport *transport = arg;
+
+ return (ct->transport == transport) ? CMP_MATCH | CMP_STOP : 0;
+}
+
+struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_uri(const char *contact_uri)
+{
+ RAII_VAR(struct ao2_container *, cts, NULL, ao2_cleanup);
+ struct ast_sip_contact_transport *ct;
+
+ if (!(cts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact_transport", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL)) ||
+ !(ct = ao2_callback(cts, 0, contact_transport_find_by_uri, (void *)contact_uri))) {
+ return NULL;
+ }
+
+ return ct;
+}
+
+struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_transport(pjsip_transport *transport)
+{
+ RAII_VAR(struct ao2_container *, cts, NULL, ao2_cleanup);
+ struct ast_sip_contact_transport *ct;
+
+ if (!(cts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact_transport", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL)) ||
+ !(ct = ao2_callback(cts, 0, contact_transport_find_by_transport, transport))) {
+ return NULL;
+ }
+
+ return ct;
+}
+
struct ast_sip_aor *ast_sip_location_retrieve_aor(const char *aor_name)
{
return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
@@ -113,31 +181,6 @@
return contact;
}
-static int contact_find_by_uri(void *obj, void *args, int flags)
-{
- struct ast_sip_contact *contact = obj;
- const char *uri = args;
-
- if (!strcmp(contact->uri, uri)) {
- return CMP_MATCH | CMP_STOP;
- }
- return 0;
-}
-
-struct ast_sip_contact *ast_sip_location_retrieve_aor_contact(const struct ast_sip_aor *aor, const char *contact_uri)
-{
- RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
- struct ast_sip_contact *contact;
-
- contacts = ast_sip_location_retrieve_aor_contacts(aor);
- if (!contacts || (ao2_container_count(contacts) == 0)) {
- return NULL;
- }
-
- contact = ao2_callback(contacts, OBJ_NOLOCK, contact_find_by_uri, (void *)contact_uri);
- return contact;
-}
-
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
{
/* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
@@ -161,7 +204,7 @@
return contacts;
}
-struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list, const char *contact_uri)
+struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
{
char *aor_name;
char *rest;
@@ -180,11 +223,7 @@
if (!aor) {
continue;
}
- if (!ast_strlen_zero(contact_uri)) {
- contact = ast_sip_location_retrieve_aor_contact(aor, contact_uri);
- } else {
- contact = ast_sip_location_retrieve_first_aor_contact(aor);
- }
+ contact = ast_sip_location_retrieve_first_aor_contact(aor);
/* If a valid contact is available use its URI for dialing */
if (contact) {
break;
@@ -199,7 +238,7 @@
return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "contact", contact_name);
}
-int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, pjsip_transport *transport)
+int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time)
{
char name[AST_UUID_STR_LEN];
RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
@@ -212,7 +251,6 @@
ast_string_field_set(contact, uri, uri);
contact->expiration_time = expiration_time;
- contact->transport = transport;
return ast_sorcery_create(ast_sip_get_sorcery(), contact);
}
@@ -263,9 +301,11 @@
{
ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
ast_sorcery_apply_default(sorcery, "aor", "config", "res_sip.conf,criteria=type=aor");
+ ast_sorcery_apply_default(sorcery, "contact_transport", "memory", NULL);
if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, NULL) ||
- ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, NULL)) {
+ ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, NULL) ||
+ ast_sorcery_object_register(sorcery, "contact_transport", contact_transport_alloc, NULL, NULL)) {
return -1;
}
@@ -281,5 +321,7 @@
ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, NULL, 0, 0);
+ ast_sorcery_object_field_register(sorcery, "contact_transport", "uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact_transport, uri));
+
return 0;
}
Modified: team/qwell/fun_with_transports/res/res_sip_registrar.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/res/res_sip_registrar.c?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/res/res_sip_registrar.c (original)
+++ team/qwell/fun_with_transports/res/res_sip_registrar.c Wed Apr 10 16:23:52 2013
@@ -190,7 +190,6 @@
struct registrar_contact_details details = { 0, };
pjsip_tx_data *tdata;
pjsip_response_addr addr;
- pjsip_transport *transport = NULL;
if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) || !endpoint) {
return PJ_FALSE;
@@ -205,10 +204,6 @@
if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 416, NULL, NULL, NULL);
return PJ_TRUE;
- }
-
- if (!strcasecmp(rdata->tp_info.transport->type_name, "WS") || !strcasecmp(rdata->tp_info.transport->type_name, "WSS")) {
- transport = rdata->tp_info.transport;
}
uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
@@ -303,14 +298,13 @@
continue;
}
- ast_sip_location_add_contact(aor, contact_uri, ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1)), transport);
+ ast_sip_location_add_contact(aor, contact_uri, ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1)));
ast_verb(3, "Added contact '%s' to AOR '%s' with expiration of %d seconds\n",
contact_uri, aor_name, expiration);
} else if (expiration) {
RAII_VAR(struct ast_sip_contact *, updated, ast_sorcery_copy(ast_sip_get_sorcery(), contact), ao2_cleanup);
updated->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
- updated->transport = transport;
ast_sip_location_update_contact(updated);
ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
Modified: team/qwell/fun_with_transports/res/res_sip_session.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/res/res_sip_session.c?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/res/res_sip_session.c (original)
+++ team/qwell/fun_with_transports/res/res_sip_session.c Wed Apr 10 16:23:52 2013
@@ -976,26 +976,11 @@
/* If no location has been provided use the AOR list from the endpoint itself */
location = S_OR(location, endpoint->aors);
- contact = ast_sip_location_retrieve_contact_from_aor_list(location, NULL);
- if (contact && !ast_strlen_zero(contact->uri)) {
+ contact = ast_sip_location_retrieve_contact_from_aor_list(location);
+ if (!contact || ast_strlen_zero(contact->uri)) {
+ uri = location;
+ } else {
uri = contact->uri;
- request_transport = contact->transport;
- } else {
- char *contact_uri;
- char *rest = ast_strdupa(location);
-
- while ((contact_uri = strsep(&rest, ","))) {
- if ((contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors, contact_uri))) {
- uri = contact->uri;
- request_transport = contact->transport;
- break;
- }
- }
-
- /* If no URI was found using the provided AORs and contacts then use the location as provided as a last resort */
- if (ast_strlen_zero(uri)) {
- uri = location;
- }
}
/* If we still have no URI to dial fail to create the session */
Modified: team/qwell/fun_with_transports/res/res_sip_transport_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/qwell/fun_with_transports/res/res_sip_transport_websocket.c?view=diff&rev=385268&r1=385267&r2=385268
==============================================================================
--- team/qwell/fun_with_transports/res/res_sip_transport_websocket.c (original)
+++ team/qwell/fun_with_transports/res/res_sip_transport_websocket.c Wed Apr 10 16:23:52 2013
@@ -41,17 +41,6 @@
struct ast_websocket *ws_session;
};
-struct ws_create_data {
- struct ws_transport *transport;
- struct ast_websocket *ws_session;
-};
-
-struct ws_read_data {
- struct ws_transport *transport;
- char *payload;
- uint64_t payload_len;
-};
-
static pj_status_t ws_send_msg(pjsip_transport *transport,
pjsip_tx_data *tdata,
const pj_sockaddr_t *rem_addr,
@@ -90,14 +79,25 @@
static int transport_shutdown(void *data)
{
+ RAII_VAR(struct ast_sip_contact_transport *, ct, NULL, ao2_cleanup);
pjsip_transport *transport = data;
+
+ if ((ct = ast_sip_location_retrieve_contact_transport_by_transport(transport))) {
+ ast_sorcery_delete(ast_sip_get_sorcery(), ct);
+ }
+
pjsip_transport_shutdown(transport);
return 0;
}
+struct transport_create_data {
+ struct ws_transport *transport;
+ struct ast_websocket *ws_session;
+};
+
static int transport_create(void *data)
{
- struct ws_create_data *create_data = data;
+ struct transport_create_data *create_data = data;
struct ws_transport *newtransport;
pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
@@ -115,13 +115,16 @@
pj_lock_create_recursive_mutex(pool, pool->obj_name, &newtransport->transport.lock);
newtransport->transport.pool = pool;
- newtransport->transport.addr_len = sizeof(pj_sockaddr_in);
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(newtransport->ws_session))), &newtransport->transport.key.rem_addr);
newtransport->transport.key.rem_addr.addr.sa_family = pj_AF_INET();
newtransport->transport.key.type = ast_websocket_is_secure(newtransport->ws_session) ? transport_type_wss : transport_type_ws;
+ 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.ptr = (char *)pj_pool_alloc(pool, newtransport->transport.addr_len+4);
- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN+4, 0);
+ pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, newtransport->transport.addr_len+4, 0);
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);
@@ -141,9 +144,15 @@
return 0;
}
+struct transport_read_data {
+ struct ws_transport *transport;
+ char *payload;
+ uint64_t payload_len;
+};
+
static int transport_read(void *data)
{
- struct ws_read_data *read_data = data;
+ struct transport_read_data *read_data = data;
struct ws_transport *newtransport = read_data->transport;
struct ast_websocket *session = newtransport->ws_session;
@@ -188,7 +197,7 @@
serializer = ast_sip_create_serializer();
while (ast_wait_for_input(ast_websocket_fd(session), -1) > 0) {
- struct ws_read_data read_data;
+ struct transport_read_data read_data;
enum ast_websocket_opcode opcode;
int fragmented;
@@ -198,7 +207,7 @@
if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) {
if (!transport) {
- struct ws_create_data create_data;
+ struct transport_create_data create_data;
create_data.ws_session = session;
ast_sip_push_task_synchronous(serializer, transport_create, &create_data);
@@ -222,52 +231,107 @@
ast_websocket_unref(session);
}
+#if 0
+/* XXX Probably not needed. */
static int websocket_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
{
int type = rdata->tp_info.transport->key.type;
- if (type == transport_type_ws || type == transport_type_wss) {
- /* This is one of our transports. We need to force it to use us on the dialog. */
+
+ if (type != transport_type_ws && type != transport_type_wss) {
+ return 0;
+ }
+
+ /* This is one of our transports. We need to force it to use us on the dialog. */
+ pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_TRANSPORT, };
+
+ selector.u.transport = rdata->tp_info.transport;
+
+ pjsip_dlg_set_transport(session->inv_session->dlg, &selector);
+
+ return 0;
+}
+#endif
+
+static void websocket_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+{
+ char contact_uri[PJSIP_MAX_URL_SIZE] = { 0, };
+ RAII_VAR(struct ast_sip_contact_transport *, ct, NULL, ao2_cleanup);
+
+ pjsip_uri_print(PJSIP_URI_IN_REQ_URI, tdata->msg->line.req.uri, contact_uri, sizeof(contact_uri));
+
+ if ((ct = ast_sip_location_retrieve_contact_transport_by_uri(contact_uri))) {
pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_TRANSPORT, };
- selector.u.transport = rdata->tp_info.transport;
-
- pjsip_dlg_set_transport(session->inv_session->dlg, &selector);
- }
- return 0;
-}
-
-static void websocket_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
-{
- struct pjsip_transport *transport = (struct pjsip_transport*)session->inv_session->dlg->tp_sel.u.transport;
-
- if (transport->key.type == transport_type_ws || transport->key.type == transport_type_wss) {
- /* Avoid DNS resolution, so it doesn't try to resolve a bogus address. */
+ selector.u.transport = ct->transport;
+
+ pjsip_tx_data_set_transport(tdata, &selector);
+
tdata->dest_info.addr.count = 1;
- tdata->dest_info.addr.entry[0].type = transport->key.type;
- tdata->dest_info.addr.entry[0].addr = transport->key.rem_addr;
- tdata->dest_info.addr.entry[0].addr_len = transport->addr_len;
+ tdata->dest_info.addr.entry[0].type = ct->transport->key.type;
+ tdata->dest_info.addr.entry[0].addr = ct->transport->key.rem_addr;
+ tdata->dest_info.addr.entry[0].addr_len = ct->transport->addr_len;
}
}
static struct ast_sip_session_supplement websocket_supplement = {
- .incoming_request = websocket_incoming_request,
.outgoing_request = websocket_outgoing_request,
};
+static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
+{
+ pjsip_contact_hdr *contact_hdr = NULL;
+
+ int type = rdata->tp_info.transport->key.type;
+
+ if (type != transport_type_ws && type != transport_type_wss) {
+ return 0;
+ }
+
+ if ((contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL))) {
+ RAII_VAR(struct ast_sip_contact_transport *, ct, NULL, ao2_cleanup);
+ char contact_uri[PJSIP_MAX_URL_SIZE];
+
+ pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, pjsip_uri_get_uri(contact_hdr->uri), contact_uri, sizeof(contact_uri));
+
+ if ((ct = ast_sip_location_retrieve_contact_transport_by_uri(contact_uri))) {
+ RAII_VAR(struct ast_sip_contact_transport *, ct_copy, ast_sorcery_copy(ast_sip_get_sorcery(), ct), ao2_cleanup);
+ ct_copy->transport = rdata->tp_info.transport;
+ ast_sorcery_update(ast_sip_get_sorcery(), ct_copy);
+ } else {
+ ct = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact_transport", NULL);
+ ast_string_field_set(ct, uri, contact_uri);
+ ct->transport = rdata->tp_info.transport;
+ ast_sorcery_create(ast_sip_get_sorcery(), ct);
+ }
+ }
+
+ return 0;
+}
+
+static pjsip_module websocket_module = {
+ .name = { "WebSocket Transport Module", 26 },
+ .priority = 0,
+ .on_rx_request = websocket_on_rx_msg,
+};
+
static int load_module(void)
{
- ast_websocket_add_protocol("sip", websocket_cb);
-
pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE, "WS", 5060, &transport_type_ws);
pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE, "WSS", 5060, &transport_type_wss);
ast_sip_session_register_supplement(&websocket_supplement);
+ ast_sip_register_service(&websocket_module);
+
+ ast_websocket_add_protocol("sip", websocket_cb);
return AST_MODULE_LOAD_SUCCESS;
}
static int unload_module(void)
{
+ ast_sip_unregister_service(&websocket_module);
+ ast_websocket_remove_protocol("sip", websocket_cb);
+
return 0;
}
More information about the asterisk-commits
mailing list