1 /*!
2 * \file sccp_rtp.c
3 * \brief SCCP RTP Class
4 * \author Sergio Chersovani <mlists [at] c-net.it>
5 * \note Reworked, but based on chan_sccp code.
6 * The original chan_sccp driver that was made by Zozo which itself was derived from the chan_skinny driver.
7 * Modified by Jan Czmok and Julien Goodwin
8 * \note This program is free software and may be modified and distributed under the terms of the GNU Public License.
9 * See the LICENSE file at the top of the source tree.
10 *
11 */
12
13 /*!
14 * =============================
15 * Example Networks
16 * =============================
17 * tokyo 200.0.0.254 / 172.20.0.0
18 * 7905:172.20.0.5
19 *
20 * havana 150.0.0.254 / 192.168.0.0
21 * 7970:192.168.0.5
22 *
23 * amsterdam 100.0.0.254 / 10.10.0.0 (IP-Forward) (NoNat)
24 * (PBX):100.0.0.1 & 10.10.0.1)
25 * 7941: 10.10.0.5
26 * 7942: 10.10.0.6
27 *
28 * berlin 80.0.0.254 / 10.20.0.0 (Port Forward) (Nat) sccp.conf needs externip
29 * (PBX): 10.20.0.1
30 * 7941: 10.20.0.5
31 *
32 * ====================================
33 * Example Calls
34 * ====================================
35 * amsterdam -> amsterdam via amsterdam : inDirectRTP
36 * 172.20.0.5 -> 10.0.0.1:PBX:10.0.0.1 -> 10.0.0.6
37 * leg1: us them
38 * leg2: them us
39 *
40 * amsterdam -> amsterdam via amsterdam : DirectRTP
41 * 172.20.0.5 -> 10.0.0.1:PBX:10.0.0.1 -> 10.0.0.6
42 * leg1:us them
43 * leg2:them us
44 *
45 * tokyo -> amsterdam via amsterdam (Single NAT : IP-Forward) inDirectRTP
46 * 172.20.0.5 -> 200.0.0.254 -> Internet -> 100.0.0.1:PBX:10.0.0.1 -> 10.0.0.5
47 * leg1: us them
48 * leg2: them us
49 *
50 * tokyo -> amsterdam via amsterdam (Single NAT : IP-Forward) DirectRTP
51 * 172.20.0.5 -> 200.0.0.254 -> Internet -> 100.0.0.1:PBX:10.0.0.1 -> 10.0.0.5
52 * leg1: us them
53 * leg2: them us
54 *
55 * tokyo -> havana via amsterdam (Single NAT : IP-Forward) inDirectRTP
56 * 172.20.0.5 -> 200.0.0.254 -> Internet -> 100.0.0.1:PBX:100.0.0.1 -> Internet -> 150.0.0.254 -> 192.168.0.5
57 * leg1: us them
58 * leg2: them us
59 *
60 * tokyo -> havana via amsterdam (Single NAT : IP-Forward) DirectRTP
61 * 172.20.0.5 -> 200.0.0.254 -> Internet -> 100.0.0.1:PBX:100.0.0.1 -> Internet -> 150.0.0.254 -> 192.168.0.5
62 * leg1: us them
63 * leg2: them us
64 *
65 * tokyo -> havana via berlin (Double Nat : Port-Forward on PBX Location) inDirectRTP
66 * 172.20.0.5 -> 200.0.0.254 -> Internet -> 80.0.0.254 -> 10.20.0.1:PBX:10.20.0.1 -> 80.0.0.254 -> Internet -> 150.0.0.254 -> 192.168.0.5
67 * leg1: us them
68 * leg2: them us
69 *
70 * tokyo -> havana via berlin (Double Nat : Port-Forward on PBX Location) DirectRTP
71 * 172.20.0.5 -> 200.0.0.254 -> Internet -> 80.0.0.254 -> 10.20.0.1:PBX:10.20.0.1 -> 80.0.0.254 -> Internet -> 150.0.0.254 -> 192.168.0.5
72 * leg1: us them
73 * leg2: them us
74 *
75 * ====================================
76 * How to name the addresses
77 * ====================================
78 * 172.20.0.5 / 192.168.0.5 = phone = physicalIP => (and phone_remote for the phone on the other side of the channel) This information does not get send to the pbx
79 * 200.0.0.254 / 150.0.0.254 = d->session->sin = reachableVia => (can be equal to physicalIP), remote ip-address + port of the connection (gotten from physicalIP)
80 => written to phone(us) during openreceivechannel
81 => written to phone_remote(them) during startmediatransmission
82 * 100.0.0.254 / 100.0.0.254 = externalip = rtp->remote => only required when double nat
83 * 100.0.0.1 / 100.0.0.1 = d->session->ourip = rtp->remote => local ip-address + port of the phone's connection
84 * 10.0.0.1 = d->session->ourip = rtp->remote => local ip-address + port of the phone's connection
85 */
86
87 #include "config.h"
88 #include "common.h"
89 #include "sccp_channel.h"
90 #include "sccp_device.h"
91 #include "sccp_line.h"
92 #include "sccp_linedevice.h"
93 #include "sccp_rtp.h"
94 #include "sccp_session.h"
95 #include "sccp_utils.h"
96
97 SCCP_FILE_VERSION(__FILE__, "");
98
99 /*!
100 * \brief create a new rtp server
101 * \todo refactor iPbx.rtp_???_server to include sccp_rtp_type_t
102 */
sccp_rtp_createServer(constDevicePtr d,channelPtr c,sccp_rtp_type_t type)103 boolean_t sccp_rtp_createServer(constDevicePtr d, channelPtr c, sccp_rtp_type_t type)
104 {
105 sccp_rtp_t *rtp = NULL;
106
107 if (!c || !d) {
108 return FALSE;
109 }
110
111 switch(type) {
112 case SCCP_RTP_AUDIO:
113 rtp = &(c->rtp.audio);
114 break;
115 #if CS_SCCP_VIDEO
116 case SCCP_RTP_VIDEO:
117 rtp = &(c->rtp.video);
118 break;
119 #endif
120 default:
121 pbx_log(LOG_ERROR, "%s: (sccp_rtp_createRTPServer) unknown/unhandled rtp type, cancelling\n", c->designator);
122 return FALSE;
123 }
124
125 if (rtp->instance) {
126 if (rtp->instance_active) {
127 sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_3 "%s: we already have a %s server, we use this one\n", c->designator, sccp_rtp_type2str(type));
128 return TRUE;
129 } else {
130 sccp_rtp_destroy(c);
131 }
132 }
133 rtp->type = type;
134
135 if (iPbx.rtp_create_instance) {
136 rtp->instance_active = iPbx.rtp_create_instance(d, c, rtp);
137 } else {
138 pbx_log(LOG_ERROR, "we should start our own rtp server, but we don't have one\n");
139 return FALSE;
140 }
141 struct sockaddr_storage *phone_remote = &rtp->phone_remote;
142
143 if (!sccp_rtp_getUs(rtp, phone_remote)) {
144 pbx_log(LOG_WARNING, "%s: Did not get our rtp part\n", c->currentDeviceId);
145 return FALSE;
146 }
147
148 uint16_t port = sccp_rtp_getServerPort(rtp);
149 sccp_session_getOurIP(d->session, phone_remote, 0);
150 sccp_netsock_setPort(phone_remote, port);
151
152 if (ast_test_flag(GLOB(global_jbconf), AST_JB_ENABLED)) {
153 if (ast_test_flag(GLOB(global_jbconf), AST_JB_FORCED) || !d->directrtp) {
154 pbx_jb_configure(c->owner, GLOB(global_jbconf));
155 }
156 }
157
158 char buf[NI_MAXHOST + NI_MAXSERV];
159 sccp_copy_string(buf, sccp_netsock_stringify(phone_remote), sizeof(buf));
160 boolean_t isMappedIPv4 = sccp_netsock_ipv4_mapped(phone_remote, phone_remote);
161 sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "%s: (sccp_rtp_createRtpServer) setting new phone %s destination to: %s, family:%s, mapped: %s\n", c->designator, sccp_rtp_type2str(type), buf,
162 sccp_netsock_is_IPv4(phone_remote) ? "IPv4" : "IPv6", isMappedIPv4 ? "True" : "False");
163
164 return rtp->instance_active;
165 }
166
167 /*!
168 * \brief request the port to be used for RTP, early on, so that we can use it during bridging, even before open_receive_ack has been received (directrtp)
169 */
sccp_rtp_requestRTPPorts(constDevicePtr device,channelPtr channel)170 int sccp_rtp_requestRTPPorts(constDevicePtr device, channelPtr channel)
171 {
172 pbx_assert(device != NULL && channel != NULL);
173
174 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: (requestRTPPort) request rtp port from phone\n", device->id);
175 device->protocol->sendPortRequest(device, channel, SKINNY_MEDIA_TRANSPORT_TYPE_RTP, SKINNY_MEDIA_TYPE_AUDIO);
176
177 #ifdef CS_SCCP_VIDEO
178 if (sccp_channel_getVideoMode(channel) != SCCP_VIDEO_MODE_OFF && sccp_device_isVideoSupported(device)) {
179 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: (requestRTPPort) request vrtp port from phone\n", device->id);
180 if (channel->rtp.video.instance || sccp_rtp_createServer(device, channel, SCCP_RTP_VIDEO)) {
181 device->protocol->sendPortRequest(device, channel, SKINNY_MEDIA_TRANSPORT_TYPE_RTP, SKINNY_MEDIA_TYPE_MAIN_VIDEO);
182 }
183 }
184 #endif
185 return 1;
186 }
187
188 /*!
189 * \brief Stop an RTP Source.
190 * \param channel SCCP Channel
191 */
sccp_rtp_stop(constChannelPtr channel)192 void sccp_rtp_stop(constChannelPtr channel)
193 {
194 if (!channel) {
195 return;
196 }
197 if (iPbx.rtp_stop) {
198 sccp_rtp_t *const audio = (sccp_rtp_t *) &(channel->rtp.audio); // discard const
199 if (audio->instance && audio->instance_active) {
200 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_4 "%s: Stopping PBX audio rtp transmission on channel %s\n", channel->currentDeviceId, channel->designator);
201 iPbx.rtp_stop(audio->instance);
202 audio->instance_active = FALSE;
203 }
204 sccp_rtp_t *const video = (sccp_rtp_t *) &(channel->rtp.video); // discard const
205 if (video->instance && video->instance_active) {
206 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_4 "%s: Stopping PBX video rtp transmission on channel %s\n", channel->currentDeviceId, channel->designator);
207 iPbx.rtp_stop(video->instance);
208 video->instance_active = FALSE;
209 }
210 } else {
211 pbx_log(LOG_ERROR, "no pbx function to stop rtp\n");
212 }
213 }
214
215 /*!
216 * \brief Destroy RTP Source.
217 * \param c SCCP Channel
218 */
sccp_rtp_destroy(constChannelPtr c)219 void sccp_rtp_destroy(constChannelPtr c)
220 {
221 sccp_rtp_t *audio = (sccp_rtp_t *) &(c->rtp.audio);
222 sccp_rtp_t *video = (sccp_rtp_t *) &(c->rtp.video);
223
224 if (audio->instance) {
225 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: destroying PBX rtp server on channel %s\n", c->currentDeviceId, c->designator);
226 if (audio->instance_active) {
227 iPbx.rtp_stop(audio->instance);
228 }
229 iPbx.rtp_destroy(audio->instance);
230 audio->instance = NULL;
231 }
232
233 if (video->instance) {
234 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: destroying PBX vrtp server on channel %s\n", c->currentDeviceId, c->designator);
235 if (video->instance_active) {
236 iPbx.rtp_stop(video->instance);
237 }
238 iPbx.rtp_destroy(video->instance);
239 video->instance = NULL;
240 }
241 }
242
sccp_rtp_getState(constRtpPtr rtp,sccp_rtp_dir_t dir)243 sccp_rtp_status_t sccp_rtp_getState(constRtpPtr rtp, sccp_rtp_dir_t dir)
244 {
245 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
246 const sccp_rtp_direction_t * const direction = (dir == SCCP_RTP_RECEPTION) ? &rtp->reception : &rtp->transmission;
247 return direction->_state;
248 }
249
sccp_rtp_areBothInvalid(constRtpPtr rtp)250 sccp_rtp_status_t sccp_rtp_areBothInvalid(constRtpPtr rtp)
251 {
252 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
253 return !rtp->reception._state && !rtp->transmission._state;
254 }
255
sccp_rtp_appendState(rtpPtr rtp,sccp_rtp_dir_t dir,sccp_rtp_status_t state)256 void sccp_rtp_appendState(rtpPtr rtp, sccp_rtp_dir_t dir, sccp_rtp_status_t state)
257 {
258 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
259 sccp_rtp_direction_t * direction = (dir == SCCP_RTP_RECEPTION) ? &rtp->reception : &rtp->transmission;
260 direction->_state |= state;
261 }
262
sccp_rtp_subtractState(rtpPtr rtp,sccp_rtp_dir_t dir,sccp_rtp_status_t state)263 void sccp_rtp_subtractState(rtpPtr rtp, sccp_rtp_dir_t dir, sccp_rtp_status_t state)
264 {
265 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
266 sccp_rtp_direction_t * direction = (dir == SCCP_RTP_RECEPTION) ? &rtp->reception : &rtp->transmission;
267 direction->_state &= ~state;
268 }
269
sccp_rtp_setState(rtpPtr rtp,sccp_rtp_dir_t dir,sccp_rtp_status_t newstate)270 void sccp_rtp_setState(rtpPtr rtp, sccp_rtp_dir_t dir, sccp_rtp_status_t newstate)
271 {
272 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
273 sccp_rtp_direction_t * direction = (dir == SCCP_RTP_RECEPTION) ? &rtp->reception : &rtp->transmission;
274 direction->_state = newstate;
275 }
276
sccp_rtp_setCallback(rtpPtr rtp,sccp_rtp_dir_t dir,scpp_rtp_direction_cb_t cb)277 void sccp_rtp_setCallback(rtpPtr rtp, sccp_rtp_dir_t dir, scpp_rtp_direction_cb_t cb)
278 {
279 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
280 sccp_rtp_direction_t * direction = (dir == SCCP_RTP_RECEPTION) ? &rtp->reception : &rtp->transmission;
281 direction->cb = cb;
282 }
283
284 /* Note: this does unset callback in the process */
285 /* Note: We should maybe move the callback to sccp_rtp_t instead of sccp_rtp_direction_t because it get's a little confusing in sccp_indicate CONNECTED */
rtp_fetchActiveCallback(rtpPtr rtp,sccp_rtp_dir_t dir)286 static scpp_rtp_direction_cb_t rtp_fetchActiveCallback(rtpPtr rtp, sccp_rtp_dir_t dir)
287 {
288 SCOPED_MUTEX(rtplock, (ast_mutex_t *)&rtp->lock);
289 scpp_rtp_direction_cb_t callback = NULL;
290 sccp_rtp_direction_t * direction = (dir == SCCP_RTP_RECEPTION) ? &rtp->reception : &rtp->transmission;
291 if(direction->cb && (direction->_state & SCCP_RTP_STATUS_ACTIVE) == SCCP_RTP_STATUS_ACTIVE) {
292 callback = direction->cb;
293 direction->cb = NULL;
294 }
295 return callback;
296 }
297
sccp_rtp_runCallback(rtpPtr rtp,sccp_rtp_dir_t dir,constChannelPtr channel)298 boolean_t sccp_rtp_runCallback(rtpPtr rtp, sccp_rtp_dir_t dir, constChannelPtr channel)
299 {
300 scpp_rtp_direction_cb_t callback = NULL;
301 if((callback = rtp_fetchActiveCallback(rtp, dir))) {
302 callback(channel); // note callback has to be called without rtp lock held
303 return TRUE;
304 }
305 return FALSE;
306 }
307
308 /*!
309 * \brief update the phones destination address (it's peer)
310 * \param c SCCP Channel
311 * \param rtp SCCP RTP
312 * \param new_peer socket info to remote device
313 */
sccp_rtp_set_peer(constChannelPtr c,rtpPtr rtp,struct sockaddr_storage * new_peer)314 void sccp_rtp_set_peer(constChannelPtr c, rtpPtr rtp, struct sockaddr_storage * new_peer)
315 {
316 /* validate socket */
317 if (sccp_netsock_getPort(new_peer) == 0) {
318 sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: ( sccp_rtp_set_peer ) remote information are invalid, don't change anything\n", c->currentDeviceId);
319 return;
320 }
321
322 /* check if we have new information, which requires us to update */
323 if (sccp_netsock_equals(new_peer, &rtp->phone_remote)) {
324 sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: (sccp_rtp_set_peer) remote information is equal to the current info, ignore change\n", c->currentDeviceId);
325 return;
326 }
327
328 memcpy(&rtp->phone_remote, new_peer, sizeof rtp->phone_remote);
329 pbx_log(LOG_NOTICE, "%s: ( sccp_rtp_set_peer ) Set new remote address to %s\n", c->currentDeviceId, sccp_netsock_stringify(&rtp->phone_remote));
330
331 if(sccp_rtp_getState(rtp, SCCP_RTP_TRANSMISSION)) {
332 /* Shutdown any early-media or previous media on re-invite */
333 /*! \todo we should wait for the acknowledgement to get back. We don't have a function/procedure in place to do this at this moment in time (sccp_dev_send_wait) */
334 sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: (sccp_rtp_set_peer) Restart media transmission on channel %d\n", c->currentDeviceId, c->callid);
335
336 /*! \todo we should check if this is a video or audio rtp */
337 sccp_channel_updateMediaTransmission(c);
338 }
339 }
340
341 /*!
342 * \brief update phones source rtp address
343 * \param c SCCP Channel
344 * \param rtp SCCP RTP
345 * \param new_peer socket info to remote device
346 */
sccp_rtp_set_phone(constChannelPtr c,rtpPtr rtp,struct sockaddr_storage * new_peer)347 void sccp_rtp_set_phone(constChannelPtr c, rtpPtr rtp, struct sockaddr_storage * new_peer)
348 {
349 /* validate socket */
350 if (sccp_netsock_getPort(new_peer) == 0) {
351 sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: (sccp_rtp_set_phone) remote information are invalid, don't change anything\n", c->currentDeviceId);
352 return;
353 }
354
355 AUTO_RELEASE(sccp_device_t, device , sccp_channel_getDevice(c));
356
357 if (device) {
358
359 /* check if we have new infos */
360 char peerIpStr[NI_MAXHOST + NI_MAXSERV];
361 char remoteIpStr[NI_MAXHOST + NI_MAXSERV];
362 char phoneIpStr[NI_MAXHOST + NI_MAXSERV];
363 if (device->nat >= SCCP_NAT_ON) {
364 /* Rewrite ip-addres to the outside source address using the phones connection (device->sin) */
365 sccp_copy_string(peerIpStr, sccp_netsock_stringify(new_peer), sizeof(peerIpStr));
366 uint16_t port = sccp_netsock_getPort(new_peer);
367 sccp_session_getSas(device->session, new_peer);
368 sccp_netsock_ipv4_mapped(new_peer, new_peer);
369 sccp_netsock_setPort(new_peer, port);
370 }
371
372 /*! \todo if we enable this, we get an audio issue when resume on the same device, so we need to force asterisk to update -MC */
373 /*
374 if (sccp_netsock_equals(new_peer, &c->rtp.audio.phone)) {
375 sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: (sccp_rtp_set_phone) remote information are equal to the current one, ignore change\n", c->currentDeviceId);
376 return;
377 }
378 */
379
380 memcpy(&rtp->phone, new_peer, sizeof(rtp->phone));
381
382 //update pbx
383 if (iPbx.rtp_setPhoneAddress) {
384 iPbx.rtp_setPhoneAddress(rtp, new_peer, device->nat >= SCCP_NAT_ON ? 1 : 0);
385 }
386
387 sccp_copy_string(remoteIpStr, sccp_netsock_stringify(&rtp->phone_remote), sizeof(remoteIpStr));
388 sccp_copy_string(phoneIpStr, sccp_netsock_stringify(&rtp->phone), sizeof(phoneIpStr));
389 if (device->nat >= SCCP_NAT_ON) {
390 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: Tell PBX to send RTP/UDP media from %s to %s (NAT:%s)\n", DEV_ID_LOG(device), remoteIpStr, phoneIpStr, peerIpStr);
391 } else {
392 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: Tell PBX to send RTP/UDP media from %s to %s (NoNat)\n", DEV_ID_LOG(device), remoteIpStr, phoneIpStr);
393 }
394 }
395 }
396
397 /*! \todo move the refreshing of the hostname->ip-address to another location (for example scheduler) to re-enable dns hostname lookup */
sccp_rtp_updateNatRemotePhone(constChannelPtr c,rtpPtr rtp)398 int sccp_rtp_updateNatRemotePhone(constChannelPtr c, rtpPtr rtp)
399 {
400 int res = 0;
401 AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
402 if (d) {
403 struct sockaddr_storage sus = { 0 };
404 struct sockaddr_storage *phone_remote = &rtp->phone_remote;
405 sccp_session_getOurIP(d->session, &sus, 0);
406
407 uint16_t usFamily = (sccp_netsock_is_IPv6(&sus) && !sccp_netsock_is_mapped_IPv4(&sus)) ? AF_INET6 : AF_INET;
408 uint16_t remoteFamily = (sccp_netsock_is_IPv6(phone_remote) && !sccp_netsock_is_mapped_IPv4(phone_remote)) ? AF_INET6 : AF_INET;
409
410 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: checkNat us: %s, usFamily: %s\n", d->id, sccp_netsock_stringify(&sus), (usFamily == AF_INET6) ? "IPv6" : "IPv4");
411 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: checkNat remote: %s, remoteFamily: %s\n", d->id, sccp_netsock_stringify(phone_remote), (remoteFamily == AF_INET6) ? "IPv6" : "IPv4");
412 if (d->nat >= SCCP_NAT_ON) {
413 uint16_t port = sccp_rtp_getServerPort(rtp); // get rtp server port
414 if (!sccp_netsock_getExternalAddr(phone_remote, remoteFamily)) { // get externip/externhost ip-address (PBX behind NAT Firewall)
415 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_2 "%s: no externip/externhost set, falling back to using incoming interface address:%s\n", d->id, sccp_netsock_stringify(&sus));
416 memcpy(phone_remote, &sus, sizeof(struct sockaddr_storage));
417 }
418 if (usFamily != remoteFamily) {
419 sccp_netsock_ipv4_mapped(phone_remote, phone_remote); // we need this to convert mapped IPv4 to real IPv4 address
420 }
421 sccp_netsock_setPort(phone_remote, port);
422 sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: (updateNatRemotePhone) new remote: %s, new remoteFamily: %s\n", d->id, sccp_netsock_stringify(phone_remote), (remoteFamily == AF_INET6) ? "IPv6" : "IPv4");
423 res = 1;
424 }
425 }
426 return res;
427 }
428
sccp_rtp_print(constChannelPtr c,sccp_rtp_type_t type,struct ast_str * buf,int buflen)429 void sccp_rtp_print(constChannelPtr c, sccp_rtp_type_t type, struct ast_str * buf, int buflen)
430 {
431 pbx_assert(c && buf);
432 const sccp_rtp_t * rtp;
433 switch(type) {
434 case SCCP_RTP_AUDIO:
435 rtp = &(c->rtp.audio);
436 break;
437 #if CS_SCCP_VIDEO
438 case SCCP_RTP_VIDEO:
439 rtp = &(c->rtp.video);
440 break;
441 #endif
442 default:
443 pbx_log(LOG_ERROR, "%s: (sccp_rtp_print) unknown/unhandled rtp type, cancelling\n", c->designator);
444 return;
445 }
446 AUTO_RELEASE(sccp_device_t, d, sccp_channel_getDevice(c));
447 if(!d || !rtp) {
448 return;
449 }
450
451 boolean_t isNatted = d->nat >= SCCP_NAT_ON ? TRUE : FALSE;
452 boolean_t isIPv4 = sccp_netsock_is_IPv4(&rtp->phone_remote) || sccp_netsock_ipv4_mapped(&rtp->phone_remote, (struct sockaddr_storage *)&rtp->phone_remote) ? TRUE : FALSE;
453 boolean_t isDirectRTP = d->directrtp;
454 const struct sockaddr_storage * const ip = isIPv4 ? &d->ipv4 : &d->ipv6;
455
456 pbx_str_reset(buf);
457 if(isNatted) {
458 pbx_str_append(&buf, 0, "PH1:%s -> FW:%s ----> FW:%s --> %s:%s\n", sccp_netsock_stringify(ip), sccp_netsock_stringify(&rtp->phone), "", isDirectRTP ? sccp_netsock_stringify(&rtp->phone_remote) : "",
459 isDirectRTP ? "AST" : "PH");
460 } else {
461 pbx_str_append(&buf, 0, "PH1:%s ----> %s:%s\n", sccp_netsock_stringify(&rtp->phone), isDirectRTP ? sccp_netsock_stringify(&rtp->phone_remote) : "", isDirectRTP ? "AST" : "PH");
462 }
463 }
464
465 /*!
466 * \brief Get Audio Peer RTP Information
467 */
sccp_rtp_getAudioPeerInfo(constChannelPtr c,sccp_rtp_t ** rtp)468 sccp_rtp_info_t sccp_rtp_getAudioPeerInfo(constChannelPtr c, sccp_rtp_t **rtp)
469 {
470 unsigned int result = SCCP_RTP_INFO_NORTP;
471
472 AUTO_RELEASE(sccp_device_t, device , sccp_channel_getDevice(c));
473
474 if (!device) {
475 return SCCP_RTP_INFO_NORTP;
476 }
477
478 *rtp = &(((sccp_channel_t *) c)->rtp.audio);
479
480 result = SCCP_RTP_INFO_AVAILABLE;
481 // \todo add apply_ha(d->ha, &sin) check here instead
482 if (device->directrtp && device->nat <= SCCP_NAT_AUTO_OFF && !c->conference) {
483 result |= SCCP_RTP_INFO_ALLOW_DIRECTRTP;
484 }
485 return (sccp_rtp_info_t) result;
486 }
487
488 #ifdef CS_SCCP_VIDEO
489 /*!
490 * \brief Get Video Peer RTP Information
491 */
sccp_rtp_getVideoPeerInfo(constChannelPtr c,sccp_rtp_t ** rtp)492 sccp_rtp_info_t sccp_rtp_getVideoPeerInfo(constChannelPtr c, sccp_rtp_t ** rtp)
493 {
494 unsigned int result = SCCP_RTP_INFO_NORTP;
495
496 AUTO_RELEASE(sccp_device_t, device , sccp_channel_getDevice(c));
497
498 if (!device) {
499 return SCCP_RTP_INFO_NORTP;
500 }
501
502 *rtp = &(((sccp_channel_t *) c)->rtp.video);
503
504 result = SCCP_RTP_INFO_AVAILABLE;
505 if (device->directrtp && device->nat <= SCCP_NAT_AUTO_OFF && !c->conference) {
506 result |= SCCP_RTP_INFO_ALLOW_DIRECTRTP;
507 }
508 return (sccp_rtp_info_t)result;
509 }
510
511 /*!
512 * \brief Get Video Peer
513 */
sccp_rtp_getVideoPeer(constChannelPtr c,struct sockaddr_storage ** new_peer)514 boolean_t sccp_rtp_getVideoPeer(constChannelPtr c, struct sockaddr_storage **new_peer)
515 {
516 sccp_rtp_t *video = (sccp_rtp_t *) &(c->rtp.video);
517 *new_peer = &video->phone_remote;
518 return TRUE;
519 }
520 #endif
521
522 /*!
523 * \brief Get Audio Peer
524 */
sccp_rtp_getAudioPeer(constChannelPtr c,struct sockaddr_storage ** new_peer)525 boolean_t sccp_rtp_getAudioPeer(constChannelPtr c, struct sockaddr_storage **new_peer)
526 {
527 sccp_rtp_t *audio = (sccp_rtp_t *) &(c->rtp.audio);
528 *new_peer = &audio->phone_remote;
529 return TRUE;
530 }
531
532 /*!
533 * \brief Get Payload Type
534 */
sccp_rtp_get_payloadType(constRtpPtr rtp,skinny_codec_t codec)535 uint8_t sccp_rtp_get_payloadType(constRtpPtr rtp, skinny_codec_t codec)
536 {
537 if (iPbx.rtp_get_payloadType) {
538 return iPbx.rtp_get_payloadType(rtp, codec);
539 }
540 return 97;
541 }
542
543 /*!
544 * \brief Retrieve Phone Socket Information
545 */
sccp_rtp_getUs(constRtpPtr rtp,struct sockaddr_storage * us)546 boolean_t sccp_rtp_getUs(constRtpPtr rtp, struct sockaddr_storage * us)
547 {
548 if (rtp->instance) {
549 iPbx.rtp_getUs(rtp->instance, us);
550 return TRUE;
551 }
552 // us = &rtp->phone_remote;
553 return FALSE;
554 }
555
sccp_rtp_getServerPort(constRtpPtr rtp)556 uint16_t sccp_rtp_getServerPort(constRtpPtr rtp)
557 {
558 uint16_t port = 0;
559 struct sockaddr_storage sas;
560
561 sccp_rtp_getUs(rtp, &sas);
562
563 port = sccp_netsock_getPort(&sas);
564 return port;
565 }
566
567 /*!
568 * \brief Retrieve Phone Socket Information
569 */
sccp_rtp_getPeer(constRtpPtr rtp,struct sockaddr_storage * them)570 boolean_t sccp_rtp_getPeer(constRtpPtr rtp, struct sockaddr_storage * them)
571 {
572 if (rtp->instance) {
573 iPbx.rtp_getPeer(rtp->instance, them);
574 return TRUE;
575 }
576 return FALSE;
577 }
578
579 /*!
580 * \brief Get Sample Rate
581 */
sccp_rtp_get_sampleRate(skinny_codec_t codec)582 int sccp_rtp_get_sampleRate(skinny_codec_t codec)
583 {
584 if (iPbx.rtp_get_sampleRate) {
585 return iPbx.rtp_get_sampleRate(codec);
586 }
587 return 3840;
588 }
589
590 // kate: indent-width 8; replace-tabs off; indent-mode cstyle; auto-insert-doxygen on; line-numbers on; tab-indents on; keep-extra-spaces off; auto-brackets off;
591