1 /*
2 * Copyright (C) 2008 Sippy Software, Inc., http://www.sippysoft.com
3 *
4 * This file is part of ser, a free SIP server.
5 *
6 * ser is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
10 *
11 * For a license to use the ser software under conditions
12 * other than those described here, or to purchase support for this
13 * software, please contact iptel.org by e-mail at the following addresses:
14 * info@iptel.org
15 *
16 * ser is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27 #include <stdio.h>
28 #include <sys/uio.h>
29
30 #include "../../core/ip_addr.h"
31 #include "../../core/parser/msg_parser.h"
32 #include "../../core/sr_module.h"
33 #include "../../core/ut.h"
34 #include "rtpproxy.h"
35 #include "rtpproxy_funcs.h"
36
37 int
fixup_var_str_int(void ** param,int param_no)38 fixup_var_str_int(void **param, int param_no)
39 {
40 int ret;
41 pv_elem_t *model;
42 str s;
43
44 if (param_no == 1) {
45 model = NULL;
46 s.s = (char *)(*param);
47 s.len = strlen(s.s);
48 if (pv_parse_format(&s, &model) < 0) {
49 LM_ERR("wrong format[%s]!\n", (char *)(*param));
50 return E_UNSPEC;
51 }
52 if (model == NULL) {
53 LM_ERR("empty parameter!\n");
54 return E_UNSPEC;
55 }
56 *param = (void *)model;
57 } else if (param_no == 2) {
58 /* According to
59 * http://www.kamailio.org/docs/modules/1.5.x/nathelper.html#rtpproxy_stream2xxx
60 * this could be -1 */
61 s.s = (char *)(*param);
62 s.len = strlen(s.s);
63 if (str2sint(&s, &ret)==0) {
64 pkg_free(*param);
65 *param = (void *)(long)ret;
66 } else {
67 LM_ERR("bad number <%s>\n", (char *)(*param));
68 return E_CFG;
69 }
70 }
71 return 0;
72 }
73
74 int
rtpproxy_stream(struct sip_msg * msg,str * pname,int count,int stream2uac)75 rtpproxy_stream(struct sip_msg* msg, str *pname, int count, int stream2uac)
76 {
77 int nitems;
78 str callid, from_tag, to_tag;
79 struct rtpp_node *node;
80 char cbuf[16];
81 struct iovec v[] = {
82 {NULL, 0},
83 {cbuf, 0}, /* 1 P<count> */
84 {" ", 1},
85 {NULL, 0}, /* 3 callid */
86 {" ", 1},
87 {NULL, 0}, /* 5 pname */
88 {" session ", 9},
89 {NULL, 0}, /* 7 from tag */
90 {";1 ", 3},
91 {NULL, 0}, /* 9 to tag */
92 {";1", 2}
93 };
94
95 if (get_callid(msg, &callid) == -1 || callid.len == 0) {
96 LM_ERR("can't get Call-Id field\n");
97 return -1;
98 }
99 if (get_to_tag(msg, &to_tag) == -1) {
100 LM_ERR("can't get To tag\n");
101 return -1;
102 }
103 if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
104 LM_ERR("can't get From tag\n");
105 return -1;
106 }
107 v[1].iov_len = sprintf(cbuf, "P%d", count);
108 STR2IOVEC(callid, v[3]);
109 STR2IOVEC(*pname, v[5]);
110 node = select_rtpp_node(callid, 1);
111 if (!node) {
112 LM_ERR("no available proxies\n");
113 return -1;
114 }
115 if (node->rn_ptl_supported == 0) {
116 LM_ERR("required functionality is not "
117 "supported by the version of the RTPproxy running on the selected "
118 "node. Please upgrade the RTPproxy and try again.\n");
119 return -1;
120 }
121 set_rtp_inst_pvar(msg, &node->rn_url);
122 nitems = 11;
123 if (stream2uac == 0) {
124 if (to_tag.len == 0)
125 return -1;
126 STR2IOVEC(to_tag, v[7]);
127 STR2IOVEC(from_tag, v[9]);
128 } else {
129 STR2IOVEC(from_tag, v[7]);
130 STR2IOVEC(to_tag, v[9]);
131 if (to_tag.len <= 0)
132 nitems -= 2;
133 }
134 send_rtpp_command(node, v, nitems);
135
136 return 1;
137 }
138
139 static int
rtpproxy_stream2_f(struct sip_msg * msg,char * str1,int count,int stream2uac)140 rtpproxy_stream2_f(struct sip_msg *msg, char *str1, int count, int stream2uac)
141 {
142 str pname;
143
144 if (str1 == NULL || pv_printf_s(msg, (pv_elem_p)str1, &pname) != 0)
145 return -1;
146 return rtpproxy_stream(msg, &pname, count, stream2uac);
147 }
148
149 int
rtpproxy_stream2uac2_f(struct sip_msg * msg,char * str1,char * str2)150 rtpproxy_stream2uac2_f(struct sip_msg* msg, char* str1, char* str2)
151 {
152
153 return rtpproxy_stream2_f(msg, str1, (int)(long)str2, 1);
154 }
155
156 int
rtpproxy_stream2uas2_f(struct sip_msg * msg,char * str1,char * str2)157 rtpproxy_stream2uas2_f(struct sip_msg* msg, char* str1, char* str2)
158 {
159
160 return rtpproxy_stream2_f(msg, str1, (int)(long)str2, 0);
161 }
162
163 int
rtpproxy_stop_stream(struct sip_msg * msg,int stream2uac)164 rtpproxy_stop_stream(struct sip_msg* msg, int stream2uac)
165 {
166 int nitems;
167 str callid, from_tag, to_tag;
168 struct rtpp_node *node;
169 struct iovec v[] = {
170 {NULL, 0},
171 {"S", 1}, /* 1 */
172 {" ", 1},
173 {NULL, 0}, /* 3 callid */
174 {" ", 1},
175 {NULL, 0}, /* 5 from tag */
176 {";1 ", 3},
177 {NULL, 0}, /* 7 to tag */
178 {";1", 2}
179 };
180
181 if (get_callid(msg, &callid) == -1 || callid.len == 0) {
182 LM_ERR("can't get Call-Id field\n");
183 return -1;
184 }
185 if (get_to_tag(msg, &to_tag) == -1) {
186 LM_ERR("can't get To tag\n");
187 return -1;
188 }
189 if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
190 LM_ERR("can't get From tag\n");
191 return -1;
192 }
193 STR2IOVEC(callid, v[3]);
194 node = select_rtpp_node(callid, 1);
195 if (!node) {
196 LM_ERR("no available proxies\n");
197 return -1;
198 }
199 if (node->rn_ptl_supported == 0) {
200 LM_ERR("required functionality is not "
201 "supported by the version of the RTPproxy running on the selected "
202 "node. Please upgrade the RTPproxy and try again.\n");
203 return -1;
204 }
205 set_rtp_inst_pvar(msg, &node->rn_url);
206 nitems = 9;
207 if (stream2uac == 0) {
208 if (to_tag.len == 0)
209 return -1;
210 STR2IOVEC(to_tag, v[5]);
211 STR2IOVEC(from_tag, v[7]);
212 } else {
213 STR2IOVEC(from_tag, v[5]);
214 STR2IOVEC(to_tag, v[7]);
215 if (to_tag.len <= 0)
216 nitems -= 2;
217 }
218 send_rtpp_command(node, v, nitems);
219
220 return 1;
221 }
222
223 int
rtpproxy_stop_stream2uac2_f(struct sip_msg * msg,char * str1,char * str2)224 rtpproxy_stop_stream2uac2_f(struct sip_msg* msg, char* str1, char* str2)
225 {
226
227 return rtpproxy_stop_stream(msg, 1);
228 }
229
230 int
rtpproxy_stop_stream2uas2_f(struct sip_msg * msg,char * str1,char * str2)231 rtpproxy_stop_stream2uas2_f(struct sip_msg* msg, char* str1, char* str2)
232 {
233
234 return rtpproxy_stop_stream(msg, 0);
235 }
236