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