32 #include "asterisk/res_pjsip.h"
33 #include "asterisk/res_pjsip_session.h"
34 #include "asterisk/res_pjsip_session_caps.h"
39 #include "asterisk/res_pjsip.h"
49 #include "asterisk/features_config.h"
55 #include "res_pjsip_session/pjsip_session.h"
57 #define SDP_HANDLER_BUCKETS 11
59 #define MOD_DATA_ON_RESPONSE "on_response"
60 #define MOD_DATA_NAT_HOOK "nat_hook"
63 #define DEFAULT_NUM_SESSION_MEDIA 2
69 static void handle_incoming_request(
struct ast_sip_session *session, pjsip_rx_data *rdata);
70 static void handle_incoming_response(
struct ast_sip_session *session, pjsip_rx_data *rdata,
72 static int handle_incoming(
struct ast_sip_session *session, pjsip_rx_data *rdata,
74 static void handle_outgoing_request(
struct ast_sip_session *session, pjsip_tx_data *tdata);
75 static void handle_outgoing_response(
struct ast_sip_session *session, pjsip_tx_data *tdata);
77 ast_sip_session_request_creation_cb on_request_creation,
78 ast_sip_session_sdp_creation_cb on_sdp_creation,
79 ast_sip_session_response_cb on_response,
80 enum ast_sip_session_refresh_method
method,
int generate_new_sdp,
107 static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv,
struct ast_sip_session *session,
const pjmedia_sdp_session *offer,
const unsigned int ignore_active_stream_topology);
109 static int sdp_handler_list_hash(
const void *obj,
int flags)
112 const char *stream_type = flags &
OBJ_KEY ? obj : handler_list->stream_type;
117 const char *ast_sip_session_get_name(
const struct ast_sip_session *session)
120 return "(null session)";
123 return ast_channel_name(session->
channel);
133 return id->number.valid
138 static int sdp_handler_list_cmp(
void *obj,
void *arg,
int flags)
142 const char *stream_type2 = flags &
OBJ_KEY ? arg : handler_list2->stream_type;
144 return strcmp(handler_list1->stream_type, stream_type2) ? 0 :
CMP_MATCH |
CMP_STOP;
150 ao2_find(sdp_handlers, stream_type,
OBJ_KEY), ao2_cleanup);
157 if (!strcmp(iter->
id, handler->
id)) {
158 ast_log(LOG_WARNING,
"Handler '%s' already registered for stream type '%s'.\n", handler->
id, stream_type);
163 ast_debug(1,
"Registered SDP stream handler '%s' for stream type '%s'\n", handler->
id, stream_type);
169 handler_list = ao2_alloc(
sizeof(*handler_list) + strlen(stream_type), NULL);
174 strcpy(handler_list->stream_type, stream_type);
177 if (!
ao2_link(sdp_handlers, handler_list)) {
180 ast_debug(1,
"Registered SDP stream handler '%s' for stream type '%s'\n", handler->
id, stream_type);
185 static int remove_handler(
void *obj,
void *arg,
void *data,
int flags)
190 const char *stream_type = arg;
193 if (!strcmp(iter->
id, handler->
id)) {
195 ast_debug(1,
"Unregistered SDP stream handler '%s' for stream type '%s'\n", handler->
id, stream_type);
201 ast_debug(3,
"No more handlers exist for stream type '%s'\n", stream_type);
213 static int media_stats_local_ssrc_cmp(
228 media_state =
ast_calloc(1,
sizeof(*media_state));
234 ast_free(media_state);
240 ast_free(media_state);
249 return internal_sip_session_media_state_alloc(
250 DEFAULT_NUM_SESSION_MEDIA, DEFAULT_NUM_SESSION_MEDIA);
258 if (!media_state || !sip_session) {
265 if (!media || !media->
rtp) {
298 for (index = 0; index < AST_MEDIA_TYPE_END; ++index) {
315 cloned = internal_sip_session_media_state_alloc(
325 ast_sip_session_media_state_free(cloned);
336 ao2_cleanup(session_media);
360 ast_sip_session_media_state_reset(media_state);
365 ast_free(media_state);
373 ast_log(LOG_WARNING,
"Pending topology was NULL for channel '%s'\n",
374 session->
channel ? ast_channel_name(session->
channel) :
"unknown");
395 int fd, ast_sip_session_media_read_cb callback)
399 .read_callback = callback,
400 .session = session_media,
408 ast_sip_session_media_write_cb callback)
428 return session_media;
438 return bundle_group_session_media;
442 return session_media;
457 ast_assert(session_media->
handler != handler);
478 static void session_media_dtor(
void *obj)
489 if (session_media->
srtp) {
493 ast_free(session_media->
mid);
504 SCOPE_ENTER(1,
"%s Adding position %d\n", ast_sip_session_get_name(session), position);
511 if (current_session_media && current_session_media->
type == type) {
512 SCOPE_EXIT_RTN_VALUE(current_session_media,
"Using existing media_session\n");
520 if (session_media->
type == type) {
522 ast_trace(1,
"Reusing existing media session\n");
531 ast_free(session_media->
mid);
534 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't alloc mid\n");
538 ast_trace(1,
"Can't reuse existing media session because the types are different. %s <> %s\n",
540 session_media = NULL;
544 if (!session_media) {
547 if (!session_media) {
550 ast_trace(1,
"Creating new media session\n");
566 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't alloc mid\n");
586 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't replace media_session\n");
589 ao2_cleanup(current_session_media);
598 SCOPE_EXIT_RTN_VALUE(session_media,
"Done\n");
604 case AST_MEDIA_TYPE_AUDIO:
606 case AST_MEDIA_TYPE_VIDEO:
608 case AST_MEDIA_TYPE_IMAGE:
610 return (type_streams[type] > 0);
611 case AST_MEDIA_TYPE_UNKNOWN:
612 case AST_MEDIA_TYPE_TEXT:
621 static int get_mid_bundle_group(
const pjmedia_sdp_session *sdp,
const char *
mid)
626 for (index = 0; index < sdp->attr_count; ++index) {
627 pjmedia_sdp_attr *attr = sdp->attr[index];
628 char value[pj_strlen(&attr->value) + 1], *mids = value, *attr_mid;
630 if (pj_strcmp2(&attr->name,
"group") || pj_strncmp2(&attr->value,
"BUNDLE", 6)) {
634 ast_copy_pj_str(value, &attr->value,
sizeof(value));
639 while ((attr_mid = strsep(&mids,
" "))) {
640 if (!strcmp(attr_mid, mid)) {
657 const pjmedia_sdp_session *sdp,
658 const struct pjmedia_sdp_media *stream)
660 pjmedia_sdp_attr *attr;
667 ast_free(session_media->
mid);
668 session_media->
mid = NULL;
673 attr = pjmedia_sdp_media_find_attr2(stream,
"mid", NULL);
679 if (!session_media->
mid) {
682 ast_copy_pj_str(session_media->
mid, &attr->value, attr->value.slen + 1);
685 session_media->
bundle_group = get_mid_bundle_group(sdp, session_media->
mid);
693 static void set_remote_mslabel_and_stream_group(
struct ast_sip_session *session,
695 const pjmedia_sdp_session *sdp,
696 const struct pjmedia_sdp_media *stream,
706 for (index = 0; index < stream->attr_count; ++index) {
707 pjmedia_sdp_attr *attr = stream->attr[index];
708 char attr_value[pj_strlen(&attr->value) + 1];
709 char *ssrc_attribute_name, *ssrc_attribute_value = NULL;
710 char *msid, *tmp = attr_value;
711 static const pj_str_t STR_msid = {
"msid", 4 };
712 static const pj_str_t STR_ssrc = {
"ssrc", 4 };
713 static const pj_str_t STR_label = {
"label", 5 };
715 if (!pj_strcmp(&attr->name, &STR_label)) {
716 ast_copy_pj_str(attr_value, &attr->value,
sizeof(attr_value));
718 }
else if (!pj_strcmp(&attr->name, &STR_msid)) {
719 ast_copy_pj_str(attr_value, &attr->value,
sizeof(attr_value));
720 msid = strsep(&tmp,
" ");
723 }
else if (!pj_strcmp(&attr->name, &STR_ssrc)) {
724 ast_copy_pj_str(attr_value, &attr->value,
sizeof(attr_value));
726 if ((ssrc_attribute_name = strchr(attr_value,
' '))) {
728 *ssrc_attribute_name++ =
'\0';
729 ssrc_attribute_value = strchr(ssrc_attribute_name,
':');
730 if (ssrc_attribute_value) {
732 *ssrc_attribute_value++ =
'\0';
735 if (!strcasecmp(ssrc_attribute_name,
"mslabel") && !ast_strlen_zero(ssrc_attribute_value)) {
767 ast_free(session_media->
mid);
768 session_media->
mid = NULL;
773 static int handle_incoming_sdp(
struct ast_sip_session *session,
const pjmedia_sdp_session *sdp)
777 int type_streams[AST_MEDIA_TYPE_END] = {0};
778 SCOPE_ENTER(3,
"%s: Media count: %d\n", ast_sip_session_get_name(session), sdp->media_count);
781 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: Failed to handle incoming SDP. Session has been already disconnected\n",
782 ast_sip_session_get_name(session));
789 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"%s: Couldn't alloc pending topology\n",
790 ast_sip_session_get_name(session));
794 for (i = 0; i < sdp->media_count; ++i) {
803 pjmedia_sdp_media *remote_stream = sdp->media[i];
804 SCOPE_ENTER(4,
"%s: Processing stream %d\n", ast_sip_session_get_name(session), i);
807 ast_copy_pj_str(media, &sdp->media[i]->desc.media,
sizeof(media));
813 ast_trace(-1,
"%s: Using existing pending stream %s\n", ast_sip_session_get_name(session),
818 char *stream_name = NULL, *stream_name_allocated = NULL;
819 const char *stream_label = NULL;
824 ast_trace(-1,
"%s: Found existing active stream %s\n", ast_sip_session_get_name(session),
833 if (ast_strlen_zero(stream_name)) {
836 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't alloc stream name\n",
837 ast_sip_session_get_name(session));
840 stream_name = stream_name_allocated;
841 ast_trace(-1,
"%s: Using %s for new stream name\n", ast_sip_session_get_name(session),
846 ast_free(stream_name_allocated);
849 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't alloc stream\n",
850 ast_sip_session_get_name(session));
853 if (!ast_strlen_zero(stream_label)) {
855 ast_trace(-1,
"%s: Using %s for new stream label\n", ast_sip_session_get_name(session),
863 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't set stream in topology\n",
864 ast_sip_session_get_name(session));
868 if (!ast_sip_session_is_pending_stream_default(session, stream) || strcmp(media,
"audio")) {
869 if (pjmedia_sdp_media_find_attr2(remote_stream,
"sendonly", NULL)) {
875 }
else if (pjmedia_sdp_media_find_attr2(remote_stream,
"recvonly", NULL)) {
877 }
else if (pjmedia_sdp_media_find_attr2(remote_stream,
"inactive", NULL)) {
885 ast_trace(-1,
"%s: Using new stream %s\n", ast_sip_session_get_name(session),
890 if (!session_media) {
891 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't alloc session media\n",
892 ast_sip_session_get_name(session));
896 if (!remote_stream->desc.port || is_stream_limitation_reached(type, session->
endpoint, type_streams)) {
897 remove_stream_from_bundle(session_media, stream);
898 SCOPE_EXIT_EXPR(
continue,
"%s: Declining incoming SDP media stream %s'\n",
902 set_mid_and_bundle_group(session, session_media, sdp, remote_stream);
903 set_remote_mslabel_and_stream_group(session, session_media, sdp, remote_stream, stream);
906 handler = session_media->
handler;
907 ast_trace(-1,
"%s: Negotiating incoming SDP media stream %s using %s SDP handler\n",
913 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't negotiate stream %s\n",
915 }
else if (res == 0) {
916 remove_stream_from_bundle(session_media, stream);
917 SCOPE_EXIT_EXPR(
continue,
"%s: Declining incoming SDP media stream %s\n",
919 }
else if (res > 0) {
921 ++type_streams[
type];
923 SCOPE_EXIT_EXPR(
continue,
"%s: Media stream %s handled by %s\n",
929 handler_list = ao2_find(sdp_handlers, media,
OBJ_KEY);
931 SCOPE_EXIT_EXPR(
continue,
"%s: Media stream %s has no registered handlers\n",
935 if (handler == session_media->
handler) {
938 ast_trace(-1,
"%s: Negotiating incoming SDP media stream %s using %s SDP handler\n",
946 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't negotiate stream %s\n",
948 }
else if (res == 0) {
949 remove_stream_from_bundle(session_media, stream);
950 ast_trace(-1,
"%s: Declining incoming SDP media stream %s\n",
953 }
else if (res > 0) {
954 session_media_set_handler(session_media, handler);
956 ++type_streams[
type];
957 ast_trace(-1,
"%s: Media stream %s handled by %s\n",
964 SCOPE_EXIT(
"%s: Done with stream %s\n", ast_sip_session_get_name(session),
969 SCOPE_EXIT_RTN_VALUE(handled ? 0 : -1,
"%s: Handled? %s\n", ast_sip_session_get_name(session),
970 handled ?
"yes" :
"no");
975 const pjmedia_sdp_session *remote,
int index,
struct ast_stream *asterisk_stream)
978 struct pjmedia_sdp_media *local_stream = local->media[index];
983 SCOPE_ENTER(1,
"%s\n", session ? ast_sip_session_get_name(session) :
"unknown");
986 ast_copy_pj_str(media, &local->media[index]->desc.media,
sizeof(media));
994 if (!ast_sip_session_is_pending_stream_default(session, asterisk_stream) || strcmp(media,
"audio")) {
996 if (pjmedia_sdp_media_find_attr2(local_stream,
"sendonly", NULL)) {
998 }
else if (pjmedia_sdp_media_find_attr2(local_stream,
"recvonly", NULL)) {
1000 }
else if (pjmedia_sdp_media_find_attr2(local_stream,
"inactive", NULL)) {
1009 set_mid_and_bundle_group(session, session_media, remote, remote->media[index]);
1010 set_remote_mslabel_and_stream_group(session, session_media, remote, remote->media[index], asterisk_stream);
1012 handler = session_media->
handler;
1014 ast_debug(4,
"%s: Applying negotiated SDP media stream '%s' using %s SDP handler\n",
1019 ast_debug(4,
"%s: Applied negotiated SDP media stream '%s' using %s SDP handler\n",
1022 SCOPE_EXIT_RTN_VALUE(0,
"%s: Applied negotiated SDP media stream '%s' using %s SDP handler\n",
1026 SCOPE_EXIT_RTN_VALUE(-1,
"%s: Failed to apply negotiated SDP media stream '%s' using %s SDP handler\n",
1031 handler_list = ao2_find(sdp_handlers, media,
OBJ_KEY);
1032 if (!handler_list) {
1033 ast_debug(4,
"%s: No registered SDP handlers for media type '%s'\n", ast_sip_session_get_name(session), media);
1037 if (handler == session_media->
handler) {
1040 ast_debug(4,
"%s: Applying negotiated SDP media stream '%s' using %s SDP handler\n",
1046 SCOPE_EXIT_RTN_VALUE(-1,
"%s: Handler '%s' returned %d\n",
1047 ast_sip_session_get_name(session), handler->
id, res);
1050 ast_debug(4,
"%s: Applied negotiated SDP media stream '%s' using %s SDP handler\n",
1054 session_media_set_handler(session_media, handler);
1055 SCOPE_EXIT_RTN_VALUE(0,
"%s: Handler '%s' handled this sdp stream\n",
1056 ast_sip_session_get_name(session), handler->
id);
1062 ast_debug(4,
"%s: Stopping SDP media stream '%s' as it is not currently negotiated\n",
1067 SCOPE_EXIT_RTN_VALUE(0,
"%s: Media type '%s' %s\n",
1069 res ?
"not negotiated. Stopped" :
"handled");
1072 static int handle_negotiated_sdp(
struct ast_sip_session *session,
const pjmedia_sdp_session *local,
const pjmedia_sdp_session *remote)
1076 unsigned int changed = 0;
1077 SCOPE_ENTER(1,
"%s\n", ast_sip_session_get_name(session));
1088 active_media_state_clone =
1090 if (!active_media_state_clone) {
1091 ast_log(LOG_WARNING,
"%s: Unable to clone active media state\n",
1092 ast_sip_session_get_name(session));
1099 ast_log(LOG_WARNING,
"%s: No pending or active media state\n",
1100 ast_sip_session_get_name(session));
1112 ast_log(LOG_WARNING,
"%s: Local SDP contains %d media streams while we expected it to contain %u\n",
1113 ast_sip_session_get_name(session),
1115 SCOPE_EXIT_RTN_VALUE(-1,
"Media stream count mismatch\n");
1120 for (i = 0; i < local->media_count; ++i) {
1124 if (!remote->media[i]) {
1135 if (!remote->media[i]->desc.port) {
1153 if (handle_negotiated_sdp_session_media(session_media, session, local, remote, i, stream)) {
1154 SCOPE_EXIT_RTN_VALUE(-1,
"Unable to handle negotiated session media\n");
1157 changed |= session_media->
changed;
1162 ast_channel_lock(session->
channel);
1165 for (i = 0; i < local->media_count; ++i) {
1169 if (!remote->media[i]) {
1183 session_media_set_handler(session_media, NULL);
1195 if (pjmedia_sdp_neg_was_answer_remote(session->
inv_session->neg) == PJ_FALSE &&
1222 ast_channel_unlock(session->
channel);
1228 }
else if (changed == 2) {
1234 SCOPE_EXIT_RTN_VALUE(0);
1237 #define DATASTORE_BUCKETS 53
1238 #define MEDIA_BUCKETS 7
1240 static void session_datastore_destroy(
void *obj)
1247 datastore->
data = NULL;
1250 ast_free((
void *) datastore->
uid);
1251 datastore->
uid = NULL;
1257 char uuid_buf[AST_UUID_STR_LEN];
1258 const char *uid_ptr =
uid;
1264 datastore = ao2_alloc(
sizeof(*datastore), session_datastore_destroy);
1270 if (ast_strlen_zero(uid)) {
1276 if (!datastore->
uid) {
1286 ast_assert(datastore != NULL);
1287 ast_assert(datastore->
info != NULL);
1288 ast_assert(ast_strlen_zero(datastore->
uid) == 0);
1301 void ast_sip_session_remove_datastore(
struct ast_sip_session *session,
const char *name)
1306 enum delayed_method {
1307 DELAYED_METHOD_INVITE,
1308 DELAYED_METHOD_UPDATE,
1321 static const char *delayed_method2str(
enum delayed_method method)
1323 const char *str =
"<unknown>";
1326 case DELAYED_METHOD_INVITE:
1329 case DELAYED_METHOD_UPDATE:
1332 case DELAYED_METHOD_BYE:
1367 enum delayed_method method,
1368 ast_sip_session_request_creation_cb on_request_creation,
1369 ast_sip_session_sdp_creation_cb on_sdp_creation,
1370 ast_sip_session_response_cb on_response,
1371 int generate_new_sdp,
1408 SCOPE_ENTER(3,
"%s: sending delayed %s request\n",
1409 ast_sip_session_get_name(session),
1410 delayed_method2str(delay->
method));
1413 case DELAYED_METHOD_INVITE:
1421 SCOPE_EXIT_RTN_VALUE(res,
"%s\n", ast_sip_session_get_name(session));
1422 case DELAYED_METHOD_UPDATE:
1430 SCOPE_EXIT_RTN_VALUE(res,
"%s\n", ast_sip_session_get_name(session));
1431 case DELAYED_METHOD_BYE:
1432 ast_sip_session_terminate(session, 0);
1433 SCOPE_EXIT_RTN_VALUE(0,
"%s: Terminating session on delayed BYE\n", ast_sip_session_get_name(session));
1436 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: Don't know how to send delayed %s(%d) request.\n",
1437 ast_sip_session_get_name(session),
1451 static int invite_proceeding(
void *vsession)
1457 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
1461 case DELAYED_METHOD_INVITE:
1463 case DELAYED_METHOD_UPDATE:
1465 ast_trace(-1,
"%s: Sending delayed %s request\n", ast_sip_session_get_name(session),
1466 delayed_method2str(delay->
method));
1467 res = send_delayed_request(session, delay);
1468 delayed_request_free(delay);
1473 case DELAYED_METHOD_BYE:
1485 SCOPE_EXIT_RTN_VALUE(res,
"%s\n", ast_sip_session_get_name(session));
1498 static int invite_terminated(
void *vsession)
1505 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
1512 case DELAYED_METHOD_INVITE:
1513 if (!timer_running) {
1517 case DELAYED_METHOD_UPDATE:
1518 case DELAYED_METHOD_BYE:
1524 ast_trace(-1,
"%s: Sending delayed %s request\n", ast_sip_session_get_name(session),
1525 delayed_method2str(delay->
method));
1526 res = send_delayed_request(session, delay);
1527 delayed_request_free(delay);
1536 SCOPE_EXIT_RTN_VALUE(res,
"%s\n", ast_sip_session_get_name(session));
1549 static int invite_collision_timeout(
void *vsession)
1553 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
1563 res = invite_terminated(session);
1566 SCOPE_EXIT_RTN_VALUE(res,
"%s\n", ast_sip_session_get_name(session));
1579 static int update_completed(
void *vsession)
1585 res = invite_proceeding(session);
1587 res = invite_terminated(session);
1594 int (*cb)(
void *vsession))
1603 ast_sip_session_request_creation_cb on_request,
1604 ast_sip_session_sdp_creation_cb on_sdp_creation,
1605 ast_sip_session_response_cb on_response,
1606 int generate_new_sdp,
1607 enum delayed_method method,
1613 on_request, on_sdp_creation, on_response, generate_new_sdp, pending_media_state,
1614 active_media_state);
1615 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
1618 ast_sip_session_media_state_free(pending_media_state);
1619 ast_sip_session_media_state_free(active_media_state);
1620 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR,
"Unable to allocate delay request\n");
1623 if (method == DELAYED_METHOD_BYE || queue_head) {
1629 SCOPE_EXIT_RTN_VALUE(0);
1632 static pjmedia_sdp_session *generate_session_refresh_sdp(
struct ast_sip_session *session)
1634 pjsip_inv_session *inv_session = session->
inv_session;
1635 const pjmedia_sdp_session *previous_sdp = NULL;
1636 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
1638 if (inv_session->neg) {
1639 if (pjmedia_sdp_neg_was_answer_remote(inv_session->neg)) {
1640 pjmedia_sdp_neg_get_active_remote(inv_session->neg, &previous_sdp);
1642 pjmedia_sdp_neg_get_active_local(inv_session->neg, &previous_sdp);
1645 SCOPE_EXIT_RTN_VALUE(create_local_sdp(inv_session, session, previous_sdp, 0));
1652 pj_pool_t *dlg_pool;
1653 pjsip_fromto_hdr *dlg_info;
1654 pjsip_contact_hdr *dlg_contact;
1655 pjsip_name_addr *dlg_info_name_addr;
1656 pjsip_sip_uri *dlg_info_uri;
1657 pjsip_sip_uri *dlg_contact_uri;
1659 const char *pjsip_from_domain;
1667 ast_channel_lock(session->
channel);
1668 effective_id = ast_channel_connected_effective_id(session->
channel);
1670 ast_channel_unlock(session->
channel);
1679 dlg_contact = session->
inv_session->dlg->local.contact;
1680 dlg_info_name_addr = (pjsip_name_addr *) dlg_info->uri;
1681 dlg_info_uri = pjsip_uri_get_uri(dlg_info_name_addr);
1682 dlg_contact_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(dlg_contact->uri);
1685 ast_sip_modify_id_header(dlg_pool, dlg_info, &connected_id);
1687 pj_strdup2(dlg_pool, &dlg_contact_uri->user,
S_COR(connected_id.number.valid, connected_id.number.str,
""));
1694 dlg_info_name_addr->display.ptr = NULL;
1695 dlg_info_name_addr->display.slen = 0;
1706 ast_channel_lock(session->
channel);
1708 if (!ast_strlen_zero(pjsip_from_domain)) {
1709 ast_debug(3,
"%s: From header domain reset by channel variable SIPFROMDOMAIN (%s)\n",
1710 ast_sip_session_get_name(session), pjsip_from_domain);
1711 pj_strdup2(dlg_pool, &dlg_info_uri->host, pjsip_from_domain);
1713 ast_channel_unlock(session->
channel);
1724 pj_strdup2(dlg_pool, &dlg_info_name_addr->display,
"Anonymous");
1727 pj_strdup2(dlg_pool, &dlg_info_uri->user,
"anonymous");
1731 pj_strdup2(dlg_pool, &dlg_contact_uri->user,
"anonymous");
1735 pj_strdup2(dlg_pool, &dlg_info_uri->host,
"anonymous.invalid");
1738 ast_sip_add_usereqphone(session->
endpoint, dlg_pool, dlg_info->uri);
1745 #define STREAM_REMOVED(_stream) (ast_stream_get_state(_stream) == AST_STREAM_STATE_REMOVED)
1746 #define STATE_REMOVED(_stream_state) (_stream_state == AST_STREAM_STATE_REMOVED)
1747 #define STATE_NONE(_stream_state) (_stream_state == AST_STREAM_STATE_END)
1748 #define GET_STREAM_SAFE(_topology, _i) (_i < ast_stream_topology_get_count(_topology) ? ast_stream_topology_get_stream(_topology, _i) : NULL)
1749 #define GET_STREAM_STATE_SAFE(_stream) (_stream ? ast_stream_get_state(_stream) : AST_STREAM_STATE_END)
1750 #define GET_STREAM_NAME_SAFE(_stream) (_stream ? ast_stream_get_name(_stream) : "")
1769 SCOPE_ENTER(3,
"%s: Topology: %s\n", session_name,
1772 if (session_count != stream_count) {
1773 SCOPE_EXIT_RTN_VALUE(0,
"%s: %d media sessions but %d streams\n", session_name,
1774 session_count, stream_count);
1777 for (i = 0; i < stream_count; i++) {
1780 const char *stream_name = NULL;
1785 SCOPE_EXIT_EXPR(
goto end,
"%s: stream %d is null\n", session_name, i);
1789 for (j = 0; j < stream_count; j++) {
1791 if (j == i || !possible_dup) {
1794 if (!STREAM_REMOVED(stream) &&
ast_strings_equal(stream_name, GET_STREAM_NAME_SAFE(possible_dup))) {
1795 SCOPE_EXIT_EXPR(
goto end,
"%s: stream %i %s is duplicated to %d\n", session_name,
1802 SCOPE_EXIT_EXPR(
continue,
"%s: media %d is null\n", session_name, i);
1805 for (j = 0; j < session_count; j++) {
1807 if (j == i || !possible_dup) {
1810 if (!ast_strlen_zero(media->
label) && !ast_strlen_zero(possible_dup->
label)
1812 SCOPE_EXIT_EXPR(
goto end,
"%s: media %d %s is duplicated to %d\n", session_name,
1813 i, media->
label, j);
1818 SCOPE_EXIT_EXPR(
goto end,
"%s: media %d has stream_num %d\n", session_name,
1823 SCOPE_EXIT_EXPR(
goto end,
"%s: media %d has type %s but stream has type %s\n", stream_name,
1831 SCOPE_EXIT_RTN_VALUE(res,
"%s: %s\n", session_name, res ?
"Valid" :
"NOT Valid");
1848 const char *session_name,
1852 int run_post_validation)
1861 int max_stream_count;
1863 SCOPE_ENTER(2,
"%s: DP: %s DA: %s CA: %s\n", session_name,
1877 new_pending_state = ast_sip_session_media_state_clone(current_active_state);
1878 if (!new_pending_state) {
1879 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
"%s: Couldn't clone current_active_state to new_pending_state\n", session_name);
1881 new_pending = new_pending_state->topology;
1883 for (i = 0; i < max_stream_count; i++) {
1884 struct ast_stream *dp_stream = GET_STREAM_SAFE(delayed_pending, i);
1885 struct ast_stream *da_stream = GET_STREAM_SAFE(delayed_active, i);
1886 struct ast_stream *ca_stream = GET_STREAM_SAFE(current_active, i);
1887 struct ast_stream *np_stream = GET_STREAM_SAFE(new_pending, i);
1896 const char *da_name = GET_STREAM_NAME_SAFE(da_stream);
1897 const char *dp_name = GET_STREAM_NAME_SAFE(dp_stream);
1898 const char *ca_name = GET_STREAM_NAME_SAFE(ca_stream);
1899 const char *np_name = GET_STREAM_NAME_SAFE(np_stream);
1900 const char *found_da_name __attribute__((unused)) =
"";
1901 const char *found_np_name __attribute__((unused)) =
"";
1902 int found_da_slot __attribute__((unused)) = -1;
1903 int found_np_slot = -1;
1904 int removed_np_slot = -1;
1906 SCOPE_ENTER(3,
"%s: slot: %d DP: %s DA: %s CA: %s\n", session_name, i,
1911 if (STATE_NONE(da_state) && STATE_NONE(dp_state) && STATE_NONE(ca_state)) {
1912 SCOPE_EXIT_EXPR(
break,
"%s: All gone\n", session_name);
1920 if (STATE_NONE(dp_state) && !STATE_NONE(da_state)) {
1926 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_WARNING,
"%s: DP slot is empty but DA is not\n", session_name);
1929 if (STATE_NONE(dp_state)) {
1936 SCOPE_EXIT_EXPR(
continue,
"%s: No DP stream so use CA stream as is\n", session_name);
1944 ast_trace(-1,
"%s: Same stream in all 3 states\n", session_name);
1945 if (dp_state == da_state && da_state == ca_state) {
1947 SCOPE_EXIT_EXPR(
continue,
"%s: All in the same state so nothing to do\n", session_name);
1949 if (da_state != ca_state) {
1954 SCOPE_EXIT_EXPR(
continue,
"%s: Ignoring request to change state from %s to %s\n",
1957 if (dp_state != da_state) {
1960 SCOPE_EXIT_EXPR(
continue,
"%s: Changed NP stream state from %s to %s\n",
1985 ast_trace(-1,
"%s: Checking if DP is already in NP somewhere\n", session_name);
1988 const char *possible_existing_name = GET_STREAM_NAME_SAFE(possible_existing);
1990 ast_trace(-1,
"%s: Checking %s against %s\n", session_name, dp_name, possible_existing_name);
1991 if (found_np_slot == -1 &&
ast_strings_equal(dp_name, possible_existing_name)) {
1992 ast_trace(-1,
"%s: Pending stream %s slot %d is in NP slot %d\n", session_name,
1995 found_np_stream = possible_existing;
1999 if (STREAM_REMOVED(possible_existing) && removed_np_slot == -1) {
2000 removed_np_slot = j;
2002 if (removed_np_slot >= 0 && found_np_slot >= 0) {
2009 found_np_stream = np_stream;
2010 found_np_state = np_state;
2011 found_np_name = np_name;
2022 ast_trace(-1,
"%s: Checking if DP is already in DA somewhere\n", session_name);
2025 const char *possible_existing_name = GET_STREAM_NAME_SAFE(possible_existing);
2027 ast_trace(-1,
"%s: Checking %s against %s\n", session_name, dp_name, possible_existing_name);
2029 ast_trace(-1,
"%s: Pending stream %s slot %d is already in delayed active slot %d\n",
2030 session_name, dp_name, i, j);
2032 found_da_stream = possible_existing;
2041 found_da_stream = da_stream;
2042 found_da_state = da_state;
2043 found_da_name = da_name;
2046 ast_trace(-1,
"%s: Found NP slot: %d Found removed NP slot: %d Found DA slot: %d\n",
2047 session_name, found_np_slot, removed_np_slot, found_da_slot);
2054 if (!found_da_stream) {
2061 ast_trace(-1,
"%s: There was no corresponding DA stream so the request was to add a stream\n", session_name);
2063 if (found_np_stream) {
2068 SCOPE_EXIT_EXPR(
continue,
"%s: New stream requested but it's already in CA\n", session_name);
2073 ast_trace(-1,
"%s: There was no corresponding NP stream\n", session_name);
2074 if (STATE_REMOVED(dp_state)) {
2081 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
2082 "%s: Attempting to remove stream %d:%s but it doesn't exist anywhere.\n", session_name, i, dp_name);
2089 ast_trace(-1,
"%s: Checking for open slot\n", session_name);
2090 if (removed_np_slot >= 0) {
2094 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_WARNING,
"%s: Couldn't set stream in new topology\n", session_name);
2103 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_WARNING,
"%s: Couldn't replace media session\n", session_name);
2106 ao2_cleanup(old_media);
2107 SCOPE_EXIT_EXPR(
continue,
"%s: Replaced removed stream in slot %d\n",
2108 session_name, removed_np_slot);
2112 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_WARNING,
"%s: Couldn't append stream in new topology\n", session_name);
2117 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_WARNING,
"%s: Couldn't replace media session\n", session_name);
2119 SCOPE_EXIT_EXPR(
continue,
"%s: Appended new stream to slot %d\n",
2120 session_name, new_slot);
2128 ast_trace(-1,
"%s: There was a corresponding DA stream so the request was to change/remove a stream\n", session_name);
2129 if (dp_state == found_da_state) {
2131 if (!found_np_stream) {
2139 SCOPE_EXIT_EXPR(
continue,
"%s: Stream doesn't exist in CA so nothing to do\n", session_name);
2140 }
else if (dp_state == found_np_state) {
2141 SCOPE_EXIT_EXPR(
continue,
"%s: States are the same all around so nothing to do\n", session_name);
2143 SCOPE_EXIT_EXPR(
continue,
"%s: Something changed the CA state so we're going to leave it as is\n", session_name);
2147 ast_trace(-1,
"%s: Requesting state change to %s\n", session_name,
ast_stream_state2str(dp_state));
2148 if (!found_np_stream) {
2149 SCOPE_EXIT_EXPR(
continue,
"%s: Stream doesn't exist in CA so nothing to do\n", session_name);
2150 }
else if (da_state == found_np_state) {
2152 SCOPE_EXIT_EXPR(
continue,
"%s: Changed NP stream state from %s to %s\n",
2155 SCOPE_EXIT_EXPR(
continue,
"%s: Something changed the CA state so we're going to leave it as is\n",
2161 SCOPE_EXIT(
"%s: Done with slot %d\n", session_name, i);
2164 ast_trace(-1,
"%s: Resetting default media states\n", session_name);
2165 for (i = 0; i < AST_MEDIA_TYPE_END; i++) {
2167 new_pending_state->default_session[i] = NULL;
2172 if (media && media->
type == i && !STREAM_REMOVED(stream)) {
2173 new_pending_state->default_session[i] = media;
2179 if (run_post_validation) {
2180 ast_trace(-1,
"%s: Running post-validation\n", session_name);
2181 if (!is_media_state_valid(session_name, new_pending_state)) {
2182 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
"State not consistent\n");
2190 returned_media_state = new_pending_state;
2191 new_pending_state = NULL;
2192 SCOPE_EXIT_RTN_VALUE(returned_media_state,
"%s: NP: %s\n", session_name,
2197 ast_sip_session_request_creation_cb on_request_creation,
2198 ast_sip_session_sdp_creation_cb on_sdp_creation,
2199 ast_sip_session_response_cb on_response,
2200 enum ast_sip_session_refresh_method method,
int generate_new_sdp,
2205 pjsip_inv_session *inv_session = session->
inv_session;
2206 pjmedia_sdp_session *new_sdp = NULL;
2207 pjsip_tx_data *tdata;
2209 SCOPE_ENTER(3,
"%s: New SDP? %s Queued? %s DP: %s DA: %s\n", ast_sip_session_get_name(session),
2210 generate_new_sdp ?
"yes" :
"no", queued ?
"yes" :
"no",
2214 if (pending_media_state && (!pending_media_state->
topology || !generate_new_sdp)) {
2216 ast_sip_session_media_state_free(pending_media_state);
2217 ast_sip_session_media_state_free(active_media_state);
2218 SCOPE_EXIT_RTN_VALUE(-1,
"%s: Not sending reinvite because %s%s\n", ast_sip_session_get_name(session),
2219 pending_media_state->
topology == NULL ?
"pending topology is null " :
"",
2220 !generate_new_sdp ?
"generate_new_sdp is false" :
"");
2223 if (inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2225 ast_sip_session_media_state_free(pending_media_state);
2226 ast_sip_session_media_state_free(active_media_state);
2227 SCOPE_EXIT_RTN_VALUE(0,
"%s: Not sending reinvite because of disconnected state\n",
2228 ast_sip_session_get_name(session));
2232 if (inv_session->dlg->state != PJSIP_DIALOG_STATE_ESTABLISHED) {
2233 res = delay_request(session, on_request_creation, on_sdp_creation, on_response,
2235 method == AST_SIP_SESSION_REFRESH_METHOD_INVITE
2236 ? DELAYED_METHOD_INVITE : DELAYED_METHOD_UPDATE,
2237 pending_media_state, active_media_state ? active_media_state : ast_sip_session_media_state_clone(session->
active_media_state), queued);
2238 SCOPE_EXIT_RTN_VALUE(res,
"%s: Delay sending reinvite because dialog has not been established\n",
2239 ast_sip_session_get_name(session));
2242 if (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE) {
2243 if (inv_session->invite_tsx) {
2245 res = delay_request(session, on_request_creation, on_sdp_creation,
2246 on_response, generate_new_sdp, DELAYED_METHOD_INVITE, pending_media_state,
2247 active_media_state ? active_media_state : ast_sip_session_media_state_clone(session->
active_media_state), queued);
2248 SCOPE_EXIT_RTN_VALUE(res,
"%s: Delay sending reinvite because of outstanding transaction\n",
2249 ast_sip_session_get_name(session));
2250 }
else if (inv_session->state != PJSIP_INV_STATE_CONFIRMED) {
2254 ast_sip_session_media_state_free(pending_media_state);
2255 ast_sip_session_media_state_free(active_media_state);
2256 SCOPE_EXIT_RTN_VALUE(0,
"%s: Not sending reinvite because not in confirmed state\n",
2257 ast_sip_session_get_name(session));
2261 if (generate_new_sdp) {
2263 if (inv_session->neg
2264 && pjmedia_sdp_neg_get_state(inv_session->neg)
2265 != PJMEDIA_SDP_NEG_STATE_DONE) {
2266 res = delay_request(session, on_request_creation, on_sdp_creation,
2267 on_response, generate_new_sdp,
2268 method == AST_SIP_SESSION_REFRESH_METHOD_INVITE
2269 ? DELAYED_METHOD_INVITE : DELAYED_METHOD_UPDATE, pending_media_state,
2270 active_media_state ? active_media_state : ast_sip_session_media_state_clone(session->
active_media_state), queued);
2271 SCOPE_EXIT_RTN_VALUE(res,
"%s: Delay session refresh with new SDP because SDP negotiation is not yet done\n",
2272 ast_sip_session_get_name(session));
2276 if (pending_media_state) {
2278 int type_streams[AST_MEDIA_TYPE_END] = {0};
2280 ast_trace(-1,
"%s: Pending media state exists\n", ast_sip_session_get_name(session));
2288 res = delay_request(session, on_request_creation, on_sdp_creation,
2289 on_response, generate_new_sdp,
2290 method == AST_SIP_SESSION_REFRESH_METHOD_INVITE
2291 ? DELAYED_METHOD_INVITE : DELAYED_METHOD_UPDATE, pending_media_state,
2292 active_media_state ? active_media_state : ast_sip_session_media_state_clone(session->
active_media_state), queued);
2293 SCOPE_EXIT_RTN_VALUE(res,
"%s: Delay sending reinvite because of outstanding requests\n",
2294 ast_sip_session_get_name(session));
2301 if (active_media_state && active_media_state->
topology &&
2307 ast_trace(-1,
"%s: Active media state exists and is%s equal to pending\n", ast_sip_session_get_name(session),
2314 new_pending_state = resolve_refresh_media_states(ast_sip_session_get_name(session),
2316 if (new_pending_state) {
2318 ast_sip_session_media_state_free(pending_media_state);
2319 pending_media_state = new_pending_state;
2321 ast_sip_session_media_state_reset(pending_media_state);
2322 ast_sip_session_media_state_free(active_media_state);
2323 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: Unable to merge media states\n", ast_sip_session_get_name(session));
2332 ast_trace(-1,
"%s: Pruning and checking formats of streams\n", ast_sip_session_get_name(session));
2337 SCOPE_ENTER(4,
"%s: Checking stream %s\n", ast_sip_session_get_name(session),
2343 ast_trace(-1,
"%s: Found existing stream %s\n", ast_sip_session_get_name(session),
2351 ao2_cleanup(session_media);
2356 ast_trace(-1,
"%s: Dropped overlimit stream %s\n", ast_sip_session_get_name(session),
2361 SCOPE_EXIT_EXPR(
continue);
2367 if (!existing_stream) {
2368 ast_trace(-1,
"%s: Dropped removed stream %s\n", ast_sip_session_get_name(session),
2374 SCOPE_EXIT_EXPR(
continue);
2384 ast_sip_session_media_state_free(pending_media_state);
2385 ast_sip_session_media_state_free(active_media_state);
2387 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Unable to alloc format caps\n", ast_sip_session_get_name(session));
2393 if (!existing_stream) {
2399 SCOPE_EXIT_EXPR(
continue,
"%s: Dropped incompatible stream %s\n",
2408 SCOPE_EXIT_EXPR(
continue,
"%s: Dropped incompatible stream %s\n",
2420 ao2_cleanup(joint_cap);
2440 SCOPE_ENTER(4,
"%s: Stream %s not in pending\n", ast_sip_session_get_name(session),
2445 ast_sip_session_media_state_free(pending_media_state);
2446 ast_sip_session_media_state_free(active_media_state);
2448 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Unable to clone stream %s\n",
2456 ast_sip_session_media_state_free(pending_media_state);
2457 ast_sip_session_media_state_free(active_media_state);
2459 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Unable to append cloned stream\n",
2460 ast_sip_session_get_name(session));
2462 SCOPE_EXIT(
"%s: Appended empty stream in position %d to make counts match\n",
2463 ast_sip_session_get_name(session), position);
2473 ast_sip_session_media_state_free(pending_media_state);
2474 ast_sip_session_media_state_free(active_media_state);
2479 SCOPE_EXIT_RTN_VALUE(queued ? 1 : 0,
"%s: Topologies are equal. Not sending re-invite\n",
2480 ast_sip_session_get_name(session));
2488 new_sdp = generate_session_refresh_sdp(session);
2491 ast_sip_session_media_state_free(active_media_state);
2492 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: Failed to generate session refresh SDP. Not sending session refresh\n",
2493 ast_sip_session_get_name(session));
2495 if (on_sdp_creation) {
2498 ast_sip_session_media_state_free(active_media_state);
2499 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: on_sdp_creation failed\n", ast_sip_session_get_name(session));
2504 if (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE) {
2505 if (pjsip_inv_reinvite(inv_session, NULL, new_sdp, &tdata)) {
2506 if (generate_new_sdp) {
2509 ast_sip_session_media_state_free(active_media_state);
2510 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: Failed to create reinvite properly\n", ast_sip_session_get_name(session));
2512 }
else if (pjsip_inv_update(inv_session, NULL, new_sdp, &tdata)) {
2513 if (generate_new_sdp) {
2516 ast_sip_session_media_state_free(active_media_state);
2517 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: Failed to create UPDATE properly\n", ast_sip_session_get_name(session));
2519 if (on_request_creation) {
2521 if (generate_new_sdp) {
2524 ast_sip_session_media_state_free(active_media_state);
2525 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING,
"%s: on_request_creation failed.\n", ast_sip_session_get_name(session));
2528 ast_sip_session_send_request_with_cb(session, tdata, on_response);
2529 ast_sip_session_media_state_free(active_media_state);
2532 SCOPE_EXIT_RTN_VALUE(res,
"%s: Sending session refresh SDP via %s\n", ast_sip_session_get_name(session),
2533 method == AST_SIP_SESSION_REFRESH_METHOD_INVITE ?
"re-INVITE" :
"UPDATE");
2537 ast_sip_session_request_creation_cb on_request_creation,
2538 ast_sip_session_sdp_creation_cb on_sdp_creation,
2539 ast_sip_session_response_cb on_response,
2540 enum ast_sip_session_refresh_method method,
int generate_new_sdp,
2543 return sip_session_refresh(session, on_request_creation, on_sdp_creation,
2544 on_response, method, generate_new_sdp, media_state, NULL, 0);
2547 int ast_sip_session_regenerate_answer(
struct ast_sip_session *session,
2548 ast_sip_session_sdp_creation_cb on_sdp_creation)
2550 pjsip_inv_session *inv_session = session->
inv_session;
2551 pjmedia_sdp_session *new_answer = NULL;
2552 const pjmedia_sdp_session *previous_offer = NULL;
2553 SCOPE_ENTER(1,
"%s\n", ast_sip_session_get_name(session));
2556 if (!inv_session->neg || (pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
2557 pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO)) {
2558 ast_log(LOG_WARNING,
"Requested to regenerate local SDP answer for channel '%s' but negotiation in state '%s'\n",
2559 ast_channel_name(session->
channel), pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_get_state(inv_session->neg)));
2560 SCOPE_EXIT_RTN_VALUE(-1,
"Bad negotiation state\n");
2563 pjmedia_sdp_neg_get_neg_remote(inv_session->neg, &previous_offer);
2564 if (pjmedia_sdp_neg_get_state(inv_session->neg) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) {
2566 pjmedia_sdp_neg_negotiate(inv_session->pool, inv_session->neg, 0);
2567 pjmedia_sdp_neg_set_remote_offer(inv_session->pool, inv_session->neg, previous_offer);
2570 new_answer = create_local_sdp(inv_session, session, previous_offer, 0);
2572 ast_log(LOG_WARNING,
"Could not create a new local SDP answer for channel '%s'\n",
2573 ast_channel_name(session->
channel));
2574 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create new SDP\n");
2577 if (on_sdp_creation) {
2579 SCOPE_EXIT_RTN_VALUE(-1,
"Callback failed\n");
2583 pjsip_inv_set_sdp_answer(inv_session, new_answer);
2585 SCOPE_EXIT_RTN_VALUE(0);
2588 void ast_sip_session_send_response(
struct ast_sip_session *session, pjsip_tx_data *tdata)
2590 pjsip_dialog *dlg = pjsip_tdata_get_dlg(tdata);
2595 handle_outgoing_response(session, tdata);
2601 static pj_bool_t session_on_rx_request(pjsip_rx_data *rdata);
2602 static pj_bool_t session_on_rx_response(pjsip_rx_data *rdata);
2603 static pj_status_t session_on_tx_response(pjsip_tx_data *tdata);
2604 static void session_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e);
2606 static pjsip_module session_module = {
2607 .name = {
"Session Module", 14},
2608 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
2609 .on_rx_request = session_on_rx_request,
2610 .on_rx_response = session_on_rx_response,
2611 .on_tsx_state = session_on_tsx_state,
2612 .on_tx_response = session_on_tx_response,
2620 static int sdp_requires_deferral(
struct ast_sip_session *session,
const pjmedia_sdp_session *sdp)
2631 for (i = 0; i < sdp->media_count; ++i) {
2640 enum ast_sip_session_sdp_stream_defer res;
2641 pjmedia_sdp_media *remote_stream = sdp->media[i];
2644 ast_copy_pj_str(media, &sdp->media[i]->desc.media,
sizeof(media));
2665 if (existing_stream) {
2668 if (!ast_strlen_zero(stream_label)) {
2674 if (!session_media) {
2679 if (!ast_sip_session_is_pending_stream_default(session, stream) || strcmp(media,
"audio")) {
2680 if (pjmedia_sdp_media_find_attr2(remote_stream,
"sendonly", NULL)) {
2686 }
else if (pjmedia_sdp_media_find_attr2(remote_stream,
"recvonly", NULL)) {
2688 }
else if (pjmedia_sdp_media_find_attr2(remote_stream,
"inactive", NULL)) {
2698 handler = session_media->
handler;
2703 case AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED:
2705 case AST_SIP_SESSION_SDP_DEFER_ERROR:
2707 case AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED:
2709 case AST_SIP_SESSION_SDP_DEFER_NEEDED:
2717 handler_list = ao2_find(sdp_handlers, media,
OBJ_KEY);
2718 if (!handler_list) {
2719 ast_debug(3,
"%s: No registered SDP handlers for media type '%s'\n", ast_sip_session_get_name(session), media);
2723 if (handler == session_media->
handler) {
2732 case AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED:
2734 case AST_SIP_SESSION_SDP_DEFER_ERROR:
2735 session_media_set_handler(session_media, handler);
2737 case AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED:
2739 session_media_set_handler(session_media, handler);
2741 case AST_SIP_SESSION_SDP_DEFER_NEEDED:
2743 session_media_set_handler(session_media, handler);
2753 static pj_bool_t session_reinvite_on_rx_request(pjsip_rx_data *rdata)
2757 pjsip_rdata_sdp_info *sdp_info;
2760 if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD ||
2761 !(dlg = pjsip_ua_find_dialog(&rdata->msg_info.cid->id, &rdata->msg_info.to->tag, &rdata->msg_info.from->tag, PJ_FALSE)) ||
2762 !(session = ast_sip_dialog_get_session(dlg)) ||
2773 pj_str_t key, deferred_key;
2774 pjsip_tx_data *tdata;
2777 pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS, &rdata->msg_info.cseq->method, rdata);
2778 pjsip_tsx_create_key(rdata->tp_info.pool, &deferred_key, PJSIP_ROLE_UAS, &session->
deferred_reinvite->msg_info.cseq->method,
2782 if (!pj_strcmp(&key, &deferred_key)) {
2787 if (pjsip_dlg_create_response(dlg, rdata, 491, NULL, &tdata) == PJ_SUCCESS) {
2788 if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
2789 pjsip_tx_data_dec_ref(tdata);
2796 if (!(sdp_info = pjsip_rdata_get_sdp_info(rdata)) ||
2797 (sdp_info->sdp_err != PJ_SUCCESS)) {
2801 if (!sdp_info->sdp) {
2805 deferred = sdp_requires_deferral(session, sdp_info->sdp);
2806 if (deferred == -1) {
2809 }
else if (!deferred) {
2825 pjsip_endpt_process_rx_data(ast_sip_get_pjsip_endpoint(),
2832 static pjsip_module session_reinvite_module = {
2833 .name = {
"Session Re-Invite Module", 24 },
2834 .priority = PJSIP_MOD_PRIORITY_UA_PROXY_LAYER - 1,
2835 .on_rx_request = session_reinvite_on_rx_request,
2838 void ast_sip_session_send_request_with_cb(
struct ast_sip_session *session, pjsip_tx_data *tdata,
2839 ast_sip_session_response_cb on_response)
2841 pjsip_inv_session *inv_session = session->
inv_session;
2848 if (inv_session->state == PJSIP_INV_STATE_DISCONNECTED &&
2849 tdata->msg->line.req.method.id != PJSIP_BYE_METHOD) {
2853 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, session_module.id,
2854 MOD_DATA_ON_RESPONSE, on_response);
2856 handle_outgoing_request(session, tdata);
2862 void ast_sip_session_send_request(
struct ast_sip_session *session, pjsip_tx_data *tdata)
2864 ast_sip_session_send_request_with_cb(session, tdata, NULL);
2867 int ast_sip_session_create_invite(
struct ast_sip_session *session, pjsip_tx_data **tdata)
2869 pjmedia_sdp_session *offer;
2870 SCOPE_ENTER(1,
"%s\n", ast_sip_session_get_name(session));
2872 if (!(offer = create_local_sdp(session->
inv_session, session, NULL, 0))) {
2873 pjsip_inv_terminate(session->
inv_session, 500, PJ_FALSE);
2874 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create offer\n");
2877 pjsip_inv_set_local_sdp(session->
inv_session, offer);
2878 pjmedia_sdp_neg_set_prefer_remote_codec_order(session->
inv_session->neg, PJ_FALSE);
2879 #ifdef PJMEDIA_SDP_NEG_ANSWER_MULTIPLE_CODECS
2881 pjmedia_sdp_neg_set_answer_multiple_codecs(session->
inv_session->neg, PJ_TRUE);
2889 set_from_header(session);
2891 if (pjsip_inv_invite(session->
inv_session, tdata) != PJ_SUCCESS) {
2892 SCOPE_EXIT_RTN_VALUE(-1,
"pjsip_inv_invite failed\n");
2895 SCOPE_EXIT_RTN_VALUE(0);
2898 static int datastore_hash(
const void *obj,
int flags)
2901 const char *uid = flags &
OBJ_KEY ? obj : datastore->
uid;
2903 ast_assert(uid != NULL);
2908 static int datastore_cmp(
void *obj,
void *arg,
int flags)
2912 const char *uid2 = flags &
OBJ_KEY ? arg : datastore2->
uid;
2914 ast_assert(datastore1->
uid != NULL);
2915 ast_assert(uid2 != NULL);
2920 static void session_destructor(
void *obj)
2925 #ifdef TEST_FRAMEWORK
2927 const char *endpoint_name = session->
endpoint ?
2931 ast_debug(3,
"%s: Destroying SIP session\n", ast_sip_session_get_name(session));
2943 handle_session_destroy(session);
2946 ast_sip_session_remove_supplements(session);
2959 delayed_request_free(delay);
2963 ao2_cleanup(session->
aor);
2964 ao2_cleanup(session->
contact);
2967 ast_dsp_free(session->
dsp);
2970 struct pjsip_dialog *dlg = session->
inv_session->dlg;
2976 #ifdef HAVE_PJSIP_INV_SESSION_REF
2979 pjsip_dlg_dec_session(dlg, &session_module);
2986 static void sip_channel_destroy(
void *obj)
2990 ao2_cleanup(channel->
pvt);
2991 ao2_cleanup(channel->
session);
3015 int dsp_features = 0;
3017 session = ao2_alloc(
sizeof(*session), session_destructor);
3047 if (endpoint->
dtmf == AST_SIP_DTMF_INBAND || endpoint->
dtmf == AST_SIP_DTMF_AUTO) {
3048 dsp_features |= DSP_FEATURE_DIGIT_DETECT;
3051 dsp_features |= DSP_FEATURE_FAX_DETECT;
3055 if (!session->
dsp) {
3098 #ifdef HAVE_PJSIP_INV_SESSION_REF
3099 if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
3100 ast_log(LOG_ERROR,
"Can't increase the session reference counter\n");
3105 pjsip_dlg_inc_session(inv_session->dlg, &session_module);
3106 inv_session->mod_data[session_module.id] =
ao2_bump(session);
3113 if (ast_sip_session_add_supplements(session)) {
3122 handle_session_begin(session);
3125 ret_session = session;
3132 ast_cond_t cond_suspended;
3133 ast_cond_t cond_complete;
3138 static void sip_session_suspender_dtor(
void *vdoomed)
3142 ast_cond_destroy(&doomed->cond_suspended);
3143 ast_cond_destroy(&doomed->cond_complete);
3154 static int sip_session_suspend_task(
void *data)
3158 ao2_lock(suspender);
3161 suspender->suspended = 1;
3162 ast_cond_signal(&suspender->cond_suspended);
3165 while (!suspender->complete) {
3169 ao2_unlock(suspender);
3192 suspender = ao2_alloc(
sizeof(*suspender), sip_session_suspender_dtor);
3197 ast_cond_init(&suspender->cond_suspended, NULL);
3198 ast_cond_init(&suspender->cond_complete, NULL);
3211 ao2_lock(suspender);
3212 while (!suspender->suspended) {
3215 ao2_unlock(suspender);
3231 ao2_lock(suspender);
3232 suspender->complete = 1;
3233 ast_cond_signal(&suspender->cond_complete);
3234 ao2_unlock(suspender);
3251 static pj_bool_t outbound_invite_auth(pjsip_rx_data *rdata)
3253 pjsip_transaction *tsx;
3255 pjsip_inv_session *inv;
3256 pjsip_tx_data *tdata;
3259 if (rdata->msg_info.msg->line.status.code != 401
3260 && rdata->msg_info.msg->line.status.code != 407) {
3265 tsx = pjsip_rdata_get_tsx(rdata);
3266 dlg = pjsip_rdata_get_dlg(rdata);
3271 if (tsx->method.id != PJSIP_INVITE_METHOD) {
3276 inv = pjsip_dlg_get_inv_session(dlg);
3277 session = inv->mod_data[session_module.id];
3279 if (PJSIP_INV_STATE_CONFIRMED <= inv->state) {
3285 ast_debug(3,
"%s: A reINVITE is being challenged\n", ast_sip_session_get_name(session));
3288 ast_debug(3,
"%s: Initial INVITE is being challenged.\n", ast_sip_session_get_name(session));
3291 ast_debug(3,
"%s: Initial INVITE reached maximum number of auth attempts.\n", ast_sip_session_get_name(session));
3296 tsx->last_tx, &tdata)) {
3304 pjsip_inv_uac_restart(inv, PJ_FALSE);
3306 ast_sip_session_send_request(session, tdata);
3310 static pjsip_module outbound_invite_auth_module = {
3311 .name = {
"Outbound INVITE Auth", 20},
3312 .priority = PJSIP_MOD_PRIORITY_DIALOG_USAGE,
3313 .on_rx_response = outbound_invite_auth,
3326 static int setup_outbound_invite_auth(pjsip_dialog *dlg)
3331 status = pjsip_dlg_add_usage(dlg, &outbound_invite_auth_module, NULL);
3334 return status != PJ_SUCCESS ? -1 : 0;
3338 struct ast_sip_contact *contact,
const char *location,
const char *request_user,
3341 const char *uri = NULL;
3344 pjsip_timer_setting timer;
3346 struct pjsip_inv_session *inv_session;
3353 if (location || !contact) {
3354 location =
S_OR(location, endpoint->
aors);
3356 ast_sip_location_retrieve_contact_and_aor_from_list_filtered(location, AST_SIP_CONTACT_FILTER_REACHABLE,
3357 &found_aor, &found_contact);
3358 if (!found_contact || ast_strlen_zero(found_contact->uri)) {
3361 uri = found_contact->uri;
3368 if (ast_strlen_zero(uri)) {
3369 ast_log(LOG_ERROR,
"Endpoint '%s': No URI available. Is endpoint registered?\n",
3371 SCOPE_EXIT_RTN_VALUE(NULL,
"No URI\n");
3374 if (!(dlg = ast_sip_create_dialog_uac(endpoint, uri, request_user))) {
3375 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't create dialog\n");
3378 if (setup_outbound_invite_auth(dlg)) {
3379 pjsip_dlg_terminate(dlg);
3380 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't setup auth\n");
3383 if (pjsip_inv_create_uac(dlg, NULL, endpoint->
extensions.
flags, &inv_session) != PJ_SUCCESS) {
3384 pjsip_dlg_terminate(dlg);
3385 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't create uac\n");
3387 #if defined(HAVE_PJSIP_REPLACE_MEDIA_STREAM) || defined(PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE)
3388 inv_session->sdp_neg_flags = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE;
3391 pjsip_timer_setting_default(&timer);
3394 pjsip_timer_init_session(inv_session, &timer);
3396 session = ast_sip_session_alloc(endpoint, found_contact ? found_contact : contact,
3399 pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3421 clone_stream = ast_sip_session_create_joint_call_stream(session, req_stream);
3430 pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3432 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't create topology\n");
3447 pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3449 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't clone topology\n");
3453 if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
3454 pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3459 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't add usage\n");
3463 ret_session = session;
3465 SCOPE_EXIT_RTN_VALUE(ret_session);
3468 static int session_end(
void *vsession);
3469 static int session_end_completion(
void *vsession);
3471 void ast_sip_session_terminate(
struct ast_sip_session *session,
int response)
3474 pjsip_tx_data *packet = NULL;
3475 SCOPE_ENTER(1,
"%s Response %d\n", ast_sip_session_get_name(session), response);
3479 SCOPE_EXIT_RTN(
"Deferred\n");
3497 case PJSIP_INV_STATE_NULL:
3506 session->
inv_session->mod_data[session_module.id] = NULL;
3507 pjsip_inv_terminate(session->
inv_session, response, PJ_TRUE);
3508 session_end(session);
3513 session_end_completion(session);
3515 pjsip_inv_terminate(session->
inv_session, response, PJ_TRUE);
3518 case PJSIP_INV_STATE_CONFIRMED:
3520 ast_debug(3,
"%s: Delay sending BYE because of outstanding transaction...\n",
3521 ast_sip_session_get_name(session));
3525 delay_request(session, NULL, NULL, NULL, 0, DELAYED_METHOD_BYE, NULL, NULL, 1);
3530 status = pjsip_inv_end_session(session->
inv_session, response, NULL, &packet);
3531 if (status == PJ_SUCCESS && packet) {
3536 delayed_request_free(delay);
3539 if (packet->msg->type == PJSIP_RESPONSE_MSG) {
3540 ast_sip_session_send_response(session, packet);
3542 ast_sip_session_send_request(session, packet);
3550 static int session_termination_task(
void *data)
3557 ast_sip_session_terminate(session, 0);
3565 static void session_termination_cb(pj_timer_heap_t *
timer_heap,
struct pj_timer_entry *
entry)
3570 ao2_cleanup(session);
3574 int ast_sip_session_defer_termination(
struct ast_sip_session *session)
3576 pj_time_val delay = { .sec = 60, };
3590 res = (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(),
3606 static void sip_session_defer_termination_stop_timer(
struct ast_sip_session *session)
3608 if (pj_timer_heap_cancel_if_active(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
3614 void ast_sip_session_defer_termination_cancel(
struct ast_sip_session *session)
3625 ast_sip_session_terminate(session, 0);
3629 sip_session_defer_termination_stop_timer(session);
3642 ast_debug(3,
"%s: Ending session after being deferred\n", ast_sip_session_get_name(session));
3644 session_end(session);
3650 pjsip_inv_session *inv_session = pjsip_dlg_get_inv_session(dlg);
3654 !(session = inv_session->mod_data[session_module.id])) {
3663 pjsip_dialog *ast_sip_session_get_dialog(
const struct ast_sip_session *session)
3665 pjsip_inv_session *inv_session = session->
inv_session;
3671 return inv_session->dlg;
3674 pjsip_inv_state ast_sip_session_get_pjsip_inv_state(
const struct ast_sip_session *session)
3676 pjsip_inv_session *inv_session = session->
inv_session;
3679 return PJSIP_INV_STATE_NULL;
3682 return inv_session->state;
3686 static int fetch_callerid_num(
struct ast_sip_session *session, pjsip_rx_data *rdata,
char *buf,
size_t len)
3700 enum sip_get_destination_result {
3702 SIP_GET_DEST_EXTEN_FOUND,
3704 SIP_GET_DEST_EXTEN_NOT_FOUND,
3706 SIP_GET_DEST_EXTEN_PARTIAL,
3708 SIP_GET_DEST_UNSUPPORTED_URI,
3721 static enum sip_get_destination_result get_destination(
struct ast_sip_session *session, pjsip_rx_data *rdata)
3724 pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
3728 if (!ast_sip_is_allowed_uri(ruri)) {
3729 return SIP_GET_DEST_UNSUPPORTED_URI;
3732 ast_copy_pj_str(session->
exten, ast_sip_pjsip_uri_get_username(ruri),
sizeof(session->
exten));
3733 if (ast_strlen_zero(session->
exten)) {
3735 ast_debug(1,
"RURI contains no user portion: defaulting to extension 's'\n");
3743 AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(session->
exten);
3745 pickup_cfg = ast_get_chan_features_pickup_config(NULL);
3747 ast_log(LOG_ERROR,
"%s: Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n",
3748 ast_sip_session_get_name(session));
3755 fetch_callerid_num(session, rdata, cid_num,
sizeof(cid_num));
3759 if (!strcmp(session->
exten, pickupexten) ||
3767 return SIP_GET_DEST_EXTEN_FOUND;
3774 !strncmp(session->
exten, pickupexten, strlen(session->
exten)) ||
3777 return SIP_GET_DEST_EXTEN_PARTIAL;
3780 return SIP_GET_DEST_EXTEN_NOT_FOUND;
3805 static int new_invite_initial_answer(pjsip_inv_session *inv_session, pjsip_rx_data *rdata,
3806 int answer_code,
int terminate_code, pj_bool_t notify)
3808 pjsip_tx_data *tdata = NULL;
3811 if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
3812 if (pjsip_inv_initial_answer(
3813 inv_session, rdata, answer_code, NULL, NULL, &tdata) != PJ_SUCCESS) {
3815 pjsip_inv_terminate(inv_session, terminate_code ? terminate_code : answer_code, notify);
3818 pjsip_inv_send_msg(inv_session, tdata);
3822 if (answer_code >= 300) {
3827 pjsip_dlg_dec_lock(inv_session->dlg);
3852 static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata,
const struct ast_sip_endpoint *endpoint)
3854 pjsip_tx_data *tdata;
3856 pjsip_inv_session *inv_session;
3858 const pj_str_t STR_100REL = {
"100rel", 6};
3860 pj_status_t dlg_status = PJ_EUNKNOWN;
3866 if (endpoint->
rel100 == AST_SIP_100REL_PEER_SUPPORTED && rdata->msg_info.supported != NULL) {
3867 for (i = 0; i < rdata->msg_info.supported->count; ++i) {
3868 if (pj_stricmp(&rdata->msg_info.supported->values[i], &STR_100REL) == 0) {
3869 options |= PJSIP_INV_REQUIRE_100REL;
3875 if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, ast_sip_get_pjsip_endpoint(), &tdata) != PJ_SUCCESS) {
3877 if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
3878 pjsip_tx_data_dec_ref(tdata);
3881 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
3886 dlg = ast_sip_create_dialog_uas_locked(endpoint, rdata, &dlg_status);
3888 if (dlg_status != PJ_EEXISTS) {
3889 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
3899 if (pjsip_inv_create_uas(dlg, rdata, NULL, options, &inv_session) != PJ_SUCCESS) {
3900 pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
3906 pjsip_dlg_dec_lock(dlg);
3907 pjsip_dlg_terminate(dlg);
3911 #if defined(HAVE_PJSIP_REPLACE_MEDIA_STREAM) || defined(PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE)
3912 inv_session->sdp_neg_flags = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE;
3914 if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
3916 new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE);
3918 pjsip_dlg_dec_session(inv_session->dlg, &session_module);
3933 static int check_sdp_content_type_supported(pjsip_media_type *content_type)
3935 pjsip_media_type app_sdp;
3936 pjsip_media_type_init2(&app_sdp,
"application",
"sdp");
3938 if (!pjsip_media_type_cmp(content_type, &app_sdp, 0)) {
3945 static int check_content_disposition_in_multipart(pjsip_multipart_part *part)
3947 pjsip_hdr *hdr = part->hdr.next;
3948 static const pj_str_t str_handling_required = {
"handling=required", 16};
3950 while (hdr != &part->hdr) {
3951 if (hdr->type == PJSIP_H_OTHER) {
3952 pjsip_generic_string_hdr *generic_hdr = (pjsip_generic_string_hdr*)hdr;
3954 if (!pj_stricmp2(&hdr->name,
"Content-Disposition") &&
3955 pj_stristr(&generic_hdr->hvalue, &str_handling_required) &&
3956 !check_sdp_content_type_supported(&part->body->content_type)) {
3969 static int check_content_disposition(pjsip_rx_data *rdata)
3971 pjsip_msg_body *body = rdata->msg_info.msg->body;
3972 pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype;
3974 if (body && ctype_hdr &&
3975 ast_sip_is_media_type_in(&ctype_hdr->media, &pjsip_media_type_multipart_mixed,
3976 &pjsip_media_type_multipart_alternative, SENTINEL)) {
3977 pjsip_multipart_part *part = pjsip_multipart_get_first_part(body);
3978 while (part != NULL) {
3979 if (check_content_disposition_in_multipart(part)) {
3982 part = pjsip_multipart_get_next_part(body, part);
3990 pjsip_tx_data *tdata = NULL;
3991 pjsip_timer_setting timer;
3992 pjsip_rdata_sdp_info *sdp_info;
3993 pjmedia_sdp_session *local = NULL;
3994 char buffer[AST_SOCKADDR_BUFLEN];
3995 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(invite->
session));
4003 ast_trace_log(-1, LOG_ERROR,
"%s: Session already DISCONNECTED [reason=%d (%s)]\n",
4004 ast_sip_session_get_name(invite->
session),
4007 SCOPE_EXIT_RTN_VALUE(-1);
4010 switch (get_destination(invite->
session, invite->
rdata)) {
4011 case SIP_GET_DEST_EXTEN_FOUND:
4014 case SIP_GET_DEST_UNSUPPORTED_URI:
4015 ast_trace(-1,
"%s: Call (%s:%s) to extension '%s' - unsupported uri\n",
4016 ast_sip_session_get_name(invite->
session),
4017 invite->
rdata->tp_info.transport->type_name,
4018 pj_sockaddr_print(&invite->
rdata->pkt_info.src_addr, buffer,
sizeof(buffer), 3),
4020 if (pjsip_inv_initial_answer(invite->
session->
inv_session, invite->
rdata, 416, NULL, NULL, &tdata) == PJ_SUCCESS) {
4021 ast_sip_session_send_response(invite->
session, tdata);
4026 case SIP_GET_DEST_EXTEN_PARTIAL:
4027 ast_trace(-1,
"%s: Call (%s:%s) to extension '%s' - partial match\n",
4028 ast_sip_session_get_name(invite->
session),
4029 invite->
rdata->tp_info.transport->type_name,
4030 pj_sockaddr_print(&invite->
rdata->pkt_info.src_addr, buffer,
sizeof(buffer), 3),
4033 if (pjsip_inv_initial_answer(invite->
session->
inv_session, invite->
rdata, 484, NULL, NULL, &tdata) == PJ_SUCCESS) {
4034 ast_sip_session_send_response(invite->
session, tdata);
4039 case SIP_GET_DEST_EXTEN_NOT_FOUND:
4041 ast_trace_log(-1, LOG_NOTICE,
"%s: Call (%s:%s) to extension '%s' rejected because extension not found in context '%s'.\n",
4042 ast_sip_session_get_name(invite->
session),
4043 invite->
rdata->tp_info.transport->type_name,
4044 pj_sockaddr_print(&invite->
rdata->pkt_info.src_addr, buffer,
sizeof(buffer), 3),
4048 if (pjsip_inv_initial_answer(invite->
session->
inv_session, invite->
rdata, 404, NULL, NULL, &tdata) == PJ_SUCCESS) {
4049 ast_sip_session_send_response(invite->
session, tdata);
4056 if (check_content_disposition(invite->
rdata)) {
4057 if (pjsip_inv_initial_answer(invite->
session->
inv_session, invite->
rdata, 415, NULL, NULL, &tdata) == PJ_SUCCESS) {
4058 ast_sip_session_send_response(invite->
session, tdata);
4065 pjsip_timer_setting_default(&timer);
4075 if (pjsip_inv_initial_answer(invite->
session->
inv_session, invite->
rdata, 100, NULL, NULL, &tdata) != PJ_SUCCESS) {
4084 ast_trace(-1,
"%s: Call (%s:%s) to extension '%s' sending 100 Trying\n",
4085 ast_sip_session_get_name(invite->
session),
4086 invite->
rdata->tp_info.transport->type_name,
4087 pj_sockaddr_print(&invite->
rdata->pkt_info.src_addr, buffer,
sizeof(buffer), 3),
4089 ast_sip_session_send_response(invite->
session, tdata);
4091 sdp_info = pjsip_rdata_get_sdp_info(invite->
rdata);
4092 if (sdp_info && (sdp_info->sdp_err == PJ_SUCCESS) && sdp_info->sdp) {
4093 if (handle_incoming_sdp(invite->
session, sdp_info->sdp)) {
4095 if (pjsip_inv_end_session(invite->
session->
inv_session, 488, NULL, &tdata) == PJ_SUCCESS
4097 ast_sip_session_send_response(invite->
session, tdata);
4111 if (pjsip_inv_end_session(invite->
session->
inv_session, 500, NULL, &tdata) == PJ_SUCCESS
4113 ast_sip_session_send_response(invite->
session, tdata);
4119 pjmedia_sdp_neg_set_prefer_remote_codec_order(invite->
session->
inv_session->neg, PJ_FALSE);
4120 #ifdef PJMEDIA_SDP_NEG_ANSWER_MULTIPLE_CODECS
4122 pjmedia_sdp_neg_set_answer_multiple_codecs(invite->
session->
inv_session->neg, PJ_TRUE);
4126 handle_incoming_request(invite->
session, invite->
rdata);
4129 SCOPE_EXIT_RTN_VALUE(0,
"%s\n", ast_sip_session_get_name(invite->
session));
4132 static void handle_new_invite_request(pjsip_rx_data *rdata)
4135 ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
4136 pjsip_inv_session *inv_session = NULL;
4139 char *req_uri = TRACE_ATLEAST(1) ?
ast_alloca(256) :
"";
4140 int res = TRACE_ATLEAST(1) ? pjsip_uri_print(PJSIP_URI_IN_REQ_URI, rdata->msg_info.msg->line.req.uri, req_uri, 256) : 0;
4141 SCOPE_ENTER(1,
"Request: %s\n", res ? req_uri :
"");
4143 ast_assert(endpoint != NULL);
4145 inv_session = pre_session_setup(rdata, endpoint);
4148 SCOPE_EXIT_RTN(
"Failure in pre session setup\n");
4174 session = ast_sip_session_alloc(endpoint, NULL, inv_session, rdata);
4177 if (!new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE)) {
4179 pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
4181 SCOPE_EXIT_RTN(
"Couldn't create session\n");
4205 pjsip_dlg_dec_lock(inv_session->dlg);
4207 SCOPE_EXIT(
"Request: %s Session: %s\n", req_uri, ast_sip_session_get_name(session));
4211 static pj_bool_t does_method_match(
const pj_str_t *message_method,
const char *supplement_method)
4215 if (ast_strlen_zero(supplement_method)) {
4219 pj_cstr(&method, supplement_method);
4221 return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
4224 static pj_bool_t has_supplement(
const struct ast_sip_session *session,
const pjsip_rx_data *rdata)
4227 struct pjsip_method *method = &rdata->msg_info.msg->line.req.
method;
4234 if (does_method_match(&method->name, supplement->
method)) {
4245 static void session_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e)
4248 pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx);
4249 pjsip_inv_session *inv_session = (dlg ? pjsip_dlg_get_inv_session(dlg) : NULL);
4250 struct ast_sip_session *session = (inv_session ? inv_session->mod_data[session_module.id] : NULL);
4251 SCOPE_ENTER(1,
"%s TSX State: %s Inv State: %s\n", ast_sip_session_get_name(session),
4252 pjsip_tsx_state_str(tsx->state), inv_session ? pjsip_inv_state_name(inv_session->state) :
"unknown");
4255 ast_trace(2,
"Topology: Pending: %s Active: %s\n",
4267 static pj_bool_t session_on_rx_response(pjsip_rx_data *rdata)
4270 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
4271 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
4272 pjsip_inv_session *inv_session = dlg ? pjsip_dlg_get_inv_session(dlg) : NULL;
4273 struct ast_sip_session *session = (inv_session ? inv_session->mod_data[session_module.id] : NULL);
4274 SCOPE_ENTER(1,
"%s Method: %.*s Status: %d\n", ast_sip_session_get_name(session),
4275 (
int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
4277 SCOPE_EXIT_RTN_VALUE(PJ_FALSE);
4297 static pj_bool_t session_on_rx_request(pjsip_rx_data *rdata)
4299 pj_status_t handled = PJ_FALSE;
4300 struct pjsip_request_line req = rdata->msg_info.msg->line.req;
4301 pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
4302 pjsip_inv_session *inv_session = (dlg ? pjsip_dlg_get_inv_session(dlg) : NULL);
4303 struct ast_sip_session *session = (inv_session ? inv_session->mod_data[session_module.id] : NULL);
4304 char *req_uri = TRACE_ATLEAST(1) ?
ast_alloca(256) :
"";
4305 int res = TRACE_ATLEAST(1) ? pjsip_uri_print(PJSIP_URI_IN_REQ_URI, rdata->msg_info.msg->line.req.uri, req_uri, 256) : 0;
4306 SCOPE_ENTER(1,
"%s Request: %.*s %s\n", ast_sip_session_get_name(session),
4307 (
int) pj_strlen(&req.method.name), pj_strbuf(&req.method.name), res ? req_uri :
"");
4309 switch (req.method.id) {
4310 case PJSIP_INVITE_METHOD:
4312 ast_log(LOG_WARNING,
"on_rx_request called for INVITE in mid-dialog?\n");
4316 handle_new_invite_request(rdata);
4320 handled = dlg && (inv_session = pjsip_dlg_get_inv_session(dlg)) &&
4321 has_supplement(inv_session->mod_data[session_module.id], rdata);
4325 SCOPE_EXIT_RTN_VALUE(handled,
"%s Handled request %.*s %s ? %s\n", ast_sip_session_get_name(session),
4326 (
int) pj_strlen(&req.method.name), pj_strbuf(&req.method.name), req_uri,
4327 handled == PJ_TRUE ?
"yes" :
"no");
4331 static pj_bool_t session_on_tx_response(pjsip_tx_data *tdata)
4333 pjsip_dialog *dlg = pjsip_tdata_get_dlg(tdata);
4336 handle_outgoing_response(session, tdata);
4342 static void resend_reinvite(pj_timer_heap_t *timer, pj_timer_entry *entry)
4346 ast_debug(3,
"%s: re-INVITE collision timer expired.\n",
4347 ast_sip_session_get_name(session));
4363 static void reschedule_reinvite(
struct ast_sip_session *session, ast_sip_session_response_cb on_response)
4369 const char *session_name = ast_sip_session_get_name(session);
4370 int use_pending = 0;
4373 SCOPE_ENTER(3,
"%s\n", session_name);
4398 if (!pending_media_state) {
4399 SCOPE_EXIT_LOG_RTN(LOG_ERROR,
"%s: Failed to clone pending media state\n", session_name);
4405 if (!active_media_state) {
4406 ast_sip_session_media_state_free(pending_media_state);
4407 SCOPE_EXIT_LOG_RTN(LOG_ERROR,
"%s: Failed to clone active media state\n", session_name);
4411 if (delay_request(session, NULL, NULL, on_response, 1, DELAYED_METHOD_INVITE, pending_media_state,
4412 active_media_state, 1)) {
4413 ast_sip_session_media_state_free(pending_media_state);
4414 ast_sip_session_media_state_free(active_media_state);
4415 SCOPE_EXIT_LOG_RTN(LOG_ERROR,
"%s: Failed to add delayed request\n", session_name);
4420 SCOPE_EXIT_LOG_RTN(LOG_ERROR,
"%s: re-INVITE collision while timer running!!!\n", session_name);
4424 if (inv->role == PJSIP_ROLE_UAC) {
4425 tv.msec = 2100 + ast_random() % 2000;
4427 tv.msec = ast_random() % 2000;
4432 if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(),
4435 SCOPE_EXIT_LOG_RTN(LOG_ERROR,
"%s: Couldn't schedule timer\n", session_name);
4441 static void __print_debug_details(
const char *
function, pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
4443 int id = session_module.id;
4446 if (!DEBUG_ATLEAST(5)) {
4451 ast_log(LOG_DEBUG,
"Function %s called on event %s\n",
4452 function, pjsip_event_str(e->type));
4454 ast_log(LOG_DEBUG,
"Transaction %p does not belong to an inv_session?\n", tsx);
4455 ast_log(LOG_DEBUG,
"The transaction state is %s\n",
4456 pjsip_tsx_state_str(tsx->state));
4460 session = inv->mod_data[session_module.id];
4463 ast_log(LOG_DEBUG,
"inv_session %p has no ast session\n", inv);
4465 ast_log(LOG_DEBUG,
"The state change pertains to the endpoint '%s(%s)'\n",
4469 if (inv->invite_tsx) {
4470 ast_log(LOG_DEBUG,
"The inv session still has an invite_tsx (%p)\n",
4473 ast_log(LOG_DEBUG,
"The inv session does NOT have an invite_tsx\n");
4476 ast_log(LOG_DEBUG,
"The %s %.*s transaction involved in this state change is %p\n",
4477 pjsip_role_name(tsx->role),
4478 (
int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name),
4480 ast_log(LOG_DEBUG,
"The current transaction state is %s\n",
4481 pjsip_tsx_state_str(tsx->state));
4482 ast_log(LOG_DEBUG,
"The transaction state change event is %s\n",
4483 pjsip_event_str(e->body.tsx_state.type));
4485 ast_log(LOG_DEBUG,
"There is no transaction involved in this state change\n");
4487 ast_log(LOG_DEBUG,
"The current inv state is %s\n", pjsip_inv_state_name(inv->state));
4490 #define print_debug_details(inv, tsx, e) __print_debug_details(__PRETTY_FUNCTION__, (inv), (tsx), (e))
4492 static void handle_incoming_request(
struct ast_sip_session *session, pjsip_rx_data *rdata)
4495 struct pjsip_request_line req = rdata->msg_info.msg->line.req;
4496 SCOPE_ENTER(3,
"%s: Method is %.*s\n", ast_sip_session_get_name(session), (
int) pj_strlen(&req.method.name), pj_strbuf(&req.method.name));
4506 SCOPE_EXIT(
"%s\n", ast_sip_session_get_name(session));
4543 static void handle_incoming_response(
struct ast_sip_session *session, pjsip_rx_data *rdata,
4547 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
4548 SCOPE_ENTER(3,
"%s: Response is %d %.*s\n", ast_sip_session_get_name(session),
4549 status.code, (
int) pj_strlen(&status.reason), pj_strbuf(&status.reason));
4555 if (supplement->
incoming_response && does_method_match(&rdata->msg_info.cseq->method.name, supplement->
method)) {
4560 SCOPE_EXIT(
"%s\n", ast_sip_session_get_name(session));
4563 static int handle_incoming(
struct ast_sip_session *session, pjsip_rx_data *rdata,
4564 enum ast_sip_session_response_priority response_priority)
4566 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
4567 handle_incoming_request(session, rdata);
4569 handle_incoming_response(session, rdata, response_priority);
4575 static void handle_outgoing_request(
struct ast_sip_session *session, pjsip_tx_data *tdata)
4578 struct pjsip_request_line req = tdata->msg->line.req;
4579 SCOPE_ENTER(3,
"%s: Method is %.*s\n", ast_sip_session_get_name(session),
4580 (
int) pj_strlen(&req.method.name), pj_strbuf(&req.method.name));
4589 SCOPE_EXIT(
"%s\n", ast_sip_session_get_name(session));
4592 static void handle_outgoing_response(
struct ast_sip_session *session, pjsip_tx_data *tdata)
4595 struct pjsip_status_line status = tdata->msg->line.status;
4596 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
4597 SCOPE_ENTER(3,
"%s: Method is %.*s, Response is %d %.*s\n", ast_sip_session_get_name(session),
4598 (
int) pj_strlen(&cseq->method.name),
4599 pj_strbuf(&cseq->method.name), status.code, (
int) pj_strlen(&status.reason),
4600 pj_strbuf(&status.reason));
4604 SCOPE_EXIT_LOG_RTN(LOG_ERROR,
"%s: Cannot send response due to missing sequence header",
4605 ast_sip_session_get_name(session));
4616 SCOPE_EXIT(
"%s\n", ast_sip_session_get_name(session));
4619 static int session_end(
void *vsession)
4624 sip_session_defer_termination_stop_timer(session);
4627 handle_session_end(session);
4642 static int session_end_completion(
void *vsession)
4650 ao2_cleanup(session);
4654 static int check_request_status(pjsip_inv_session *inv, pjsip_event *e)
4657 pjsip_transaction *tsx = e->body.tsx_state.tsx;
4659 if (tsx->status_code != 503 && tsx->status_code != 408) {
4663 if (!ast_sip_failover_request(tsx->last_tx)) {
4667 pjsip_inv_uac_restart(inv, PJ_FALSE);
4672 pjsip_tx_data_add_ref(tsx->last_tx);
4673 ast_sip_session_send_request(session, tsx->last_tx);
4677 static void handle_incoming_before_media(pjsip_inv_session *inv,
4681 ast_debug(3,
"%s: Received %s\n", ast_sip_session_get_name(session), rdata->msg_info.msg->type == PJSIP_REQUEST_MSG ?
4682 "request" :
"response");
4685 handle_incoming(session, rdata, AST_SIP_SESSION_BEFORE_MEDIA);
4686 msg = rdata->msg_info.msg;
4687 if (msg->type == PJSIP_REQUEST_MSG
4688 && msg->line.req.method.id == PJSIP_ACK_METHOD
4689 && pjmedia_sdp_neg_get_state(inv->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
4690 pjsip_tx_data *tdata;
4699 "%s: Ending session due to incomplete SDP negotiation. %s\n",
4700 ast_sip_session_get_name(session),
4701 pjsip_rx_data_get_info(rdata));
4702 if (pjsip_inv_end_session(inv, 400, NULL, &tdata) == PJ_SUCCESS
4704 ast_sip_session_send_request(session, tdata);
4709 static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
4711 pjsip_event_id_e type;
4713 SCOPE_ENTER(1,
"%s Event: %s Inv State: %s\n", ast_sip_session_get_name(session),
4714 pjsip_event_str(e->type), pjsip_inv_state_name(inv->state));
4717 SCOPE_EXIT_RTN(
"Shutting down\n");
4721 print_debug_details(inv, NULL, e);
4724 type = PJSIP_EVENT_UNKNOWN;
4727 session = inv->mod_data[session_module.id];
4729 SCOPE_EXIT_RTN(
"No session\n");
4733 case PJSIP_EVENT_TX_MSG:
4735 case PJSIP_EVENT_RX_MSG:
4736 handle_incoming_before_media(inv, session, e->body.rx_msg.rdata);
4738 case PJSIP_EVENT_TSX_STATE:
4739 ast_debug(3,
"%s: Source of transaction state change is %s\n", ast_sip_session_get_name(session),
4740 pjsip_event_str(e->body.tsx_state.type));
4742 switch(e->body.tsx_state.type) {
4743 case PJSIP_EVENT_TX_MSG:
4745 case PJSIP_EVENT_RX_MSG:
4746 if (!check_request_status(inv, e)) {
4747 handle_incoming_before_media(inv, session, e->body.tsx_state.src.rdata);
4750 case PJSIP_EVENT_TRANSPORT_ERROR:
4751 case PJSIP_EVENT_TIMER:
4757 check_request_status(inv, e);
4759 case PJSIP_EVENT_USER:
4760 case PJSIP_EVENT_UNKNOWN:
4761 case PJSIP_EVENT_TSX_STATE:
4766 case PJSIP_EVENT_TRANSPORT_ERROR:
4767 case PJSIP_EVENT_TIMER:
4768 case PJSIP_EVENT_UNKNOWN:
4769 case PJSIP_EVENT_USER:
4774 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
4776 ast_debug(3,
"%s: Deferring session end\n", ast_sip_session_get_name(session));
4778 SCOPE_EXIT_RTN(
"Deferring\n");
4783 session_end(session);
4790 static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
4795 static int session_end_if_disconnected(
int id, pjsip_inv_session *inv)
4799 if (inv->state != PJSIP_INV_STATE_DISCONNECTED) {
4807 pjsip_dlg_inc_lock(inv->dlg);
4808 session = inv->mod_data[
id];
4809 inv->mod_data[
id] = NULL;
4810 pjsip_dlg_dec_lock(inv->dlg);
4819 session_end_completion(session);
4825 static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
4827 ast_sip_session_response_cb cb;
4828 int id = session_module.id;
4829 pjsip_tx_data *tdata;
4831 SCOPE_ENTER(1,
"%s TSX State: %s Inv State: %s\n", ast_sip_session_get_name(session),
4832 pjsip_tsx_state_str(tsx->state), pjsip_inv_state_name(inv->state));
4835 SCOPE_EXIT_RTN(
"Shutting down\n");
4838 session = inv->mod_data[
id];
4840 print_debug_details(inv, tsx, e);
4843 SCOPE_EXIT_RTN(
"Session ended\n");
4852 if (tsx->method.id != PJSIP_BYE_METHOD && session_end_if_disconnected(
id, inv)) {
4853 SCOPE_EXIT_RTN(
"Disconnected\n");
4856 switch (e->body.tsx_state.type) {
4857 case PJSIP_EVENT_TX_MSG:
4863 tsx->mod_data[
id] = e->body.tsx_state.src.tdata->mod_data[
id];
4865 case PJSIP_EVENT_RX_MSG:
4866 cb = ast_sip_mod_data_get(tsx->mod_data,
id, MOD_DATA_ON_RESPONSE);
4872 if ((e->body.tsx_state.src.rdata->msg_info.msg->type != PJSIP_REQUEST_MSG) ||
4873 (tsx->method.id != PJSIP_BYE_METHOD)) {
4874 handle_incoming(session, e->body.tsx_state.src.rdata,
4875 AST_SIP_SESSION_AFTER_MEDIA);
4877 if (tsx->method.id == PJSIP_INVITE_METHOD) {
4878 if (tsx->role == PJSIP_ROLE_UAC) {
4879 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
4881 if (tsx->status_code == PJSIP_SC_REQUEST_PENDING) {
4882 reschedule_reinvite(session, cb);
4883 SCOPE_EXIT_RTN(
"Non 2XX final response\n");
4885 if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
4886 ast_debug(1,
"%s: reINVITE received final response code %d\n",
4887 ast_sip_session_get_name(session),
4889 if ((tsx->status_code == 401 || tsx->status_code == 407
4892 && !ast_sip_create_request_with_auth(
4894 e->body.tsx_state.src.rdata, tsx->last_tx, &tdata)) {
4896 ast_sip_session_send_request_with_cb(session, tdata, cb);
4897 SCOPE_EXIT_RTN(
"Sending authed reinvite\n");
4903 if (tsx->status_code == 481 || tsx->status_code == 408) {
4904 if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS
4906 ast_sip_session_send_request(session, tdata);
4910 }
else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
4911 if (!inv->cancelling
4912 && inv->role == PJSIP_ROLE_UAC
4913 && inv->state == PJSIP_INV_STATE_CONFIRMED
4914 && pjmedia_sdp_neg_was_answer_remote(inv->neg)
4915 && pjmedia_sdp_neg_get_state(inv->neg) == PJMEDIA_SDP_NEG_STATE_DONE
4916 && (session->
channel && ast_channel_hangupcause(session->
channel) == AST_CAUSE_BEARERCAPABILITY_NOTAVAIL)
4925 ast_debug(1,
"Endpoint '%s(%s)': Ending session due to 200 OK with incomplete SDP negotiation. %s\n",
4928 pjsip_rx_data_get_info(e->body.tsx_state.src.rdata));
4929 pjsip_inv_end_session(session->
inv_session, 503, NULL, &tdata);
4930 SCOPE_EXIT_RTN(
"Incomplete SDP negotiation\n");
4933 if (inv->cancelling && tsx->status_code == PJSIP_SC_OK) {
4934 int sdp_negotiation_done =
4935 pjmedia_sdp_neg_get_state(inv->neg) == PJMEDIA_SDP_NEG_STATE_DONE;
4959 pjsip_rx_data_get_info(e->body.tsx_state.src.rdata),
4960 sdp_negotiation_done ?
"complete" :
"incomplete");
4961 if (!sdp_negotiation_done) {
4962 ast_debug(1,
"%s: Incomplete SDP negotiation cancelled session. %s\n",
4963 ast_sip_session_get_name(session),
4964 pjsip_rx_data_get_info(e->body.tsx_state.src.rdata));
4965 }
else if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS
4967 ast_debug(1,
"%s: Ending session due to RFC5407 race condition. %s\n",
4968 ast_sip_session_get_name(session),
4969 pjsip_rx_data_get_info(e->body.tsx_state.src.rdata));
4970 ast_sip_session_send_request(session, tdata);
4977 if (tsx->role == PJSIP_ROLE_UAC) {
4978 if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
4980 ast_debug(1,
"%s: %.*s received final response code %d\n",
4981 ast_sip_session_get_name(session),
4982 (
int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name),
4984 if ((tsx->status_code == 401 || tsx->status_code == 407 || tsx->status_code == 494)
4986 && !ast_sip_create_request_with_auth(
4988 e->body.tsx_state.src.rdata, tsx->last_tx, &tdata)) {
4990 ast_sip_session_send_request_with_cb(session, tdata, cb);
4991 SCOPE_EXIT_RTN(
"Sending authed %.*s\n",
4992 (
int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name));
4998 cb(session, e->body.tsx_state.src.rdata);
5001 case PJSIP_EVENT_TRANSPORT_ERROR:
5002 case PJSIP_EVENT_TIMER:
5007 if (session_end_if_disconnected(
id, inv)) {
5008 SCOPE_EXIT_RTN(
"Disconnected\n");
5011 case PJSIP_EVENT_USER:
5012 case PJSIP_EVENT_UNKNOWN:
5013 case PJSIP_EVENT_TSX_STATE:
5020 SCOPE_EXIT_RTN(
"Nothing delayed\n");
5023 if (tsx->method.id == PJSIP_INVITE_METHOD) {
5024 if (tsx->state == PJSIP_TSX_STATE_PROCEEDING) {
5025 ast_debug(3,
"%s: INVITE delay check. tsx-state:%s\n",
5026 ast_sip_session_get_name(session),
5027 pjsip_tsx_state_str(tsx->state));
5028 check_delayed_requests(session, invite_proceeding);
5029 }
else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
5035 ast_debug(3,
"%s: INVITE delay check. tsx-state:%s\n",
5036 ast_sip_session_get_name(session),
5037 pjsip_tsx_state_str(tsx->state));
5038 check_delayed_requests(session, invite_terminated);
5040 }
else if (tsx->role == PJSIP_ROLE_UAC
5041 && tsx->state == PJSIP_TSX_STATE_COMPLETED
5042 && !pj_strcmp2(&tsx->method.name,
"UPDATE")) {
5043 ast_debug(3,
"%s: UPDATE delay check. tsx-state:%s\n",
5044 ast_sip_session_get_name(session),
5045 pjsip_tsx_state_str(tsx->state));
5046 check_delayed_requests(session, update_completed);
5054 const struct pjmedia_sdp_session *remote,
5060 SCOPE_ENTER(1,
"%s Stream: %s\n", ast_sip_session_get_name(session),
5067 SCOPE_EXIT_RTN_VALUE(-1,
"Coudn't create sdp stream\n");
5069 SCOPE_EXIT_RTN_VALUE(0,
"Had handler\n");
5073 if (!handler_list) {
5074 SCOPE_EXIT_RTN_VALUE(0,
"No handlers\n");
5079 if (handler == session_media->
handler) {
5085 SCOPE_EXIT_RTN_VALUE(-1,
"Coudn't create sdp stream\n");
5089 session_media_set_handler(session_media, handler);
5090 SCOPE_EXIT_RTN_VALUE(0,
"Handled\n");
5095 SCOPE_EXIT_RTN_VALUE(0,
"Not handled\n");
5101 char *mids[PJMEDIA_MAX_SDP_MEDIA];
5106 static int add_bundle_groups(
struct ast_sip_session *session, pj_pool_t *
pool, pjmedia_sdp_session *answer)
5109 pjmedia_sdp_attr *attr;
5115 attr = pjmedia_sdp_attr_create(pool,
"msid-semantic", pj_cstr(&stmp,
"WMS *"));
5116 pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr);
5123 memset(bundle_groups, 0,
sizeof(bundle_groups));
5134 bundle_group = &bundle_groups[session_media->
bundle_group];
5137 if (!bundle_group->
mids[0]) {
5138 bundle_group->
mids[0] = session_media->
mid;
5148 for (mid_id = 1; mid_id < PJMEDIA_MAX_SDP_MEDIA; ++mid_id) {
5149 if (!bundle_group->
mids[mid_id]) {
5150 bundle_group->
mids[mid_id] = session_media->
mid;
5153 }
else if (!strcmp(bundle_group->
mids[mid_id], session_media->
mid)) {
5160 for (index = 0; index < PJMEDIA_MAX_SDP_MEDIA; ++index) {
5161 bundle_group = &bundle_groups[index];
5168 pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr);
5176 static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv,
struct ast_sip_session *session,
const pjmedia_sdp_session *offer,
const unsigned int ignore_active_stream_topology)
5178 static const pj_str_t STR_IN = {
"IN", 2 };
5179 static const pj_str_t STR_IP4 = {
"IP4", 3 };
5180 static const pj_str_t STR_IP6 = {
"IP6", 3 };
5181 pjmedia_sdp_session *local;
5184 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
5186 if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
5187 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
"%s: Failed to create session SDP. Session has been already disconnected\n",
5188 ast_sip_session_get_name(session));
5191 if (!inv->pool_prov || !(local = PJ_POOL_ZALLOC_T(inv->pool_prov, pjmedia_sdp_session))) {
5192 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
"%s: Pool allocation failure\n", ast_sip_session_get_name(session));
5196 local->origin.version = local->origin.id = (pj_uint32_t)(ast_random());
5198 local->origin.version = offer->origin.version + 1;
5199 local->origin.id = offer->origin.id;
5211 ast_trace(-1,
"no information about stream topology received\n");
5214 ast_trace(-1,
"using existing topology\n");
5217 if (ignore_active_stream_topology) {
5218 ast_trace(-1,
"fall back to endpoint configuration - ignore active stream topolog\n");
5220 ast_trace(-1,
"fall back to endpoint configuration\n");
5225 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
"%s: No pending media state topology\n", ast_sip_session_get_name(session));
5229 ast_trace(-1,
"%s: Processing streams\n", ast_sip_session_get_name(session));
5234 unsigned int streams = local->media_count;
5235 SCOPE_ENTER(4,
"%s: Processing stream %s\n", ast_sip_session_get_name(session),
5243 if (!session_media) {
5245 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't alloc/add session media for stream %s\n",
5249 if (add_sdp_streams(session_media, session, local, offer, stream)) {
5251 SCOPE_EXIT_LOG_EXPR(
goto end, LOG_ERROR,
"%s: Couldn't add sdp streams for stream %s\n",
5256 if (streams != local->media_count) {
5257 pjmedia_sdp_media *media = local->media[streams];
5259 pjmedia_sdp_attr *attr;
5262 if (!ast_strlen_zero(session_media->
mid)) {
5263 attr = pjmedia_sdp_attr_create(inv->pool_prov,
"mid", pj_cstr(&stmp, session_media->
mid));
5264 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
5267 ast_trace(-1,
"%s: Stream %s added%s%s\n", ast_sip_session_get_name(session),
5269 S_COR(!ast_strlen_zero(session_media->
mid),
" with mid ",
""),
S_OR(session_media->
mid,
""));
5274 if (local->media_count == PJMEDIA_MAX_SDP_MEDIA) {
5275 SCOPE_EXIT_EXPR(
break,
"%s: Stream %s exceeded max pjmedia count of %d\n",
5277 PJMEDIA_MAX_SDP_MEDIA);
5280 SCOPE_EXIT(
"%s: Done with %s\n", ast_sip_session_get_name(session),
5286 ast_trace(-1,
"%s: Adding bundle groups (if available)\n", ast_sip_session_get_name(session));
5287 if (add_bundle_groups(session, inv->pool_prov, local)) {
5288 SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR,
"%s: Couldn't add bundle groups\n", ast_sip_session_get_name(session));
5292 ast_trace(-1,
"%s: Copying connection details\n", ast_sip_session_get_name(session));
5294 for (stream = 0; stream < local->media_count; stream++) {
5295 SCOPE_ENTER(4,
"%s: Processing media %d\n", ast_sip_session_get_name(session), stream);
5296 if (!local->media[stream]->conn) {
5297 SCOPE_EXIT_EXPR(
continue,
"%s: Media %d has no connection info\n", ast_sip_session_get_name(session), stream);
5301 if (!pj_strcmp(&local->conn->net_type, &local->media[stream]->conn->net_type) &&
5302 !pj_strcmp(&local->conn->addr_type, &local->media[stream]->conn->addr_type) &&
5303 !pj_strcmp(&local->conn->addr, &local->media[stream]->conn->addr)) {
5304 local->media[stream]->conn = NULL;
5306 SCOPE_EXIT_EXPR(
continue,
"%s: Media %d has good existing connection info\n", ast_sip_session_get_name(session), stream);
5310 local->conn = local->media[stream]->conn;
5311 local->media[stream]->conn = NULL;
5313 SCOPE_EXIT_EXPR(
continue,
"%s: Media %d reset\n", ast_sip_session_get_name(session), stream);
5318 ast_trace(-1,
"%s: Creating connection details\n", ast_sip_session_get_name(session));
5320 local->conn = pj_pool_zalloc(inv->pool_prov,
sizeof(
struct pjmedia_sdp_conn));
5321 local->conn->net_type = STR_IN;
5327 pj_strdup2(inv->pool_prov, &local->conn->addr, ast_sip_get_host_ip_string(session->
endpoint->
media.
rtp.
ipv6 ? pj_AF_INET6() : pj_AF_INET()));
5331 pj_strassign(&local->origin.net_type, &local->conn->net_type);
5332 pj_strassign(&local->origin.addr_type, &local->conn->addr_type);
5333 pj_strassign(&local->origin.addr, &local->conn->addr);
5336 SCOPE_EXIT_RTN_VALUE(local,
"%s\n", ast_sip_session_get_name(session));
5339 static void session_inv_on_rx_offer(pjsip_inv_session *inv,
const pjmedia_sdp_session *offer)
5342 pjmedia_sdp_session *answer;
5343 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
5346 SCOPE_EXIT_RTN(
"%s: Shutdown in progress\n", ast_sip_session_get_name(session));
5349 session = inv->mod_data[session_module.id];
5350 if (handle_incoming_sdp(session, offer)) {
5352 SCOPE_EXIT_RTN(
"%s: handle_incoming_sdp failed\n", ast_sip_session_get_name(session));
5355 if ((answer = create_local_sdp(inv, session, offer, 0))) {
5356 pjsip_inv_set_sdp_answer(inv, answer);
5357 SCOPE_EXIT_RTN(
"%s: Set SDP answer\n", ast_sip_session_get_name(session));
5359 SCOPE_EXIT_RTN(
"%s: create_local_sdp failed\n", ast_sip_session_get_name(session));
5362 static void session_inv_on_create_offer(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
5365 const pjmedia_sdp_session *previous_sdp = NULL;
5366 pjmedia_sdp_session *offer;
5368 unsigned int ignore_active_stream_topology = 0;
5376 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
5378 SCOPE_EXIT_RTN(
"%s: No channel\n", ast_sip_session_get_name(session));
5388 if (inv->invite_tsx && inv->state == PJSIP_INV_STATE_CONFIRMED
5389 && inv->invite_tsx->method.id == PJSIP_INVITE_METHOD) {
5390 ast_trace(-1,
"re-INVITE\n");
5391 if (inv->invite_tsx->role == PJSIP_ROLE_UAS
5392 && ast_sip_get_all_codecs_on_empty_reinvite()) {
5393 ast_trace(-1,
"UAS role, include all codecs in the answer on empty SDP\n");
5394 ignore_active_stream_topology = 1;
5399 if (pjmedia_sdp_neg_was_answer_remote(inv->neg)) {
5400 pjmedia_sdp_neg_get_active_remote(inv->neg, &previous_sdp);
5402 pjmedia_sdp_neg_get_active_local(inv->neg, &previous_sdp);
5406 if (ignore_active_stream_topology) {
5407 offer = create_local_sdp(inv, session, NULL, 1);
5409 offer = create_local_sdp(inv, session, previous_sdp, 0);
5412 SCOPE_EXIT_RTN(
"%s: create offer failed\n", ast_sip_session_get_name(session));
5437 for (i = 0; i < offer->media_count; ++i) {
5438 pjmedia_sdp_media *m = offer->media[i];
5439 pjmedia_sdp_attr *recvonly;
5440 pjmedia_sdp_attr *inactive;
5441 pjmedia_sdp_attr *sendonly;
5443 recvonly = pjmedia_sdp_attr_find2(m->attr_count, m->attr,
"recvonly", NULL);
5444 inactive = pjmedia_sdp_attr_find2(m->attr_count, m->attr,
"inactive", NULL);
5445 sendonly = pjmedia_sdp_attr_find2(m->attr_count, m->attr,
"sendonly", NULL);
5446 if (recvonly || inactive || sendonly) {
5447 pjmedia_sdp_attr *to_remove = recvonly ?: inactive ?: sendonly;
5448 pjmedia_sdp_attr *sendrecv;
5450 pjmedia_sdp_attr_remove(&m->attr_count, m->attr, to_remove);
5452 sendrecv = pjmedia_sdp_attr_create(session->
inv_session->pool,
"sendrecv", NULL);
5453 pjmedia_sdp_media_add_attr(m, sendrecv);
5458 SCOPE_EXIT_RTN(
"%s: offer created\n", ast_sip_session_get_name(session));
5461 static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status)
5464 const pjmedia_sdp_session *local, *remote;
5465 SCOPE_ENTER(3,
"%s\n", ast_sip_session_get_name(session));
5468 SCOPE_EXIT_RTN(
"%s: Shutdown in progress\n", ast_sip_session_get_name(session));
5471 session = inv->mod_data[session_module.id];
5472 if (!session || !session->
channel) {
5478 SCOPE_EXIT_RTN(
"%s: No channel or session\n", ast_sip_session_get_name(session));
5494 if (inv->following_fork) {
5496 ast_trace(-1,
"%s: Following early media fork with different To tags\n", ast_sip_session_get_name(session));
5498 ast_trace(-1,
"%s: Not following early media fork with different To tags\n", ast_sip_session_get_name(session));
5502 #ifdef HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
5503 else if (inv->updated_sdp_answer) {
5505 ast_trace(-1,
"%s: Accepting updated SDP with same To tag\n", ast_sip_session_get_name(session));
5507 ast_trace(-1,
"%s: Ignoring updated SDP answer with same To tag\n", ast_sip_session_get_name(session));
5513 SCOPE_EXIT_RTN(
"%s: Bailing\n", ast_sip_session_get_name(session));
5517 if ((status != PJ_SUCCESS) || (pjmedia_sdp_neg_get_active_local(inv->neg, &local) != PJ_SUCCESS) ||
5518 (pjmedia_sdp_neg_get_active_remote(inv->neg, &remote) != PJ_SUCCESS)) {
5519 ast_channel_hangupcause_set(session->
channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
5522 SCOPE_EXIT_RTN(
"%s: Couldn't get active or local or remote negotiator. Hanging up\n", ast_sip_session_get_name(session));
5525 if (handle_negotiated_sdp(session, local, remote)) {
5527 SCOPE_EXIT_RTN(
"%s: handle_negotiated_sdp failed. Resetting pending media state\n", ast_sip_session_get_name(session));
5529 SCOPE_EXIT_RTN(
"%s\n", ast_sip_session_get_name(session));
5532 static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv,
const pjsip_uri *target,
const pjsip_event *e)
5535 const pjsip_sip_uri *uri;
5538 return PJSIP_REDIRECT_STOP;
5541 session = inv->mod_data[session_module.id];
5542 if (!session || !session->
channel) {
5543 return PJSIP_REDIRECT_STOP;
5547 return PJSIP_REDIRECT_ACCEPT;
5550 if (!PJSIP_URI_SCHEME_IS_SIP(target) && !PJSIP_URI_SCHEME_IS_SIPS(target)) {
5551 return PJSIP_REDIRECT_STOP;
5554 handle_incoming(session, e->body.rx_msg.rdata, AST_SIP_SESSION_BEFORE_REDIRECTING);
5556 uri = pjsip_uri_get_uri(target);
5561 ast_copy_pj_str(exten, &uri->user,
sizeof(exten));
5567 AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
5569 ast_channel_call_forward_set(session->
channel, exten);
5571 char target_uri[PJSIP_MAX_URL_SIZE];
5575 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, target_uri,
sizeof(target_uri));
5577 ast_channel_call_forward_set(session->
channel, forward);
5580 return PJSIP_REDIRECT_STOP;
5583 static pjsip_inv_callback inv_callback = {
5584 .on_state_changed = session_inv_on_state_changed,
5585 .on_new_session = session_inv_on_new_session,
5586 .on_tsx_state_changed = session_inv_on_tsx_state_changed,
5587 .on_rx_offer = session_inv_on_rx_offer,
5588 .on_create_offer = session_inv_on_create_offer,
5589 .on_media_update = session_inv_on_media_update,
5590 .on_redirected = session_inv_on_redirected,
5594 static void session_outgoing_nat_hook(pjsip_tx_data *tdata,
struct ast_sip_transport *transport)
5598 tdata->mod_data, session_module.id, MOD_DATA_NAT_HOOK);
5599 pjsip_sdp_info *sdp_info;
5600 pjmedia_sdp_session *sdp;
5601 pjsip_dialog *dlg = pjsip_tdata_get_dlg(tdata);
5609 if (ast_strlen_zero(transport->
external_media_address) || !transport_state || hook || !tdata->msg->body) {
5613 sdp_info = pjsip_get_sdp_info(tdata->pool, tdata->msg->body, NULL, &pjsip_media_type_application_sdp);
5614 if (sdp_info->sdp_err != PJ_SUCCESS || !sdp_info->sdp) {
5617 sdp = sdp_info->sdp;
5620 char host[NI_MAXHOST];
5623 ast_copy_pj_str(host, &sdp->conn->addr,
sizeof(host));
5630 if (ast_sip_transport_is_local(transport_state, &our_sdp_addr) || !transport_state->localnet) {
5631 ast_debug(5,
"%s: Setting external media address to %s\n", ast_sip_session_get_name(session),
5634 pj_strassign(&sdp->origin.addr, &sdp->conn->addr);
5638 for (stream = 0; stream < sdp->media_count; ++stream) {
5645 ast_copy_pj_str(media, &sdp->media[stream]->desc.media,
sizeof(media));
5647 handler_list = ao2_find(sdp_handlers, media,
OBJ_KEY);
5648 if (!handler_list) {
5649 ast_debug(4,
"%s: No registered SDP handlers for media type '%s'\n", ast_sip_session_get_name(session),
5661 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, session_module.id, MOD_DATA_NAT_HOOK, nat_hook);
5664 #ifdef TEST_FRAMEWORK
5686 stream = test_stream_alloc(name, type, state);
5698 if (!session_media) {
5707 strcpy(session_media->
label, name);
5720 return session_media;
5725 if (left == right) {
5736 return memcmp(left, right,
sizeof(*left)) == 0;
5740 int assert_on_failure)
5745 if (left == right) {
5746 SCOPE_EXIT_RTN_VALUE(1,
"equal\n");
5749 if (!(left && right)) {
5750 ast_assert(!assert_on_failure);
5751 SCOPE_EXIT_RTN_VALUE(0,
"one is null: left: %p right: %p\n", left, right);
5755 ast_assert(!assert_on_failure);
5756 SCOPE_EXIT_RTN_VALUE(0,
"topologies differ\n");
5759 ast_assert(!assert_on_failure);
5760 SCOPE_EXIT_RTN_VALUE(0,
"session vector sizes different: left %zu != right %zu\n",
5765 ast_assert(!assert_on_failure);
5766 SCOPE_EXIT_RTN_VALUE(0,
"read_callback vector sizes different: left %zu != right %zu\n",
5773 ast_assert(!assert_on_failure);
5774 SCOPE_EXIT_RTN_VALUE(0,
"Media session %d different\n", i);
5782 ast_assert(!assert_on_failure);
5783 SCOPE_EXIT_RTN_VALUE(0,
"read_callback %d different\n", i);
5787 for (i = 0; i < AST_MEDIA_TYPE_END; i++) {
5793 ast_assert(!assert_on_failure);
5794 SCOPE_EXIT_RTN_VALUE(0,
"Default media session %d different. Left: %s Right: %s\n", i,
5800 SCOPE_EXIT_RTN_VALUE(1,
"equal\n");
5805 #define FREE_STATE() \
5807 ast_sip_session_media_state_free(new_pending_state); \
5808 new_pending_state = NULL; \
5809 ast_sip_session_media_state_free(delayed_pending_state); \
5810 delayed_pending_state = NULL; \
5811 ast_sip_session_media_state_free(delayed_active_state); \
5812 delayed_active_state = NULL; \
5813 ast_sip_session_media_state_free(current_active_state); \
5814 current_active_state = NULL; \
5815 ast_sip_session_media_state_free(expected_pending_state); \
5816 expected_pending_state = NULL; \
5819 #define RESET_STATE(__num) \
5822 ast_trace(-1, "Test %d\n", testnum); \
5824 delayed_pending_state = ast_sip_session_media_state_alloc(); \
5825 delayed_pending_state->topology = ast_stream_topology_alloc(); \
5826 delayed_active_state = ast_sip_session_media_state_alloc(); \
5827 delayed_active_state->topology = ast_stream_topology_alloc(); \
5828 current_active_state = ast_sip_session_media_state_alloc(); \
5829 current_active_state->topology = ast_stream_topology_alloc(); \
5830 expected_pending_state = ast_sip_session_media_state_alloc(); \
5831 expected_pending_state->topology = ast_stream_topology_alloc(); \
5836 new_pending_state = resolve_refresh_media_states("unittest", delayed_pending_state, delayed_active_state, current_active_state, 1); \
5837 if (!test_is_media_state_equal(new_pending_state, expected_pending_state, 0)) { \
5838 res = AST_TEST_FAIL; \
5840 ast_test_status_update(test, "da: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(delayed_active_state->topology, &STR_TMP))); \
5841 ast_test_status_update(test, "dp: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(delayed_pending_state->topology, &STR_TMP))); \
5842 ast_test_status_update(test, "ca: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(current_active_state->topology, &STR_TMP))); \
5843 ast_test_status_update(test, "ep: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(expected_pending_state->topology, &STR_TMP))); \
5844 ast_test_status_update(test, "np: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(new_pending_state->topology, &STR_TMP))); \
5846 ast_test_status_update(test, "Test %d %s\n", testnum, test_failed ? "FAILED" : "passed"); \
5847 ast_trace(-1, "Test %d %s\n", testnum, test_failed ? "FAILED" : "passed"); \
5858 enum ast_test_result_state res = AST_TEST_PASS;
5859 int test_failed = 0;
5865 info->name =
"merge_refresh_topologies";
5866 info->category =
"/res/res_pjsip_session/";
5867 info->summary =
"Test merging of delayed request topologies";
5868 info->description =
"Test merging of delayed request topologies";
5869 SCOPE_EXIT_RTN_VALUE(AST_TEST_NOT_RUN);
6213 SCOPE_EXIT_RTN_VALUE(res);
6217 static int load_module(
void)
6219 pjsip_endpoint *endpt;
6221 if (!ast_sip_get_sorcery() || !ast_sip_get_pjsip_endpoint()) {
6230 SDP_HANDLER_BUCKETS, sdp_handler_list_hash, NULL, sdp_handler_list_cmp);
6231 if (!sdp_handlers) {
6234 endpt = ast_sip_get_pjsip_endpoint();
6235 pjsip_inv_usage_init(endpt, &inv_callback);
6236 pjsip_100rel_init_module(endpt);
6237 pjsip_timer_init_module(endpt);
6238 if (ast_sip_register_service(&session_module)) {
6241 ast_sip_register_service(&session_reinvite_module);
6242 ast_sip_register_service(&outbound_invite_auth_module);
6244 pjsip_reason_header_load();
6247 #ifdef TEST_FRAMEWORK
6248 AST_TEST_REGISTER(test_resolve_refresh_media_states);
6253 static int unload_module(
void)
6255 pjsip_reason_header_unload();
6257 #ifdef TEST_FRAMEWORK
6258 AST_TEST_UNREGISTER(test_resolve_refresh_media_states);
6260 ast_sip_unregister_service(&outbound_invite_auth_module);
6261 ast_sip_unregister_service(&session_reinvite_module);
6262 ast_sip_unregister_service(&session_module);
6264 ao2_cleanup(nat_hook);
6265 ao2_cleanup(sdp_handlers);
6269 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"PJSIP Session resource",
6270 .support_level = AST_MODULE_SUPPORT_CORE,
6271 .load = load_module,
6272 .unload = unload_module,
6274 .requires =
"res_pjsip",
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Information needed to identify an endpoint in a call.
struct ast_sip_endpoint * endpoint
const char * ast_stream_to_str(const struct ast_stream *stream, struct ast_str **buf)
Get a string representing the stream for debugging/display purposes.
enum ast_sip_dtmf_mode dtmf
ast_sip_session_sdp_creation_cb on_sdp_creation
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
Asterisk locking-related definitions:
unsigned int sess_expires
Asterisk main include file. File version handling, generic pbx functions.
const ast_string_field fromuser
void(* stream_destroy)(struct ast_sip_session_media *session_media)
Destroy a session_media created by this handler.
static char * ast_sockaddr_stringify_addr_remote(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
struct ast_sip_session_media_state * pending_media_state
struct ast_sip_session_media_state * pending_media_state
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
const ast_string_field transport
void ast_sip_dialog_set_serializer(pjsip_dialog *dlg, struct ast_taskprocessor *serializer)
Set a serializer on a SIP dialog so requests and responses are automatically serialized.
unsigned int defer_terminate
void(* session_destroy)(struct ast_sip_session *session)
Notification that the session is being destroyed.
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
unsigned int terminate_while_deferred
struct ao2_container * datastores
Convenient Signal Processing routines.
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
int(* incoming_request)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return...
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
struct ast_sip_session::@269 supplements
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
const ast_string_field external_media_address
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
unsigned int ended_while_deferred
void(* outgoing_response)(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Called on an outgoing SIP response This method is always called from a SIP servant thread...
struct ast_sip_session * session
Session created for the new INVITE.
A handler for SDPs in SIP sessions.
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
void ast_sip_dialog_set_endpoint(pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint)
Set an endpoint on a SIP dialog so in-dialog requests do not undergo endpoint lookup.
struct ast_sip_auth_vector outbound_auths
void * pvt
Pointer to channel specific implementation information, must be ao2 object.
Universally unique identifier support.
enum ast_media_type ast_media_type_from_str(const char *media_type_str)
Conversion function to take a media string and convert it to a media type.
Set when the stream has been removed/declined.
ast_sip_session_request_creation_cb on_request_creation
const ast_string_field context
Structure for a data store type.
void(* change_outgoing_sdp_stream_media_address)(struct pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
Update media stream with external address if applicable.
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
int ast_stream_get_format_count(const struct ast_stream *stream)
Get the count of the current negotiated formats of a stream.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Set when the stream is not sending OR receiving media.
enum delayed_method method
void ast_party_id_free(struct ast_party_id *doomed)
Destroy the party id contents.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
ast_stream_state
States that a stream may be in.
static void stream_destroy(struct ast_sip_session_media *session_media)
Function which destroys the RTP instance when session ends.
char exten[AST_MAX_EXTENSION]
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
struct pjsip_inv_session * inv_session
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Socket address structure.
int ast_stream_topology_set_stream(struct ast_stream_topology *topology, unsigned int position, struct ast_stream *stream)
Set a specific position in a topology.
A structure describing a SIP session.
void(* outgoing_request)(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
Called on an outgoing SIP request This method is always called from a SIP servant thread...
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_format_cap * direct_media_cap
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
enum ast_sip_session_response_priority response_priority
int(* negotiate_incoming_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, int index, struct ast_stream *asterisk_stream)
Set session details based on a stream in an incoming SDP offer or answer.
struct ast_sip_session_media_state * active_media_state
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
char name[0]
Name for the stream within the context of the channel it is on.
struct ast_sip_session::@271 media_stats
struct ast_sip_endpoint_media_configuration media
Asterisk datastore objects.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
int ast_taskprocessor_suspend(struct ast_taskprocessor *tps)
Indicate the taskprocessor is suspended.
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
pjsip_rx_data * deferred_reinvite
Structure for SIP nat hook information.
const char * ast_stream_topology_to_str(const struct ast_stream_topology *topology, struct ast_str **buf)
Get a string representing the topology for debugging/display purposes.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Structure for SIP transport information.
struct ast_sip_session_media_state * active_media_state
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
void(* outgoing_external_message)(struct pjsip_tx_data *tdata, struct ast_sip_transport *transport)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
enum ast_media_type type
The type of media the stream is handling.
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
SRTP and SDP Security descriptions.
pjsip_rx_data * rdata
INVITE request itself.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Access Control of various sorts.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
pj_timer_entry rescheduled_reinvite
const struct ast_datastore_info * info
void(* destroy)(void *data)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct ast_channel * channel
void(* incoming_response)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on an incoming SIP response This method is always called from a SIP servant thread...
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
int ast_taskprocessor_unsuspend(struct ast_taskprocessor *tps)
Indicate the taskprocessor is unsuspended.
An entity with which Asterisk communicates.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
unsigned int trust_outbound
struct ast_taskprocessor * serializer
void ast_stream_set_group(struct ast_stream *stream, int group)
Set the stream group for a stream.
enum ast_sip_security_negotiation security_negotiation
#define ast_test_suite_event_notify(s, f,...)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ast_sip_endpoint_id_configuration id
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
int ast_shutdown_final(void)
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Set when the stream is sending and receiving media.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
struct ast_stream_topology * ast_channel_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Set the topology of streams on a channel.
Support for dynamic strings.
int ast_stream_topology_equal(const struct ast_stream_topology *left, const struct ast_stream_topology *right)
Compare two stream topologies to see if they are equal.
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
enum ast_sip_dtmf_mode dtmf
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
unsigned int trust_inbound
struct ast_taskprocessor * ast_sip_get_distributor_serializer(pjsip_rx_data *rdata)
Determine the distributor serializer for the SIP message.
pj_timer_entry scheduled_termination
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
#define DATASTORE_BUCKETS
Number of buckets for datastore container.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
unsigned int preferred_codec_only
struct ast_sip_session::@270 delayed_requests
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor's current task.
Set when the stream is sending media only.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
struct ast_sip_timer_options timer
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_calloc(num, len)
A wrapper for calloc()
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
void(* session_end)(struct ast_sip_session *session)
Notification that the session has ended.
unsigned int moh_passthrough
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Structure used for sending delayed requests.
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
struct controlling the suspension of the session's serializer.
Support for logging to various files, console and syslog Configuration in file logger.conf.
Module has failed to load, may be in an inconsistent state.
Vector container support.
An API for managing task processing threads that can be shared across modules.
ast_sip_session_response_cb on_response
void ast_party_id_init(struct ast_party_id *init)
Initialize the given party id structure.
int ast_taskprocessor_is_suspended(struct ast_taskprocessor *tps)
Get the task processor suspend status.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
void ast_sdp_srtp_destroy(struct ast_sdp_srtp *srtp)
free a ast_sdp_srtp structure
struct ast_sip_session_suspender * suspended
void(* session_begin)(struct ast_sip_session *session)
Notification that the session has begun This method will always be called from a SIP servant thread...
A supplement to SIP message processing.
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
struct ast_frame ast_null_frame
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
unsigned int allow_overlap
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
enum ast_sip_100rel_mode rel100
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
struct ast_stream * ast_stream_clone(const struct ast_stream *stream, const char *name)
Create a deep clone of an existing stream.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
enum ast_sip_session_call_direction call_direction
const char * ast_stream_state2str(enum ast_stream_state state)
Convert the state of a stream into a string.
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
const char * ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
Get a stream metadata value.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
unsigned int authentication_challenge_count
#define AST_TEST_DEFINE(hdr)
enum ast_sip_session_sdp_stream_defer(* defer_incoming_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
Determine whether a stream requires that the re-invite be deferred. If a stream can not be immediatel...
struct ast_sip_endpoint_extensions extensions
ast_media_type
Types of media.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
static pj_timer_heap_t * timer_heap
Global timer heap.
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
const ast_string_field aors
pjsip_fromto_hdr * saved_from_hdr
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
struct ast_sip_contact * contact
Asterisk module definitions.
int ast_channel_stream_topology_changed_externally(struct ast_channel *chan)
Provide notice from a channel that the topology has changed on it as a result of the remote party ren...
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
enum ast_sip_session_redirect redirect_method
int(* create_outgoing_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
Create an SDP media stream and add it to the outgoing SDP offer or answer.
Set when the stream is receiving media only.
int(* apply_negotiated_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
Apply a negotiated SDP media stream.
int ast_stream_topology_del_stream(struct ast_stream_topology *topology, unsigned int position)
Delete a specified stream from the given topology.
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
unsigned int position
The position of the stream in the topology.
void(* stream_stop)(struct ast_sip_session_media *session_media)
Stop a session_media created by this handler but do not destroy resources.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
unsigned int moh_passthrough
const ast_string_field fromdomain
const ast_string_field pickupexten
Configuration relating to call pickup.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
#define ao2_link(container, obj)
Add an object to a container.