Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
Functions | Variables
channel_info.c File Reference

Channel-locked PJSIP information for CHANNEL() reads. More...

#include "asterisk.h"
#include <pjsip.h>
#include "asterisk/astobj2.h"
#include "asterisk/channel.h"
#include "asterisk/datastore.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/rtp_engine.h"
#include "include/channel_info.h"
Include dependency graph for channel_info.c:

Go to the source code of this file.

Functions

static void channel_info_breakdown (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static void channel_info_destroy (void *data)
 
static int channel_info_incoming_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
static void channel_info_incoming_response (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
static void channel_info_outgoing_request (struct ast_sip_session *session, struct pjsip_tx_data *tdata)
 
static void channel_info_outgoing_response (struct ast_sip_session *session, struct pjsip_tx_data *tdata)
 
static void channel_info_update_locked (struct pjsip_channel_info *info, struct ast_sip_session *session)
 
static int channel_info_update_task (void *data)
 
static int copy_uri (struct pjsip_channel_uri *dest, pjsip_uri_context_e context, const void *uri, const char *type)
 
int pjsip_channel_info_create (struct ast_channel *chan, struct ast_sip_session *session)
 Create channel-owned PJSIP information before channel publication.
 
struct pjsip_channel_info * pjsip_channel_info_get (struct ast_channel *chan)
 Find the channel's information, or NULL if it has none.
 
void pjsip_channel_info_register (void)
 Register the channel information session supplement.
 
void pjsip_channel_info_schedule_update (struct ast_sip_session *session)
 Schedule a refresh from any thread without waiting for the serializer.
 
void pjsip_channel_info_unregister (void)
 Unregister the channel information session supplement.
 
void pjsip_channel_info_update (struct ast_sip_session *session)
 Refresh channel information under the channel lock.
 

Variables

static const struct ast_datastore_info channel_info_datastore
 
static struct ast_sip_session_supplement channel_info_supplement
 

Detailed Description

Channel-locked PJSIP information for CHANNEL() reads.

The channel datastore owns cached dialog URIs, the remote tag, signaling security, RTP instance references, and media security and hold flags. Readers and writers access the cache under the channel lock. A datastore lookup returns a borrowed pointer valid only while that lock is held.

Session serializer tasks refresh the cache through session->channel. SIP supplements refresh it during incoming message processing and queue refreshes for subsequent changes. Masquerades suspend the serializer while changing the channel association and move the datastore with the channel.

CHANNEL() reads use the cache for values that SIP and SDP processing can change without the channel lock. Stable identity and original request information are read directly from the session. Direct-media addresses are read under the channel lock. RTP APIs supply RTP addresses and statistics.

These reads do not wait for the session serializer or acquire the dialog lock while holding the channel lock to avoid a deadlock with masquerade processing.

Definition in file channel_info.c.

Function Documentation

◆ channel_info_breakdown()

static void channel_info_breakdown ( void *  data,
struct ast_channel *  old_chan,
struct ast_channel *  new_chan 
)
static

Definition at line 67 of file channel_info.c.

69{
70 struct pjsip_channel_info *info = data;
71 struct ast_datastore *datastore = info->datastore;
72
73 /*
74 * Core calls breakdown on the destination's old datastores before moving
75 * the source's datastores over. Both channels are locked. The moved
76 * datastore needs no fixup because it contains no channel pointer.
77 */
78 if (!ast_channel_datastore_remove(new_chan, datastore)) {
79 ast_datastore_free(datastore);
80 }
81}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition channel.c:2385
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition datastore.c:68
Structure for a data store object.
Definition datastore.h:64
const struct ast_datastore_info * info
Definition datastore.h:67

References ast_channel_datastore_remove(), ast_datastore_free(), and ast_datastore::info.

◆ channel_info_destroy()

static void channel_info_destroy ( void *  data)
static

Definition at line 57 of file channel_info.c.

58{
59 struct pjsip_channel_info *info = data;
60
61 ast_free(info->remote_tag);
62 ao2_cleanup(info->audio_rtp);
63 ao2_cleanup(info->video_rtp);
64 ast_free(info);
65}
#define ast_free(a)
Definition astmm.h:180
#define ao2_cleanup(obj)
Definition astobj2.h:1934

References ao2_cleanup, and ast_free.

◆ channel_info_incoming_request()

static int channel_info_incoming_request ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 252 of file channel_info.c.

254{
257 return 0;
258}
static struct ast_mansession session
void pjsip_channel_info_schedule_update(struct ast_sip_session *session)
Schedule a refresh from any thread without waiting for the serializer.
void pjsip_channel_info_update(struct ast_sip_session *session)
Refresh channel information under the channel lock.

References pjsip_channel_info_schedule_update(), pjsip_channel_info_update(), and session.

◆ channel_info_incoming_response()

static void channel_info_incoming_response ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

◆ channel_info_outgoing_request()

static void channel_info_outgoing_request ( struct ast_sip_session *  session,
struct pjsip_tx_data *  tdata 
)
static

Definition at line 267 of file channel_info.c.

References pjsip_channel_info_schedule_update(), and session.

◆ channel_info_outgoing_response()

static void channel_info_outgoing_response ( struct ast_sip_session *  session,
struct pjsip_tx_data *  tdata 
)
static

Definition at line 273 of file channel_info.c.

References pjsip_channel_info_schedule_update(), and session.

◆ channel_info_update_locked()

static void channel_info_update_locked ( struct pjsip_channel_info *  info,
struct ast_sip_session *  session 
)
static

Definition at line 122 of file channel_info.c.

124{
125 pjsip_dialog *dlg = session->inv_session ? session->inv_session->dlg : NULL;
126 struct ast_sip_session_media *media;
127
128 if (dlg) {
129 int target_changed;
130 const pj_str_t *tag = &dlg->remote.info->tag;
131
132 target_changed = copy_uri(&info->target_uri, PJSIP_URI_IN_REQ_URI,
133 dlg->target, "target_uri");
134 copy_uri(&info->local_uri, PJSIP_URI_IN_FROMTO_HDR,
135 dlg->local.info->uri, "local_uri");
136 copy_uri(&info->remote_uri, PJSIP_URI_IN_FROMTO_HDR,
137 dlg->remote.info->uri, "remote_uri");
138 /* PJSIP_MAX_TAG_LEN describes generated tags, not a received-tag limit. */
139 if (!info->remote_tag || strlen(info->remote_tag) != tag->slen
140 || (tag->slen && memcmp(info->remote_tag, tag->ptr, tag->slen))) {
141 char *copy = ast_strndup(tag->slen ? tag->ptr : "", tag->slen);
142
143 ast_free(info->remote_tag);
144 info->remote_tag = copy;
145 }
146#ifdef HAVE_PJSIP_GET_DEST_INFO
147 if (target_changed || info->target_uri.length < 0 || info->secure < 0) {
148 pjsip_host_info dest;
149 pj_pool_t *pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
150 "channel-info", 128, 128);
151
152 info->secure = -1;
153 if (pool) {
154 if (pjsip_get_dest_info(dlg->target, NULL, pool, &dest) == PJ_SUCCESS) {
155 info->secure = !!(dest.flag & PJSIP_TRANSPORT_SECURE);
156 }
157 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
158 }
159 }
160#else
161 ast_log(LOG_WARNING, "Asterisk has been built against a version of pjproject which does not have the required functionality to support the 'secure' argument. Please upgrade to version 2.3 or later.\n");
162 (void) target_changed;
163#endif
164 } else {
165 copy_uri(&info->target_uri, PJSIP_URI_IN_REQ_URI, NULL, "target_uri");
166 copy_uri(&info->local_uri, PJSIP_URI_IN_FROMTO_HDR, NULL, "local_uri");
167 copy_uri(&info->remote_uri, PJSIP_URI_IN_FROMTO_HDR, NULL, "remote_uri");
168 ast_free(info->remote_tag);
169 info->remote_tag = NULL;
170 info->secure = -1;
171 }
172
173 media = session->active_media_state
174 ? session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO] : NULL;
175 ao2_replace(info->audio_rtp, media ? media->rtp : NULL);
176 info->audio_secure = media && media->srtp
178 info->audio_held = media && media->remotely_held;
179 media = session->active_media_state
180 ? session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO] : NULL;
181 ao2_replace(info->video_rtp, media ? media->rtp : NULL);
182 info->video_secure = media && media->srtp
184 info->video_held = media && media->remotely_held;
185}
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define ast_strndup(str, len)
A wrapper for strndup()
Definition astmm.h:256
#define ast_log
Definition astobj2.c:42
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
static int copy_uri(struct pjsip_channel_uri *dest, pjsip_uri_context_e context, const void *uri, const char *type)
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition codec.h:33
#define LOG_WARNING
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition res_pjsip.c:518
#define NULL
Definition resample.c:96
#define AST_SRTP_CRYPTO_OFFER_OK
Definition sdp_srtp.h:45
A structure containing SIP session media information.
struct ast_sdp_srtp * srtp
Holds SRTP information.
unsigned int remotely_held
Stream is on hold by remote side.
struct ast_rtp_instance * rtp
RTP instance itself.
#define ast_test_flag(p, flag)
Definition utils.h:64

References ao2_replace, ast_free, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_sip_get_pjsip_endpoint(), AST_SRTP_CRYPTO_OFFER_OK, ast_strndup, ast_test_flag, copy(), copy_uri(), LOG_WARNING, NULL, ast_sip_session_media::remotely_held, ast_sip_session_media::rtp, session, and ast_sip_session_media::srtp.

Referenced by pjsip_channel_info_create(), and pjsip_channel_info_update().

◆ channel_info_update_task()

static int channel_info_update_task ( void *  data)
static

Definition at line 229 of file channel_info.c.

230{
231 struct ast_sip_session *session = data;
232
234 ao2_ref(session, -1);
235 return 0;
236}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
A structure describing a SIP session.

References ao2_ref, pjsip_channel_info_update(), and session.

Referenced by pjsip_channel_info_schedule_update().

◆ copy_uri()

static int copy_uri ( struct pjsip_channel_uri *  dest,
pjsip_uri_context_e  context,
const void *  uri,
const char *  type 
)
static

Definition at line 98 of file channel_info.c.

100{
101 char value[PJSIP_MAX_URL_SIZE] = "";
102 int length = 0;
103 int changed;
104
105 if (uri) {
106 length = pjsip_uri_print(context, uri, value, sizeof(value));
107 if (length < 0 || length >= sizeof(value)) {
108 ast_log(LOG_ERROR, "Unable to capture PJSIP %s in %zu bytes\n",
109 type, sizeof(value));
110 value[0] = '\0';
111 length = -1;
112 } else {
113 value[length] = '\0';
114 }
115 }
116 changed = dest->length != length || strcmp(dest->value, value);
117 ast_copy_string(dest->value, value, sizeof(dest->value));
118 dest->length = length;
119 return changed;
120}
static const char type[]
#define LOG_ERROR
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
char value[PJSIP_MAX_URL_SIZE]
int value
Definition syslog.c:37

References ast_copy_string(), ast_log, pjsip_channel_uri::length, LOG_ERROR, type, pjsip_channel_uri::value, and value.

Referenced by channel_info_update_locked().

◆ pjsip_channel_info_create()

int pjsip_channel_info_create ( struct ast_channel *  chan,
struct ast_sip_session *  session 
)

Create channel-owned PJSIP information before channel publication.

Precondition
The caller holds the channel lock and executes in the session serializer.
Return values
0on success
-1on failure

Definition at line 187 of file channel_info.c.

189{
190 struct ast_datastore *datastore;
191 struct pjsip_channel_info *info;
192
194 if (!datastore) {
195 return -1;
196 }
197 info = ast_calloc(1, sizeof(*info));
198 if (!info) {
200 return -1;
201 }
202 info->datastore = datastore;
203 info->secure = -1;
205
206 /* The caller holds the channel lock and is running in the serializer. */
209 return 0;
210}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
static const struct ast_datastore_info channel_info_datastore
static void channel_info_update_locked(struct pjsip_channel_info *info, struct ast_sip_session *session)
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
void * data
Definition datastore.h:66
struct ast_datastore * datastore

References ast_calloc, ast_channel_datastore_add(), ast_datastore_alloc, ast_datastore_free(), channel_info_datastore, channel_info_update_locked(), ast_datastore::data, pjsip_channel_info::datastore, NULL, and session.

Referenced by chan_pjsip_new().

◆ pjsip_channel_info_get()

struct pjsip_channel_info * pjsip_channel_info_get ( struct ast_channel *  chan)

Find the channel's information, or NULL if it has none.

Precondition
The caller holds the channel lock.
Note
The result is borrowed and may only be used while the channel is locked. Do not release it with ao2_cleanup(). The channel datastore owns its lifetime.

Definition at line 89 of file channel_info.c.

90{
91 struct ast_datastore *datastore;
92
94 return datastore ? datastore->data : NULL;
95}
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition channel.c:2390

References ast_channel_datastore_find(), channel_info_datastore, ast_datastore::data, and NULL.

Referenced by channel_read_pjsip(), pjsip_acf_channel_read(), and pjsip_channel_info_update().

◆ pjsip_channel_info_register()

void pjsip_channel_info_register ( void  )

Register the channel information session supplement.

Definition at line 289 of file channel_info.c.

290{
292}
static struct ast_sip_session_supplement channel_info_supplement
#define ast_sip_session_register_supplement(supplement)

References ast_sip_session_register_supplement, and channel_info_supplement.

Referenced by load_module().

◆ pjsip_channel_info_schedule_update()

void pjsip_channel_info_schedule_update ( struct ast_sip_session *  session)

Schedule a refresh from any thread without waiting for the serializer.

Definition at line 238 of file channel_info.c.

239{
240 /*
241 * Capture changes made after supplements or from an outgoing transport
242 * callback outside the serializer. Never wait for the queued refresh.
243 */
245 ao2_bump(session))) {
246 ast_log(LOG_WARNING, "Unable to queue PJSIP channel information refresh for %s\n",
248 ao2_ref(session, -1);
249 }
250}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
static int channel_info_update_task(void *data)
#define ast_sip_push_task(serializer, sip_task, task_data)
Definition res_pjsip.h:2126
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.

References ao2_bump, ao2_ref, ast_log, ast_sip_push_task, ast_sip_session_get_name(), channel_info_update_task(), LOG_WARNING, and session.

Referenced by channel_info_incoming_request(), channel_info_incoming_response(), channel_info_outgoing_request(), and channel_info_outgoing_response().

◆ pjsip_channel_info_unregister()

void pjsip_channel_info_unregister ( void  )

Unregister the channel information session supplement.

Definition at line 294 of file channel_info.c.

295{
297}
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.

References ast_sip_session_unregister_supplement(), and channel_info_supplement.

Referenced by load_module(), and unload_module().

◆ pjsip_channel_info_update()

void pjsip_channel_info_update ( struct ast_sip_session *  session)

Refresh channel information under the channel lock.

Precondition
The caller executes in the session serializer.

Definition at line 212 of file channel_info.c.

213{
214 struct ast_channel *chan = session->channel;
215 struct pjsip_channel_info *info;
216
217 /* Serializer execution stabilizes session->channel across a masquerade. */
218 if (!chan) {
219 return;
220 }
221 ast_channel_lock(chan);
223 if (info) {
225 }
226 ast_channel_unlock(chan);
227}
#define ast_channel_lock(chan)
Definition channel.h:2983
#define ast_channel_unlock(chan)
Definition channel.h:2984
struct pjsip_channel_info * pjsip_channel_info_get(struct ast_channel *chan)
Find the channel's information, or NULL if it has none.
Main Channel structure associated with a channel.

References ast_channel_lock, ast_channel_unlock, channel_info_update_locked(), pjsip_channel_info_get(), and session.

Referenced by channel_info_incoming_request(), channel_info_incoming_response(), channel_info_update_task(), and send_direct_media_request().

Variable Documentation

◆ channel_info_datastore

const struct ast_datastore_info channel_info_datastore
static
Initial value:
= {
.type = "chan_pjsip_channel_info",
.chan_breakdown = channel_info_breakdown,
}
static void channel_info_breakdown(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
static void channel_info_destroy(void *data)

Definition at line 83 of file channel_info.c.

83 {
84 .type = "chan_pjsip_channel_info",
85 .destroy = channel_info_destroy,
86 .chan_breakdown = channel_info_breakdown,
87};

Referenced by pjsip_channel_info_create(), and pjsip_channel_info_get().

◆ channel_info_supplement

struct ast_sip_session_supplement channel_info_supplement
static

Definition at line 279 of file channel_info.c.

279 {
280 /* Refresh before channel supplements publish snapshots or queue control frames. */
282 .incoming_request = channel_info_incoming_request,
283 .incoming_response = channel_info_incoming_response,
284 .outgoing_request = channel_info_outgoing_request,
285 .outgoing_response = channel_info_outgoing_response,
286 .response_priority = AST_SIP_SESSION_AFTER_MEDIA,
287};
static void channel_info_outgoing_response(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
static void channel_info_incoming_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static int channel_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static void channel_info_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition res_pjsip.h:3413
@ AST_SIP_SESSION_AFTER_MEDIA

Referenced by pjsip_channel_info_register(), and pjsip_channel_info_unregister().