Asterisk - The Open Source Telephony Project  18.5.0
pjsip_session_caps.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2020, Sangoma Technologies Corporation
5  *
6  * Kevin Harwell <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 #include "asterisk.h"
20 
21 #include "asterisk/astobj2.h"
22 #include "asterisk/channel.h"
23 #include "asterisk/format.h"
24 #include "asterisk/format_cap.h"
25 #include "asterisk/logger.h"
26 #include "asterisk/sorcery.h"
27 #include "asterisk/stream.h"
28 #include "asterisk/res_pjsip.h"
31 
32 static void log_caps(int level, const char *file, int line, const char *function,
34  const struct ast_format_cap *local, const struct ast_format_cap *remote,
35  const struct ast_format_cap *joint)
36 {
37  struct ast_str *s1;
38  struct ast_str *s2;
39  struct ast_str *s3;
41  struct ast_flags pref =
42  outgoing
45 
46  if (level == __LOG_DEBUG && !DEBUG_ATLEAST(3)) {
47  return;
48  }
49 
53 
54  ast_log(level, file, line, function, "'%s' Caps for %s %s call with pref '%s' - remote: %s local: %s joint: %s\n",
55  session->channel ? ast_channel_name(session->channel) :
57  outgoing? "outgoing" : "incoming",
58  ast_codec_media_type2str(media_type),
60  s2 ? ast_format_cap_get_names(remote, &s2) : "(NONE)",
61  s1 ? ast_format_cap_get_names(local, &s1) : "(NONE)",
62  s3 ? ast_format_cap_get_names(joint, &s3) : "(NONE)");
63 }
64 
66  struct ast_format_cap *local, enum ast_media_type media_type,
67  struct ast_flags codec_pref)
68 {
72 
73  if (!joint || !local_filtered || !remote_filtered) {
74  ast_log(LOG_ERROR, "Failed to allocate %s call offer capabilities\n",
75  ast_codec_media_type2str(media_type));
76  ao2_cleanup(joint);
77  ao2_cleanup(local_filtered);
78  ao2_cleanup(remote_filtered);
79  return NULL;
80  }
81 
82  ast_format_cap_append_from_cap(local_filtered, local, media_type);
83 
84  /* Remote should always be a subset of local, as local is what defines the underlying
85  * permitted formats.
86  */
87  ast_format_cap_get_compatible(remote, local_filtered, remote_filtered);
88 
89  if (ast_sip_call_codec_pref_test(codec_pref, LOCAL)) {
90  if (ast_sip_call_codec_pref_test(codec_pref, INTERSECT)) {
91  ast_format_cap_get_compatible(local_filtered, remote_filtered, joint); /* Get common, prefer local */
92  } else {
93  ast_format_cap_append_from_cap(joint, local_filtered, media_type); /* Add local */
94  ast_format_cap_append_from_cap(joint, remote_filtered, media_type); /* Then remote */
95  }
96  } else {
97  if (ast_sip_call_codec_pref_test(codec_pref, INTERSECT)) {
98  joint = remote_filtered; /* Get common, prefer remote - as was done when filtering initially */
99  remote_filtered = NULL;
100  } else {
101  ast_format_cap_append_from_cap(joint, remote_filtered, media_type); /* Add remote */
102  ast_format_cap_append_from_cap(joint, local_filtered, media_type); /* Then local */
103  }
104  }
105 
106  ao2_ref(local_filtered, -1);
107  ao2_cleanup(remote_filtered);
108 
109  if (ast_format_cap_empty(joint)) {
110  return joint;
111  }
112 
113  if (ast_sip_call_codec_pref_test(codec_pref, FIRST)) {
114  /*
115  * Save the most preferred one. Session capabilities are per stream and
116  * a stream only carries a single media type, so no reason to worry with
117  * the type here (i.e different or multiple types)
118  */
119  struct ast_format *single = ast_format_cap_get_format(joint, 0);
120  /* Remove all formats */
122  /* Put the most preferred one back */
123  ast_format_cap_append(joint, single, 0);
124  ao2_ref(single, -1);
125  }
126 
127  return joint;
128 }
129 
131  struct ast_stream *remote_stream)
132 {
133  struct ast_stream *joint_stream = ast_stream_clone(remote_stream, NULL);
134  const struct ast_format_cap *remote = ast_stream_get_formats(remote_stream);
135  enum ast_media_type media_type = ast_stream_get_type(remote_stream);
136 
137  struct ast_format_cap *joint = ast_sip_create_joint_call_cap(remote,
138  session->endpoint->media.codecs, media_type,
142 
143  ast_stream_set_formats(joint_stream, joint);
144  ao2_cleanup(joint);
145 
146  log_caps(LOG_DEBUG, session, media_type, session->endpoint->media.codecs, remote, joint);
147 
148  return joint_stream;
149 }
150 
152  const struct ast_sip_session *session, enum ast_media_type media_type,
153  const struct ast_format_cap *remote)
154 {
155  struct ast_format_cap *joint = ast_sip_create_joint_call_cap(remote,
156  session->endpoint->media.codecs, media_type,
160 
161  log_caps(LOG_DEBUG, session, media_type, session->endpoint->media.codecs, remote, joint);
162 
163  return joint;
164 }
static void log_caps(int level, const char *file, int line, const char *function, const struct ast_sip_session *session, enum ast_media_type media_type, const struct ast_format_cap *local, const struct ast_format_cap *remote, const struct ast_format_cap *joint)
struct ast_format_cap * ast_sip_session_create_joint_call_cap(const struct ast_sip_session *session, enum ast_media_type media_type, const struct ast_format_cap *remote)
Create joint capabilities.
struct ast_sip_endpoint * endpoint
Asterisk main include file. File version handling, generic pbx functions.
struct ast_flags outgoing_call_offer_pref
Definition: res_pjsip.h:798
#define __LOG_DEBUG
Definition: logger.h:240
media_type
Media types generate different "dummy answers" for not accepting the offer of a media stream...
Definition: sip.h:489
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
struct ast_format_cap * codecs
Definition: res_pjsip.h:770
Definition of a media format.
Definition: format.c:43
#define ast_str_alloca(init_len)
Definition: strings.h:800
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
A structure describing a SIP session.
Media Stream API.
Media Format API.
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
const char * ast_sip_call_codec_pref_to_str(struct ast_flags pref)
Convert the call codec preference flags to a string.
Definition: res_pjsip.c:5534
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_channel * channel
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:525
Format Capabilities API.
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
struct ast_stream * ast_sip_session_create_joint_call_stream(const struct ast_sip_session *session, struct ast_stream *remote_stream)
Create a new stream of joint capabilities.
struct ast_format_cap * ast_sip_create_joint_call_cap(const struct ast_format_cap *remote, struct ast_format_cap *local, enum ast_media_type media_type, struct ast_flags codec_pref)
Create joint capabilities.
Structure used to handle boolean flags.
Definition: utils.h:199
Support for logging to various files, console and syslog Configuration in file logger.conf.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_stream * ast_stream_clone(const struct ast_stream *stream, const char *name)
Create a deep clone of an existing stream.
Definition: stream.c:257
const char * ast_channel_name(const struct ast_channel *chan)
enum ast_sip_session_call_direction call_direction
ast_media_type
Types of media.
Definition: codec.h:30
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition: format_cap.c:746
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
struct ast_flags incoming_call_offer_pref
Definition: res_pjsip.h:796
#define DEBUG_ATLEAST(level)
Definition: logger.h:441
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:630
Sorcery Data Access Layer API.