Merge "test_res_rtp: Enable FIR and REMB nominal tests."
[asterisk/asterisk.git] / res / res_pjsip / pjsip_session.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2017, CFWare, LLC
5  *
6  * Corey Farrell <git@cfware.com>
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 <pjsip.h>
22 #include <pjsip_ua.h>
23 #include <pjlib.h>
24
25 #include "asterisk/res_pjsip.h"
26 #include "asterisk/res_pjsip_session.h"
27 #include "include/res_pjsip_private.h"
28 #include "asterisk/linkedlists.h"
29 #include "asterisk/lock.h"
30 #include "asterisk/module.h"
31
32
33 AST_RWLIST_HEAD_STATIC(session_supplements, ast_sip_session_supplement);
34
35 void ast_sip_session_register_supplement_with_module(struct ast_module *module, struct ast_sip_session_supplement *supplement)
36 {
37         struct ast_sip_session_supplement *iter;
38         int inserted = 0;
39         SCOPED_LOCK(lock, &session_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
40
41         ast_assert(supplement != NULL);
42
43         supplement->module = module;
44
45         if (!supplement->response_priority) {
46                 supplement->response_priority = AST_SIP_SESSION_BEFORE_MEDIA;
47         }
48
49         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&session_supplements, iter, next) {
50                 if (iter->priority > supplement->priority) {
51                         AST_RWLIST_INSERT_BEFORE_CURRENT(supplement, next);
52                         inserted = 1;
53                         break;
54                 }
55         }
56         AST_RWLIST_TRAVERSE_SAFE_END;
57
58         if (!inserted) {
59                 AST_RWLIST_INSERT_TAIL(&session_supplements, supplement, next);
60         }
61 }
62
63 void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
64 {
65         struct ast_sip_session_supplement *iter;
66         SCOPED_LOCK(lock, &session_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
67
68         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&session_supplements, iter, next) {
69                 if (supplement == iter) {
70                         AST_RWLIST_REMOVE_CURRENT(next);
71                         break;
72                 }
73         }
74         AST_RWLIST_TRAVERSE_SAFE_END;
75 }
76
77 static struct ast_sip_session_supplement *supplement_dup(const struct ast_sip_session_supplement *src)
78 {
79         struct ast_sip_session_supplement *dst = ast_calloc(1, sizeof(*dst));
80
81         if (!dst) {
82                 return NULL;
83         }
84         /* Will need to revisit if shallow copy becomes an issue */
85         *dst = *src;
86
87         return dst;
88 }
89
90 int ast_sip_session_add_supplements(struct ast_sip_session *session)
91 {
92         struct ast_sip_session_supplement *iter;
93         SCOPED_LOCK(lock, &session_supplements, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
94
95         AST_RWLIST_TRAVERSE(&session_supplements, iter, next) {
96                 struct ast_sip_session_supplement *copy = supplement_dup(iter);
97
98                 if (!copy) {
99                         return -1;
100                 }
101
102                 /* referenced session created. increasing module reference. */
103                 ast_module_ref(copy->module);
104
105                 AST_LIST_INSERT_TAIL(&session->supplements, copy, next);
106         }
107
108         return 0;
109 }
110
111 void ast_sip_session_remove_supplements(struct ast_sip_session *session)
112 {
113         struct ast_sip_session_supplement *iter;
114
115         if (!session) {
116                 return;
117         }
118
119         /* free the supplements */
120         while ((iter = AST_LIST_REMOVE_HEAD(&session->supplements, next))) {
121                 if (iter->module) {
122                         /* referenced session closed. decreasing modue reference. */
123                         ast_module_unref(iter->module);
124                 }
125
126                 ast_free(iter);
127         }
128
129         return;
130 }
131