![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
rtp.c File Reference
Definition in file rtp.c.
#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"
Include dependency graph for rtp.c:

Go to the source code of this file.
Data Structures | |
| struct | __attribute__ |
| struct | ast_rtcp |
| Structure defining an RTCP session. More... | |
| struct | ast_rtp |
| RTP session description. More... | |
| struct | rtpPayloadType |
| Structure representing a RTP session.The value of each payload format mapping:. More... | |
| struct | stun_addr |
| struct | stun_attr |
| struct | stun_header |
| struct | stun_state |
Defines | |
| #define | DEFAULT_DTMF_TIMEOUT 3000 |
| #define | FLAG_3389_WARNING (1 << 0) |
| #define | FLAG_CALLBACK_MODE (1 << 6) |
| #define | FLAG_DTMF_COMPENSATE (1 << 7) |
| #define | FLAG_HAS_DTMF (1 << 3) |
| #define | FLAG_HAS_STUN (1 << 8) |
| #define | FLAG_NAT_ACTIVE (3 << 1) |
| #define | FLAG_NAT_INACTIVE (0 << 1) |
| #define | FLAG_NAT_INACTIVE_NOWARN (1 << 1) |
| #define | FLAG_P2P_NEED_DTMF (1 << 5) |
| #define | FLAG_P2P_SENT_MARK (1 << 4) |
| #define | MAX_TIMESTAMP_SKEW 640 |
| #define | RTCP_DEFAULT_INTERVALMS 5000 |
| #define | RTCP_MAX_INTERVALMS 60000 |
| #define | RTCP_MIN_INTERVALMS 500 |
| #define | RTCP_PT_APP 204 |
| #define | RTCP_PT_BYE 203 |
| #define | RTCP_PT_FUR 192 |
| #define | RTCP_PT_RR 201 |
| #define | RTCP_PT_SDES 202 |
| #define | RTCP_PT_SR 200 |
| #define | RTP_MTU 1200 |
| #define | RTP_SEQ_MOD (1<<16) |
| #define | STUN_ACCEPT (1) |
| #define | STUN_BINDERR 0x0111 |
| #define | STUN_BINDREQ 0x0001 |
| #define | STUN_BINDRESP 0x0101 |
| #define | STUN_CHANGE_REQUEST 0x0003 |
| #define | STUN_CHANGED_ADDRESS 0x0005 |
| #define | STUN_ERROR_CODE 0x0009 |
| #define | STUN_IGNORE (0) |
| #define | STUN_MAPPED_ADDRESS 0x0001 |
| #define | STUN_MESSAGE_INTEGRITY 0x0008 |
| #define | STUN_PASSWORD 0x0007 |
| #define | STUN_REFLECTED_FROM 0x000b |
| #define | STUN_RESPONSE_ADDRESS 0x0002 |
| #define | STUN_SECERR 0x0112 |
| #define | STUN_SECREQ 0x0002 |
| #define | STUN_SECRESP 0x0102 |
| #define | STUN_SOURCE_ADDRESS 0x0004 |
| #define | STUN_UNKNOWN_ATTRIBUTES 0x000a |
| #define | STUN_USERNAME 0x0006 |
Functions | |
| static void | append_attr_address (struct stun_attr **attr, int attrval, struct sockaddr_in *sin, int *len, int *left) |
| static void | append_attr_string (struct stun_attr **attr, int attrval, const char *s, int *len, int *left) |
| static unsigned int | ast_rtcp_calc_interval (struct ast_rtp *rtp) |
| int | ast_rtcp_fd (struct ast_rtp *rtp) |
| static struct ast_rtcp * | ast_rtcp_new (void) |
| Initialize a new RTCP session. | |
| ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
| int | ast_rtcp_send_h261fur (void *data) |
| Send an H.261 fast update request. Some devices need this rather than the XML message in SIP. | |
| static int | ast_rtcp_write (void *data) |
| Write and RTCP packet to the far end. | |
| static int | ast_rtcp_write_rr (void *data) |
| Send RTCP recipient's report. | |
| static int | ast_rtcp_write_sr (void *data) |
| Send RTCP sender's report. | |
| size_t | ast_rtp_alloc_size (void) |
| Get the amount of space required to hold an RTP session. | |
| enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| The RTP bridge. | |
| int | ast_rtp_codec_getformat (int pt) |
| ast_codec_pref * | ast_rtp_codec_getpref (struct ast_rtp *rtp) |
| int | ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs) |
| void | ast_rtp_destroy (struct ast_rtp *rtp) |
| int | ast_rtp_early_bridge (struct ast_channel *c0, struct ast_channel *c1) |
| If possible, create an early bridge directly between the devices without having to send a re-invite later. | |
| int | ast_rtp_fd (struct ast_rtp *rtp) |
| ast_rtp * | ast_rtp_get_bridged (struct ast_rtp *rtp) |
| void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
| Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs. | |
| int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| char * | ast_rtp_get_quality (struct ast_rtp *rtp) |
| int | ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp) |
| Get rtp hold timeout. | |
| int | ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp) |
| Get RTP keepalive interval. | |
| int | ast_rtp_get_rtptimeout (struct ast_rtp *rtp) |
| Get rtp timeout. | |
| void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
| int | ast_rtp_getnat (struct ast_rtp *rtp) |
| void | ast_rtp_init (void) |
| Return RTCP quality string. | |
| int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code) |
| Looks up an RTP code out of our *static* outbound list. | |
| char * | ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options) |
| Build a string of MIME subtype names from a capability list. | |
| const char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code, enum ast_rtp_options options) |
| Mapping an Asterisk code into a MIME subtype (string):. | |
| rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
| Mapping between RTP payload format codes and Asterisk codes:. | |
| int | ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media) |
| ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
| Initializate a RTP session. | |
| void | ast_rtp_new_init (struct ast_rtp *rtp) |
| Initialize a new RTP structure. | |
| ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr) |
| Initializate a RTP session using an in_addr structure. | |
| int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
| Register an RTP channel client. | |
| void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
| Unregister an RTP channel client. | |
| void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
| Setting RTP payload types from lines in a SDP description:. | |
| void | ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src) |
| Copy payload types between RTP structures. | |
| void | ast_rtp_pt_default (struct ast_rtp *rtp) |
| Set payload types to defaults. | |
| static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec) |
| Write RTP packet with audio or video media frames into UDP packet. | |
| ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
| int | ast_rtp_reload (void) |
| void | ast_rtp_reset (struct ast_rtp *rtp) |
| int | ast_rtp_sendcng (struct ast_rtp *rtp, int level) |
| generate comfort noice (CNG) | |
| int | ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit) |
| Send begin frames for DTMF. | |
| static int | ast_rtp_senddigit_continuation (struct ast_rtp *rtp) |
| Send continuation frame for DTMF. | |
| int | ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit) |
| Send end packets for DTMF. | |
| void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
| void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
| void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
| Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line). | |
| void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
| void | ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout) |
| Set rtp hold timeout. | |
| void | ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period) |
| set RTP keepalive interval | |
| void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options) |
| Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line. | |
| void | ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout) |
| Set rtp timeout. | |
| void | ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp) |
| void | ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf) |
| Indicate whether this RTP session is carrying DTMF or not. | |
| void | ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate) |
| Compensate for devices that send RFC2833 packets all at once. | |
| void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
| void | ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable) |
| Enable STUN capability. | |
| int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
| void | ast_rtp_stop (struct ast_rtp *rtp) |
| void | ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username) |
| Send STUN request (??). | |
| int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
| static | AST_RWLIST_HEAD_STATIC (protos, ast_rtp_protocol) |
| List of current sessions. | |
| static enum ast_bridge_result | bridge_native_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) |
| Bridge loop for true native bridge (reinvite). | |
| static enum ast_bridge_result | bridge_p2p_loop (struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1) |
| Bridge loop for partial native bridge (packet2packet). | |
| static int | bridge_p2p_rtp_write (struct ast_rtp *rtp, struct ast_rtp *bridged, unsigned int *rtpheader, int len, int hdrlen) |
| Perform a Packet2Packet RTP write. | |
| static void | calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark) |
| static unsigned int | calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery) |
| static struct ast_rtp_protocol * | get_proto (struct ast_channel *chan) |
| Get channel driver interface structure. | |
| static int | p2p_callback_disable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod) |
| Helper function to switch a channel and RTP stream out of callback mode. | |
| static int | p2p_callback_enable (struct ast_channel *chan, struct ast_rtp *rtp, int **iod) |
| P2P RTP Callback. | |
| static void | p2p_set_bridge (struct ast_rtp *rtp0, struct ast_rtp *rtp1) |
| Helper function that sets what an RTP structure is bridged to. | |
| static struct ast_frame * | process_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len) |
| static struct ast_frame * | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno) |
| Process RTP DTMF and events according to RFC 2833. | |
| static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len) |
| Process Comfort Noise RTP. | |
| static int | rtcp_debug_test_addr (struct sockaddr_in *addr) |
| static int | rtcp_do_debug (int fd, int argc, char *argv[]) |
| static int | rtcp_do_debug_ip (int fd, int argc, char *argv[]) |
| static int | rtcp_do_stats (int fd, int argc, char *argv[]) |
| static int | rtcp_no_debug (int fd, int argc, char *argv[]) |
| static int | rtcp_no_stats (int fd, int argc, char *argv[]) |
| static void | rtp_bridge_lock (struct ast_rtp *rtp) |
| static void | rtp_bridge_unlock (struct ast_rtp *rtp) |
| static int | rtp_debug_test_addr (struct sockaddr_in *addr) |
| static int | rtp_do_debug (int fd, int argc, char *argv[]) |
| static int | rtp_do_debug_ip (int fd, int argc, char *argv[]) |
| static int | rtp_no_debug (int fd, int argc, char *argv[]) |
| static int | rtp_socket (void) |
| Open RTP or RTCP socket for a session. | |
| static int | rtpread (int *id, int fd, short events, void *cbdata) |
| static struct ast_frame * | send_dtmf (struct ast_rtp *rtp, enum ast_frame_type type) |
| static const char * | stun_attr2str (int msg) |
| static int | stun_do_debug (int fd, int argc, char *argv[]) |
| static int | stun_handle_packet (int s, struct sockaddr_in *src, unsigned char *data, size_t len) |
| static const char * | stun_msg2str (int msg) |
| static int | stun_no_debug (int fd, int argc, char *argv[]) |
| static int | stun_process_attr (struct stun_state *state, struct stun_attr *attr) |
| static void | stun_req_id (struct stun_header *req) |
| static int | stun_send (int s, struct sockaddr_in *dst, struct stun_header *resp) |
| static void | timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw) |
Variables | |
| static struct ast_cli_entry | cli_rtp [] |
| static const char | debug_usage [] |
| static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT |
| struct { | |
| int alarm | |
| const char * description | |
| unsigned int event_log:1 | |
| char * ext | |
| char * mtype | |
| char * name | |
| const char * name | |
| rtpPayloadType payloadType | |
| unsigned int queue_log:1 | |
| char * subtype | |
| char * type | |
| int val | |
| } | mimeTypes [] |
| static const char | no_debug_usage [] |
| stun_addr | packed |
| stun_attr | packed |
| stun_header | packed |
| static const char | rtcp_debug_usage [] |
| static const char | rtcp_no_debug_usage [] |
| static const char | rtcp_no_stats_usage [] |
| static const char | rtcp_stats_usage [] |
| static int | rtcpdebug |
| static struct sockaddr_in | rtcpdebugaddr |
| static int | rtcpinterval = RTCP_DEFAULT_INTERVALMS |
| static int | rtcpstats |
| static int | rtpdebug |
| static struct sockaddr_in | rtpdebugaddr |
| static int | rtpend |
| static int | rtpstart |
| static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT] |
| static const char | stun_debug_usage [] |
| static const char | stun_no_debug_usage [] |
| static int | stundebug |
|
|
samples Definition at line 76 of file rtp.c. Referenced by ast_rtp_reload(). |
|
|
Definition at line 188 of file rtp.c. Referenced by process_rfc3389(). |
|
|
Definition at line 195 of file rtp.c. Referenced by p2p_callback_disable(). |
|
|
Definition at line 196 of file rtp.c. Referenced by ast_rtp_setdtmfcompensate(), process_cisco_dtmf(), process_rfc2833(), and send_dtmf(). |
|
|
Definition at line 192 of file rtp.c. Referenced by ast_rtp_bridge(), ast_rtp_new_init(), and ast_rtp_setdtmf(). |
|
|
Definition at line 197 of file rtp.c. Referenced by ast_rtp_setstun(). |
|
|
Definition at line 189 of file rtp.c. Referenced by ast_rtp_early_bridge(), ast_rtp_getnat(), ast_rtp_make_compatible(), ast_rtp_raw_write(), ast_rtp_read(), bridge_native_loop(), and bridge_p2p_rtp_write(). |
|
|
Definition at line 190 of file rtp.c. Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write(). |
|
|
Definition at line 191 of file rtp.c. Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write(). |
|
|
Definition at line 194 of file rtp.c. Referenced by ast_rtp_bridge(), and bridge_p2p_rtp_write(). |
|
|
Definition at line 193 of file rtp.c. Referenced by ast_rtp_stop(), bridge_p2p_loop(), and bridge_p2p_rtp_write(). |
|
|
Definition at line 60 of file rtp.c. Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp(). |
|
|
Default milli-seconds between RTCP reports we send |
|
|
Max milli-seconds between RTCP reports we send Definition at line 65 of file rtp.c. Referenced by ast_rtp_reload(). |
|
|
Min milli-seconds between RTCP reports we send Definition at line 64 of file rtp.c. Referenced by ast_rtp_reload(). |
|
|
|
|
|
Definition at line 71 of file rtp.c. Referenced by ast_rtcp_read(). |
|
|
Definition at line 67 of file rtp.c. Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr(). |
|
|
Definition at line 69 of file rtp.c. Referenced by ast_rtcp_read(), and ast_rtcp_write_rr(). |
|
|
Definition at line 70 of file rtp.c. Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr(). |
|
|
Definition at line 68 of file rtp.c. Referenced by ast_rtcp_read(), and ast_rtcp_write_sr(). |
|
|
|
|
|
A sequence number can't be more than 16 bits Definition at line 62 of file rtp.c. Referenced by ast_rtp_read(). |
|
|
Definition at line 261 of file rtp.c. Referenced by ast_rtp_read(), and stun_handle_packet(). |
|
|
Definition at line 265 of file rtp.c. Referenced by stun_msg2str(). |
|
|
Definition at line 263 of file rtp.c. Referenced by ast_rtp_stun_request(), stun_handle_packet(), and stun_msg2str(). |
|
|
Definition at line 264 of file rtp.c. Referenced by stun_handle_packet(), and stun_msg2str(). |
|
|
Definition at line 272 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 274 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 278 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 260 of file rtp.c. Referenced by stun_handle_packet(). |
|
|
Definition at line 270 of file rtp.c. Referenced by stun_attr2str(), and stun_handle_packet(). |
|
|
Definition at line 277 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 276 of file rtp.c. Referenced by stun_attr2str(), and stun_process_attr(). |
|
|
Definition at line 280 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 271 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 268 of file rtp.c. Referenced by stun_msg2str(). |
|
|
Definition at line 266 of file rtp.c. Referenced by stun_msg2str(). |
|
|
Definition at line 267 of file rtp.c. Referenced by stun_msg2str(). |
|
|
Definition at line 273 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 279 of file rtp.c. Referenced by stun_attr2str(). |
|
|
Definition at line 275 of file rtp.c. Referenced by ast_rtp_stun_request(), stun_attr2str(), stun_handle_packet(), and stun_process_attr(). |
|
||||||||||||||||||||||||
|
Definition at line 368 of file rtp.c. References stun_addr::addr. Referenced by stun_handle_packet(). 00369 { 00370 int size = sizeof(**attr) + 8; 00371 struct stun_addr *addr; 00372 if (*left > size) { 00373 (*attr)->attr = htons(attrval); 00374 (*attr)->len = htons(8); 00375 addr = (struct stun_addr *)((*attr)->value); 00376 addr->unused = 0; 00377 addr->family = 0x01; 00378 addr->port = sin->sin_port; 00379 addr->addr = sin->sin_addr.s_addr; 00380 (*attr) = (struct stun_attr *)((*attr)->value + 8); 00381 *len += size; 00382 *left -= size; 00383 } 00384 }
|
|
||||||||||||||||||||||||
|
Definition at line 355 of file rtp.c. Referenced by ast_rtp_stun_request(), and stun_handle_packet(). 00356 { 00357 int size = sizeof(**attr) + strlen(s); 00358 if (*left > size) { 00359 (*attr)->attr = htons(attrval); 00360 (*attr)->len = htons(strlen(s)); 00361 memcpy((*attr)->value, s, strlen(s)); 00362 (*attr) = (struct stun_attr *)((*attr)->value + strlen(s)); 00363 *len += size; 00364 *left -= size; 00365 } 00366 }
|
|
|
Definition at line 526 of file rtp.c. Referenced by ast_rtp_raw_write(), and ast_rtp_read(). 00527 { 00528 unsigned int interval; 00529 /*! \todo XXX Do a more reasonable calculation on this one 00530 * Look in RFC 3550 Section A.7 for an example*/ 00531 interval = rtcpinterval; 00532 return interval; 00533 }
|
|
|
Definition at line 519 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s. Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), jingle_new(), sip_new(), and start_rtp().
|
|
|
Initialize a new RTCP session.
Definition at line 1873 of file rtp.c. References ast_calloc, ast_log(), free, LOG_WARNING, rtp_socket(), and ast_rtcp::s. Referenced by ast_rtp_new_with_bindaddr(). 01874 { 01875 struct ast_rtcp *rtcp; 01876 01877 if (!(rtcp = ast_calloc(1, sizeof(*rtcp)))) 01878 return NULL; 01879 rtcp->s = rtp_socket(); 01880 rtcp->us.sin_family = AF_INET; 01881 rtcp->them.sin_family = AF_INET; 01882 01883 if (rtcp->s < 0) { 01884 free(rtcp); 01885 ast_log(LOG_WARNING, "Unable to allocate RTCP socket: %s\n", strerror(errno)); 01886 return NULL; 01887 } 01888 01889 return rtcp; 01890 }
|
|
|
Definition at line 888 of file rtp.c. References ast_rtcp::accumulated_transit, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), CRASH, ast_frame::datalen, ast_rtp::f, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp(). Referenced by oh323_read(), sip_rtp_read(), and skinny_rtp_read(). 00889 { 00890 socklen_t len; 00891 int position, i, packetwords; 00892 int res; 00893 struct sockaddr_in sin; 00894 unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET]; 00895 unsigned int *rtcpheader; 00896 int pt; 00897 struct timeval now; 00898 unsigned int length; 00899 int rc; 00900 double rtt = 0; 00901 double a; 00902 double dlsr; 00903 double lsr; 00904 unsigned int msw; 00905 unsigned int lsw; 00906 unsigned int comp; 00907 struct ast_frame *f = &ast_null_frame; 00908 00909 if (!rtp || !rtp->rtcp) 00910 return &ast_null_frame; 00911 00912 len = sizeof(sin); 00913 00914 res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 00915 0, (struct sockaddr *)&sin, &len); 00916 rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET); 00917 00918 if (res < 0) { 00919 if (errno != EAGAIN) 00920 ast_log(LOG_WARNING, "RTCP Read error: %s\n", strerror(errno)); 00921 if (errno == EBADF) 00922 CRASH; 00923 return &ast_null_frame; 00924 } 00925 00926 packetwords = res / 4; 00927 00928 if (rtp->nat) { 00929 /* Send to whoever sent to us */ 00930 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00931 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00932 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 00933 if (option_debug || rtpdebug) 00934 ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00935 } 00936 } 00937 00938 if (option_debug) 00939 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00940 00941 /* Process a compound packet */ 00942 position = 0; 00943 while (position < packetwords) { 00944 i = position; 00945 length = ntohl(rtcpheader[i]); 00946 pt = (length & 0xff0000) >> 16; 00947 rc = (length & 0x1f000000) >> 24; 00948 length &= 0xffff; 00949 00950 if ((i + length) > packetwords) { 00951 ast_log(LOG_WARNING, "RTCP Read too short\n"); 00952 return &ast_null_frame; 00953 } 00954 00955 if (rtcp_debug_test_addr(&sin)) { 00956 ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 00957 ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown"); 00958 ast_verbose("Reception reports: %d\n", rc); 00959 ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]); 00960 } 00961 00962 i += 2; /* Advance past header and ssrc */ 00963 00964 switch (pt) { 00965 case RTCP_PT_SR: 00966 gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */ 00967 rtp->rtcp->spc = ntohl(rtcpheader[i+3]); 00968 rtp->rtcp->soc = ntohl(rtcpheader[i + 4]); 00969 rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff) >> 16); /* Going to LSR in RR*/ 00970 00971 if (rtcp_debug_test_addr(&sin)) { 00972 ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096); 00973 ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2])); 00974 ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4])); 00975 } 00976 i += 5; 00977 if (rc < 1) 00978 break; 00979 /* Intentional fall through */ 00980 case RTCP_PT_RR: 00981 /* This is the place to calculate RTT */ 00982 /* Don't handle multiple reception reports (rc > 1) yet */ 00983 gettimeofday(&now, NULL); 00984 timeval2ntp(now, &msw, &lsw); 00985 /* Use the one we sent them in our SR instead, rtcp->txlsr could have been rewritten if the dlsr is large */ 00986 if (ntohl(rtcpheader[i + 4])) { /* We must have the LSR */ 00987 comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16); 00988 a = (double)((comp & 0xffff0000) >> 16) + (double)((double)(comp & 0xffff)/1000000.); 00989 lsr = (double)((ntohl(rtcpheader[i + 4]) & 0xffff0000) >> 16) + (double)((double)(ntohl(rtcpheader[i + 4]) & 0xffff) / 1000000.); 00990 dlsr = (double)(ntohl(rtcpheader[i + 5])/65536.); 00991 rtt = a - dlsr - lsr; 00992 rtp->rtcp->accumulated_transit += rtt; 00993 rtp->rtcp->rtt = rtt; 00994 if (rtp->rtcp->maxrtt<rtt) 00995 rtp->rtcp->maxrtt = rtt; 00996 if (rtp->rtcp->minrtt>rtt) 00997 rtp->rtcp->minrtt = rtt; 00998 } 00999 rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]); 01000 rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff; 01001 if (rtcp_debug_test_addr(&sin)) { 01002 ast_verbose("Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24)); 01003 ast_verbose("Packets lost so far: %d\n", rtp->rtcp->reported_lost); 01004 ast_verbose("Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff)); 01005 ast_verbose("Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16); 01006 ast_verbose("Interarrival jitter: %u\n", rtp->rtcp->reported_jitter); 01007 ast_verbose("Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096); 01008 ast_verbose("DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0); 01009 if (rtt) 01010 ast_verbose("RTT: %f(sec)\n", rtt); 01011 } 01012 break; 01013 case RTCP_PT_FUR: 01014 if (rtcp_debug_test_addr(&sin)) 01015 ast_verbose("Received an RTCP Fast Update Request\n"); 01016 rtp->f.frametype = AST_FRAME_CONTROL; 01017 rtp->f.subclass = AST_CONTROL_VIDUPDATE; 01018 rtp->f.datalen = 0; 01019 rtp->f.samples = 0; 01020 rtp->f.mallocd = 0; 01021 rtp->f.src = "RTP"; 01022 f = &rtp->f; 01023 break; 01024 case RTCP_PT_SDES: 01025 if (rtcp_debug_test_addr(&sin)) 01026 ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01027 break; 01028 case RTCP_PT_BYE: 01029 if (rtcp_debug_test_addr(&sin)) 01030 ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01031 break; 01032 default: 01033 if (option_debug) 01034 ast_log(LOG_DEBUG, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 01035 break; 01036 } 01037 position += (length + 1); 01038 } 01039 01040 return f; 01041 }
|
|
|
Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
Definition at line 2329 of file rtp.c. References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur. 02330 { 02331 struct ast_rtp *rtp = data; 02332 int res; 02333 02334 rtp->rtcp->sendfur = 1; 02335 res = ast_rtcp_write(data); 02336 02337 return res; 02338 }
|
|
|
Write and RTCP packet to the far end.
Definition at line 2554 of file rtp.c. References ast_rtcp_write_rr(), ast_rtcp_write_sr(), ast_rtcp::lastsrtxcount, ast_rtp::rtcp, and ast_rtp::txcount. Referenced by ast_rtcp_send_h261fur(), ast_rtp_raw_write(), and ast_rtp_read(). 02555 { 02556 struct ast_rtp *rtp = data; 02557 int res; 02558 02559 if (rtp->txcount > rtp->rtcp->lastsrtxcount) 02560 res = ast_rtcp_write_sr(data); 02561 else 02562 res = ast_rtcp_write_rr(data); 02563 02564 return res; 02565 }
|
|
|
Send RTCP recipient's report.
Definition at line 2455 of file rtp.c. References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, and ast_rtp::themssrc. Referenced by ast_rtcp_write(). 02456 { 02457 struct ast_rtp *rtp = data; 02458 int res; 02459 int len = 32; 02460 unsigned int lost; 02461 unsigned int extended; 02462 unsigned int expected; 02463 unsigned int expected_interval; 02464 unsigned int received_interval; 02465 int lost_interval; 02466 struct timeval now; 02467 unsigned int *rtcpheader; 02468 char bdata[1024]; 02469 struct timeval dlsr; 02470 int fraction; 02471 02472 if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0)) 02473 return 0; 02474 02475 if (!rtp->rtcp->them.sin_addr.s_addr) { 02476 ast_log(LOG_ERROR, "RTCP RR transmission error to, rtcp halted %s\n",strerror(errno)); 02477 if (rtp->rtcp->schedid > 0) 02478 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02479 rtp->rtcp->schedid = -1; 02480 return 0; 02481 } 02482 02483 extended = rtp->cycles + rtp->lastrxseqno; 02484 expected = extended - rtp->seedrxseqno + 1; 02485 lost = expected - rtp->rxcount; 02486 expected_interval = expected - rtp->rtcp->expected_prior; 02487 rtp->rtcp->expected_prior = expected; 02488 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02489 rtp->rtcp->received_prior = rtp->rxcount; 02490 lost_interval = expected_interval - received_interval; 02491 if (expected_interval == 0 || lost_interval <= 0) 02492 fraction = 0; 02493 else 02494 fraction = (lost_interval << 8) / expected_interval; 02495 gettimeofday(&now, NULL); 02496 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02497 rtcpheader = (unsigned int *)bdata; 02498 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1)); 02499 rtcpheader[1] = htonl(rtp->ssrc); 02500 rtcpheader[2] = htonl(rtp->themssrc); 02501 rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02502 rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02503 rtcpheader[5] = htonl((unsigned int)rtp->rxjitter); 02504 rtcpheader[6] = htonl(rtp->rtcp->themrxlsr); 02505 rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02506 02507 if (rtp->rtcp->sendfur) { 02508 rtcpheader[8] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); /* Header from page 36 in RFC 3550 */ 02509 rtcpheader[9] = htonl(rtp->ssrc); /* Our SSRC */ 02510 len += 8; 02511 rtp->rtcp->sendfur = 0; 02512 } 02513 02514 /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos 02515 it can change mid call, and SDES can't) */ 02516 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02517 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02518 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02519 len += 12; 02520 02521 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02522 02523 if (res < 0) { 02524 ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno)); 02525 /* Remove the scheduler */ 02526 if (rtp->rtcp->schedid > 0) 02527 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02528 rtp->rtcp->schedid = -1; 02529 return 0; 02530 } 02531 02532 rtp->rtcp->rr_count++; 02533 02534 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02535 ast_verbose("\n* Sending RTCP RR to %s:%d\n" 02536 " Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n" 02537 " IA jitter: %.4f\n" 02538 " Their last SR: %u\n" 02539 " DLSR: %4.4f (sec)\n\n", 02540 ast_inet_ntoa(rtp->rtcp->them.sin_addr), 02541 ntohs(rtp->rtcp->them.sin_port), 02542 rtp->ssrc, rtp->themssrc, fraction, lost, 02543 rtp->rxjitter, 02544 rtp->rtcp->themrxlsr, 02545 (double)(ntohl(rtcpheader[7])/65536.0)); 02546 } 02547 02548 return res; 02549 }
|
|
|
Send RTCP sender's report.
Definition at line 2341 of file rtp.c. References ast_inet_ntoa(), ast_log(), ast_sched_del(), ast_verbose(), ast_rtp::cycles, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len, LOG_ERROR, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_FUR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sendfur, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount. Referenced by ast_rtcp_write(). 02342 { 02343 struct ast_rtp *rtp = data; 02344 int res; 02345 int len = 0; 02346 struct timeval now; 02347 unsigned int now_lsw; 02348 unsigned int now_msw; 02349 unsigned int *rtcpheader; 02350 unsigned int lost; 02351 unsigned int extended; 02352 unsigned int expected; 02353 unsigned int expected_interval; 02354 unsigned int received_interval; 02355 int lost_interval; 02356 int fraction; 02357 struct timeval dlsr; 02358 char bdata[512]; 02359 02360 /* Commented condition is always not NULL if rtp->rtcp is not NULL */ 02361 if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/) 02362 return 0; 02363 02364 if (!rtp->rtcp->them.sin_addr.s_addr) { /* This'll stop rtcp for this rtp session */ 02365 ast_verbose("RTCP SR transmission error, rtcp halted\n"); 02366 if (rtp->rtcp->schedid > 0) 02367 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02368 rtp->rtcp->schedid = -1; 02369 return 0; 02370 } 02371 02372 gettimeofday(&now, NULL); 02373 timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/ 02374 rtcpheader = (unsigned int *)bdata; 02375 rtcpheader[1] = htonl(rtp->ssrc); /* Our SSRC */ 02376 rtcpheader[2] = htonl(now_msw); /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/ 02377 rtcpheader[3] = htonl(now_lsw); /* now, LSW */ 02378 rtcpheader[4] = htonl(rtp->lastts); /* FIXME shouldn't be that, it should be now */ 02379 rtcpheader[5] = htonl(rtp->txcount); /* No. packets sent */ 02380 rtcpheader[6] = htonl(rtp->txoctetcount); /* No. bytes sent */ 02381 len += 28; 02382 02383 extended = rtp->cycles + rtp->lastrxseqno; 02384 expected = extended - rtp->seedrxseqno + 1; 02385 if (rtp->rxcount > expected) 02386 expected += rtp->rxcount - expected; 02387 lost = expected - rtp->rxcount; 02388 expected_interval = expected - rtp->rtcp->expected_prior; 02389 rtp->rtcp->expected_prior = expected; 02390 received_interval = rtp->rxcount - rtp->rtcp->received_prior; 02391 rtp->rtcp->received_prior = rtp->rxcount; 02392 lost_interval = expected_interval - received_interval; 02393 if (expected_interval == 0 || lost_interval <= 0) 02394 fraction = 0; 02395 else 02396 fraction = (lost_interval << 8) / expected_interval; 02397 timersub(&now, &rtp->rtcp->rxlsr, &dlsr); 02398 rtcpheader[7] = htonl(rtp->themssrc); 02399 rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff)); 02400 rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff))); 02401 rtcpheader[10] = htonl((unsigned int)rtp->rxjitter); 02402 rtcpheader[11] = htonl(rtp->rtcp->themrxlsr); 02403 rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000); 02404 len += 24; 02405 02406 rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1)); 02407 02408 if (rtp->rtcp->sendfur) { 02409 rtcpheader[13] = htonl((2 << 30) | (0 << 24) | (RTCP_PT_FUR << 16) | 1); 02410 rtcpheader[14] = htonl(rtp->ssrc); /* Our SSRC */ 02411 len += 8; 02412 rtp->rtcp->sendfur = 0; 02413 } 02414 02415 /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */ 02416 /* it can change mid call, and SDES can't) */ 02417 rtcpheader[len/4] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2); 02418 rtcpheader[(len/4)+1] = htonl(rtp->ssrc); /* Our SSRC */ 02419 rtcpheader[(len/4)+2] = htonl(0x01 << 24); /* Empty for the moment */ 02420 len += 12; 02421 02422 res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them)); 02423 if (res < 0) { 02424 ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno)); 02425 if (rtp->rtcp->schedid > 0) 02426 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02427 rtp->rtcp->schedid = -1; 02428 return 0; 02429 } 02430 02431 /* FIXME Don't need to get a new one */ 02432 gettimeofday(&rtp->rtcp->txlsr, NULL); 02433 rtp->rtcp->sr_count++; 02434 02435 rtp->rtcp->lastsrtxcount = rtp->txcount; 02436 02437 if (rtcp_debug_test_addr(&rtp->rtcp->them)) { 02438 ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 02439 ast_verbose(" Our SSRC: %u\n", rtp->ssrc); 02440 ast_verbose(" Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096); 02441 ast_verbose(" Sent(RTP): %u\n", rtp->lastts); 02442 ast_verbose(" Sent packets: %u\n", rtp->txcount); 02443 ast_verbose(" Sent octets: %u\n", rtp->txoctetcount); 02444 ast_verbose(" Report block:\n"); 02445 ast_verbose(" Fraction lost: %u\n", fraction); 02446 ast_verbose(" Cumulative loss: %u\n", lost); 02447 ast_verbose(" IA jitter: %.4f\n", rtp->rxjitter); 02448 ast_verbose(" Their last SR: %u\n", rtp->rtcp->themrxlsr); 02449 ast_verbose(" DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0)); 02450 } 02451 return res; 02452 }
|
|
|
Get the amount of space required to hold an RTP session.
Definition at line 399 of file rtp.c. Referenced by process_sdp(). 00400 { 00401 return sizeof(struct ast_rtp); 00402 }
|
|
||||||||||||||||||||||||||||
|
The RTP bridge.
Definition at line 3259 of file rtp.c. References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, option_debug, option_verbose, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3. 03260 { 03261 struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */ 03262 struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */ 03263 struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL; 03264 enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED; 03265 enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED; 03266 enum ast_bridge_result res = AST_BRIDGE_FAILED; 03267 int codec0 = 0, codec1 = 0; 03268 void *pvt0 = NULL, *pvt1 = NULL; 03269 03270 /* Lock channels */ 03271 ast_channel_lock(c0); 03272 while (ast_channel_trylock(c1)) { 03273 ast_channel_unlock(c0); 03274 usleep(1); 03275 ast_channel_lock(c0); 03276 } 03277 03278 /* Find channel driver interfaces */ 03279 if (!(pr0 = get_proto(c0))) { 03280 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 03281 ast_channel_unlock(c0); 03282 ast_channel_unlock(c1); 03283 return AST_BRIDGE_FAILED; 03284 } 03285 if (!(pr1 = get_proto(c1))) { 03286 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 03287 ast_channel_unlock(c0); 03288 ast_channel_unlock(c1); 03289 return AST_BRIDGE_FAILED; 03290 } 03291 03292 /* Get channel specific interface structures */ 03293 pvt0 = c0->tech_pvt; 03294 pvt1 = c1->tech_pvt; 03295 03296 /* Get audio and video interface (if native bridge is possible) */ 03297 audio_p0_res = pr0->get_rtp_info(c0, &p0); 03298 video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED; 03299 audio_p1_res = pr1->get_rtp_info(c1, &p1); 03300 video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED; 03301 03302 /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */ 03303 if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE)) 03304 audio_p0_res = AST_RTP_GET_FAILED; 03305 if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE)) 03306 audio_p1_res = AST_RTP_GET_FAILED; 03307 03308 /* Check if a bridge is possible (partial/native) */ 03309 if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) { 03310 /* Somebody doesn't want to play... */ 03311 ast_channel_unlock(c0); 03312 ast_channel_unlock(c1); 03313 return AST_BRIDGE_FAILED_NOWARN; 03314 } 03315 03316 /* If we need to feed DTMF frames into the core then only do a partial native bridge */ 03317 if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) { 03318 ast_set_flag(p0, FLAG_P2P_NEED_DTMF); 03319 audio_p0_res = AST_RTP_TRY_PARTIAL; 03320 } 03321 03322 if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) { 03323 ast_set_flag(p1, FLAG_P2P_NEED_DTMF); 03324 audio_p1_res = AST_RTP_TRY_PARTIAL; 03325 } 03326 03327 /* If both sides are not using the same method of DTMF transmission 03328 * (ie: one is RFC2833, other is INFO... then we can not do direct media. 03329 * -------------------------------------------------- 03330 * | DTMF Mode | HAS_DTMF | Accepts Begin Frames | 03331 * |-----------|------------|-----------------------| 03332 * | Inband | False | True | 03333 * | RFC2833 | True | True | 03334 * | SIP INFO | False | False | 03335 * -------------------------------------------------- 03336 * However, if DTMF from both channels is being monitored by the core, then 03337 * we can still do packet-to-packet bridging, because passing through the 03338 * core will handle DTMF mode translation. 03339 */ 03340 if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) || 03341 (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) { 03342 if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) { 03343 ast_channel_unlock(c0); 03344 ast_channel_unlock(c1); 03345 return AST_BRIDGE_FAILED_NOWARN; 03346 } 03347 audio_p0_res = AST_RTP_TRY_PARTIAL; 03348 audio_p1_res = AST_RTP_TRY_PARTIAL; 03349 } 03350 03351 /* Get codecs from both sides */ 03352 codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0; 03353 codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0; 03354 if (codec0 && codec1 && !(codec0 & codec1)) { 03355 /* Hey, we can't do native bridging if both parties speak different codecs */ 03356 if (option_debug > 2) 03357 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1); 03358 ast_channel_unlock(c0); 03359 ast_channel_unlock(c1); 03360 return AST_BRIDGE_FAILED_NOWARN; 03361 } 03362 03363 /* If either side can only do a partial bridge, then don't try for a true native bridge */ 03364 if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) { 03365 /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */ 03366 if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) { 03367 if (option_debug) 03368 ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n"); 03369 ast_channel_unlock(c0); 03370 ast_channel_unlock(c1); 03371 return AST_BRIDGE_FAILED_NOWARN; 03372 } 03373 if (option_verbose > 2) 03374 ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name); 03375 res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1); 03376 } else { 03377 if (option_verbose > 2) 03378 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03379 res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1); 03380 } 03381 03382 return res; 03383 }
|
|
|
get format from predefined dynamic payload format Definition at line 2711 of file rtp.c. References rtpPayloadType::code, MAX_RTP_PT, and static_RTP_PT. 02712 { 02713 if (pt < 0 || pt > MAX_RTP_PT) 02714 return 0; /* bogus payload type */ 02715 02716 if (static_RTP_PT[pt].isAstFormat) 02717 return static_RTP_PT[pt].code; 02718 else 02719 return 0; 02720 }
|
|
|
Get codec preference Definition at line 2706 of file rtp.c. References ast_rtp::pref. Referenced by add_codec_to_sdp(). 02707 { 02708 return &rtp->pref; 02709 }
|
|
||||||||||||
|
Set codec preference Definition at line 2693 of file rtp.c. References ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and prefs. Referenced by __oh323_rtp_create(), check_peer_ok(), check_user_full(), check_user_ok(), create_addr_from_peer(), register_verify(), set_peer_capabilities(), start_rtp(), transmit_response_with_attachment(), and transmit_response_with_sdp(). 02694 { 02695 int x; 02696 for (x = 0; x < 32; x++) { /* Ugly way */ 02697 rtp->pref.order[x] = prefs->order[x]; 02698 rtp->pref.framing[x] = prefs->framing[x]; 02699 } 02700 if (rtp->smoother) 02701 ast_smoother_free(rtp->smoother); 02702 rtp->smoother = NULL; 02703 return 0; 02704 }
|
|
|
||||||||||||
|
If possible, create an early bridge directly between the devices without having to send a re-invite later.
Definition at line 1522 of file rtp.c. References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer. 01523 { 01524 // dest = c0, src = c1 01525 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01526 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01527 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01528 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01529 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01530 int srccodec, nat_active = 0; 01531 01532 /* Lock channels */ 01533 ast_channel_lock(c0); 01534 if (c1) { 01535 while (ast_channel_trylock(c1)) { 01536 ast_channel_unlock(c0); 01537 usleep(1); 01538 ast_channel_lock(c0); 01539 } 01540 } 01541 01542 /* Find channel driver interfaces */ 01543 destpr = get_proto(c0); 01544 if (c1) 01545 srcpr = get_proto(c1); 01546 if (!destpr) { 01547 if (option_debug) 01548 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c0->name); 01549 ast_channel_unlock(c0); 01550 if (c1) 01551 ast_channel_unlock(c1); 01552 return -1; 01553 } 01554 if (!srcpr) { 01555 if (option_debug) 01556 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>"); 01557 ast_channel_unlock(c0); 01558 if (c1) 01559 ast_channel_unlock(c1); 01560 return -1; 01561 } 01562 01563 /* Get audio and video interface (if native bridge is possible) */ 01564 audio_dest_res = destpr->get_rtp_info(c0, &destp); 01565 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED; 01566 if (srcpr) { 01567 audio_src_res = srcpr->get_rtp_info(c1, &srcp); 01568 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED; 01569 } 01570 01571 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01572 if (audio_dest_res != AST_RTP_TRY_NATIVE) { 01573 /* Somebody doesn't want to play... */ 01574 ast_channel_unlock(c0); 01575 if (c1) 01576 ast_channel_unlock(c1); 01577 return -1; 01578 } 01579 if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec) 01580 srccodec = srcpr->get_codec(c1); 01581 else 01582 srccodec = 0; 01583 /* Consider empty media as non-existant */ 01584 if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr) 01585 srcp = NULL; 01586 if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01587 nat_active = 1; 01588 /* Bridge media early */ 01589 if (destpr->set_rtp_peer(c0, srcp, vsrcp, srccodec, nat_active)) 01590 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 01591 ast_channel_unlock(c0); 01592 if (c1) 01593 ast_channel_unlock(c1); 01594 if (option_debug) 01595 ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>"); 01596 return 0; 01597 }
|
|
|
Definition at line 514 of file rtp.c. References ast_rtp::s. Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), jingle_new(), mgcp_new(), p2p_callback_disable(), sip_new(), skinny_new(), and start_rtp(). 00515 { 00516 return rtp->s; 00517 }
|
|
|
Definition at line 2045 of file rtp.c. References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock(). Referenced by ast_rtp_read(), and check_rtp_timeout(). 02046 { 02047 struct ast_rtp *bridged = NULL; 02048 02049 rtp_bridge_lock(rtp); 02050 bridged = rtp->bridged; 02051 rtp_bridge_unlock(rtp); 02052 02053 return bridged; 02054 }
|
|
||||||||||||||||
|
Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
Definition at line 1711 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock(). Referenced by process_sdp(). 01713 { 01714 int pt; 01715 01716 rtp_bridge_lock(rtp); 01717 01718 *astFormats = *nonAstFormats = 0; 01719 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01720 if (rtp->current_RTP_PT[pt].isAstFormat) { 01721 *astFormats |= rtp->current_RTP_PT[pt].code; 01722 } else { 01723 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 01724 } 01725 } 01726 01727 rtp_bridge_unlock(rtp); 01728 01729 return; 01730 }
|
|
||||||||||||
|
Definition at line 2027 of file rtp.c. References ast_rtp::them. Referenced by add_sdp(), bridge_native_loop(), check_rtp_timeout(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp(). 02028 { 02029 if ((them->sin_family != AF_INET) || 02030 (them->sin_port != rtp->them.sin_port) || 02031 (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) { 02032 them->sin_family = AF_INET; 02033 them->sin_port = rtp->them.sin_port; 02034 them->sin_addr = rtp->them.sin_addr; 02035 return 1; 02036 } 02037 return 0; 02038 }
|
|
|
Definition at line 2093 of file rtp.c. References ast_rtcp::expected_prior, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount. Referenced by handle_request_bye(), and sip_hangup(). 02094 { 02095 /* 02096 *ssrc our ssrc 02097 *themssrc their ssrc 02098 *lp lost packets 02099 *rxjitter our calculated jitter(rx) 02100 *rxcount no. received packets 02101 *txjitter reported jitter of the other end 02102 *txcount transmitted packets 02103 *rlp remote lost packets 02104 */ 02105 02106 snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt); 02107 02108 return rtp->rtcp->quality; 02109 }
|
|
|
Get rtp hold timeout.
Definition at line 569 of file rtp.c. References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout. Referenced by check_rtp_timeout(). 00570 { 00571 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00572 return 0; 00573 return rtp->rtpholdtimeout; 00574 }
|
|
|
Get RTP keepalive interval.
Definition at line 577 of file rtp.c. References ast_rtp::rtpkeepalive. Referenced by check_rtp_timeout(). 00578 { 00579 return rtp->rtpkeepalive; 00580 }
|
|
|
Get rtp timeout.
Definition at line 561 of file rtp.c. References ast_rtp::rtptimeout. Referenced by check_rtp_timeout(). 00562 { 00563 if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ 00564 return 0; 00565 return rtp->rtptimeout; 00566 }
|
|
||||||||||||
|
Definition at line 2040 of file rtp.c. References ast_rtp::us. Referenced by add_sdp(), external_rtp_create(), get_our_media_address(), handle_open_receive_channel_ack_message(), and oh323_set_rtp_peer().
|
|
|
Definition at line 597 of file rtp.c. References ast_test_flag, and FLAG_NAT_ACTIVE. Referenced by sip_get_rtp_peer(). 00598 { 00599 return ast_test_flag(rtp, FLAG_NAT_ACTIVE); 00600 }
|
|
|
Return RTCP quality string.
Definition at line 3664 of file rtp.c. References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp. 03665 { 03666 ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry)); 03667 ast_rtp_reload(); 03668 }
|
|
||||||||||||||||
|
Looks up an RTP code out of our *static* outbound list.
Definition at line 1754 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result. Referenced by add_codec_to_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write(). 01755 { 01756 int pt = 0; 01757 01758 rtp_bridge_lock(rtp); 01759 01760 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 01761 code == rtp->rtp_lookup_code_cache_code) { 01762 /* Use our cached mapping, to avoid the overhead of the loop below */ 01763 pt = rtp->rtp_lookup_code_cache_result; 01764 rtp_bridge_unlock(rtp); 01765 return pt; 01766 } 01767 01768 /* Check the dynamic list first */ 01769 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01770 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 01771 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01772 rtp->rtp_lookup_code_cache_code = code; 01773 rtp->rtp_lookup_code_cache_result = pt; 01774 rtp_bridge_unlock(rtp); 01775 return pt; 01776 } 01777 } 01778 01779 /* Then the static list */ 01780 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 01781 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) { 01782 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 01783 rtp->rtp_lookup_code_cache_code = code; 01784 rtp->rtp_lookup_code_cache_result = pt; 01785 rtp_bridge_unlock(rtp); 01786 return pt; 01787 } 01788 } 01789 01790 rtp_bridge_unlock(rtp); 01791 01792 return -1; 01793 }
|
|
||||||||||||||||||||||||
|
Build a string of MIME subtype names from a capability list.
Definition at line 1814 of file rtp.c. References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, len, and name. 01816 { 01817 int format; 01818 unsigned len; 01819 char *end = buf; 01820 char *start = buf; 01821 01822 if (!buf || !size) 01823 return NULL; 01824 01825 snprintf(end, size, "0x%x (", capability); 01826 01827 len = strlen(end); 01828 end += len; 01829 size -= len; 01830 start = end; 01831 01832 for (format = 1; format < AST_RTP_MAX; format <<= 1) { 01833 if (capability & format) { 01834 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options); 01835 01836 snprintf(end, size, "%s|", name); 01837 len = strlen(end); 01838 end += len; 01839 size -= len; 01840 } 01841 } 01842 01843 if (start == end) 01844 snprintf(start, size, "nothing)"); 01845 else if (size > 1) 01846 *(end -1) = ')'; 01847 01848 return buf; 01849 }
|
|
||||||||||||||||
|
Mapping an Asterisk code into a MIME subtype (string):.
Definition at line 1795 of file rtp.c. References AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, mimeTypes, and payloadType. Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp(). 01797 { 01798 unsigned int i; 01799 01800 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01801 if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) { 01802 if (isAstFormat && 01803 (code == AST_FORMAT_G726_AAL2) && 01804 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01805 return "G726-32"; 01806 else 01807 return mimeTypes[i].subtype; 01808 } 01809 } 01810 01811 return ""; 01812 }
|
|
||||||||||||
|
Mapping between RTP payload format codes and Asterisk codes:.
Definition at line 1732 of file rtp.c. Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection(). 01733 { 01734 struct rtpPayloadType result; 01735 01736 result.isAstFormat = result.code = 0; 01737 01738 if (pt < 0 || pt > MAX_RTP_PT) 01739 return result; /* bogus payload type */ 01740 01741 /* Start with negotiated codecs */ 01742 rtp_bridge_lock(rtp); 01743 result = rtp->current_RTP_PT[pt]; 01744 rtp_bridge_unlock(rtp); 01745 01746 /* If it doesn't exist, check our static RTP type list, just in case */ 01747 if (!result.code) 01748 result = static_RTP_PT[pt]; 01749 01750 return result; 01751 }
|
|
||||||||||||||||
|
Definition at line 1599 of file rtp.c. References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, ast_rtp_pt_copy(), AST_RTP_TRY_NATIVE, ast_test_flag, FLAG_NAT_ACTIVE, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer. 01600 { 01601 struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */ 01602 struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */ 01603 struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL; 01604 enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED; 01605 enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 01606 int srccodec; 01607 01608 /* Lock channels */ 01609 ast_channel_lock(dest); 01610 while (ast_channel_trylock(src)) { 01611 ast_channel_unlock(dest); 01612 usleep(1); 01613 ast_channel_lock(dest); 01614 } 01615 01616 /* Find channel driver interfaces */ 01617 if (!(destpr = get_proto(dest))) { 01618 if (option_debug) 01619 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name); 01620 ast_channel_unlock(dest); 01621 ast_channel_unlock(src); 01622 return 0; 01623 } 01624 if (!(srcpr = get_proto(src))) { 01625 if (option_debug) 01626 ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name); 01627 ast_channel_unlock(dest); 01628 ast_channel_unlock(src); 01629 return 0; 01630 } 01631 01632 /* Get audio and video interface (if native bridge is possible) */ 01633 audio_dest_res = destpr->get_rtp_info(dest, &destp); 01634 video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED; 01635 audio_src_res = srcpr->get_rtp_info(src, &srcp); 01636 video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED; 01637 01638 /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */ 01639 if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE) { 01640 /* Somebody doesn't want to play... */ 01641 ast_channel_unlock(dest); 01642 ast_channel_unlock(src); 01643 return 0; 01644 } 01645 ast_rtp_pt_copy(destp, srcp); 01646 if (vdestp && vsrcp) 01647 ast_rtp_pt_copy(vdestp, vsrcp); 01648 if (srcpr->get_codec) 01649 srccodec = srcpr->get_codec(src); 01650 else 01651 srccodec = 0; 01652 if (media) { 01653 /* Bridge early */ 01654 if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE))) 01655 ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name); 01656 } 01657 ast_channel_unlock(dest); 01658 ast_channel_unlock(src); 01659 if (option_debug) 01660 ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name); 01661 return 1; 01662 }
|
|
||||||||||||||||||||
|
Initializate a RTP session.
Definition at line 1999 of file rtp.c. References ast_rtp_new_with_bindaddr(), io, and sched. 02000 { 02001 struct in_addr ia; 02002 02003 memset(&ia, 0, sizeof(ia)); 02004 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 02005 }
|
|
|
Initialize a new RTP structure. reload rtp configuration Definition at line 1896 of file rtp.c. References ast_mutex_init(), ast_random(), ast_set_flag, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, and ast_rtp::us. Referenced by ast_rtp_new_with_bindaddr(), and process_sdp(). 01897 { 01898 #ifdef P2P_INTENSE 01899 ast_mutex_init(&rtp->bridge_lock); 01900 #endif 01901 01902 rtp->them.sin_family = AF_INET; 01903 rtp->us.sin_family = AF_INET; 01904 rtp->ssrc = ast_random(); 01905 rtp->seqno = ast_random() & 0xffff; 01906 ast_set_flag(rtp, FLAG_HAS_DTMF); 01907 01908 return; 01909 }
|
|
||||||||||||||||||||||||
|
Initializate a RTP session using an in_addr structure. This fuction gets called by ast_rtp_new().
Definition at line 1911 of file rtp.c. References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), free, LOG_ERROR, rtp_socket(), rtpend, rtpstart, and sched. Referenced by __oh323_rtp_create(), ast_rtp_new(), dialog_activate_media(), gtalk_alloc(), jingle_alloc(), sip_alloc(), and start_rtp(). 01912 { 01913 struct ast_rtp *rtp; 01914 int x; 01915 int first; 01916 int startplace; 01917 01918 if (!(rtp = ast_calloc(1, sizeof(*rtp)))) 01919 return NULL; 01920 01921 ast_rtp_new_init(rtp); 01922 01923 rtp->s = rtp_socket(); 01924 if (rtp->s < 0) { 01925 free(rtp); 01926 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno)); 01927 return NULL; 01928 } 01929 if (sched && rtcpenable) { 01930 rtp->sched = sched; 01931 rtp->rtcp = ast_rtcp_new(); 01932 } 01933 01934 /* Select a random port number in the range of possible RTP */ 01935 x = (ast_random() % (rtpend-rtpstart)) + rtpstart; 01936 x = x & ~1; 01937 /* Save it for future references. */ 01938 startplace = x; 01939 /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */ 01940 for (;;) { 01941 /* Must be an even port number by RTP spec */ 01942 rtp->us.sin_port = htons(x); 01943 rtp->us.sin_addr = addr; 01944 01945 /* If there's rtcp, initialize it as well. */ 01946 if (rtp->rtcp) { 01947 rtp->rtcp->us.sin_port = htons(x + 1); 01948 rtp->rtcp->us.sin_addr = addr; 01949 } 01950 /* Try to bind it/them. */ 01951 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 01952 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 01953 break; 01954 if (!first) { 01955 /* Primary bind succeeded! Gotta recreate it */ 01956 close(rtp->s); 01957 rtp->s = rtp_socket(); 01958 } 01959 if (errno != EADDRINUSE) { 01960 /* We got an error that wasn't expected, abort! */ 01961 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno)); 01962 close(rtp->s); 01963 if (rtp->rtcp) { 01964 close(rtp->rtcp->s); 01965 free(rtp->rtcp); 01966 } 01967 free(rtp); 01968 return NULL; 01969 } 01970 /* The port was used, increment it (by two). */ 01971 x += 2; 01972 /* Did we go over the limit ? */ 01973 if (x > rtpend) 01974 /* then, start from the begingig. */ 01975 x = (rtpstart + 1) & ~1; 01976 /* Check if we reached the place were we started. */ 01977 if (x == startplace) { 01978 /* If so, there's no ports available. */ 01979 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n"); 01980 close(rtp->s); 01981 if (rtp->rtcp) { 01982 close(rtp->rtcp->s); 01983 free(rtp->rtcp); 01984 } 01985 free(rtp); 01986 return NULL; 01987 } 01988 } 01989 rtp->sched = sched; 01990 rtp->io = io; 01991 if (callbackmode) { 01992 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 01993 ast_set_flag(rtp, FLAG_CALLBACK_MODE); 01994 } 01995 ast_rtp_pt_default(rtp); 01996 return rtp; 01997 }
|
|
|
Register an RTP channel client.
Definition at line 2809 of file rtp.c. References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, protos, and ast_rtp_protocol::type. Referenced by load_module(), and register_rtp_and_udptl(). 02810 { 02811 struct ast_rtp_protocol *cur; 02812 02813 AST_RWLIST_WRLOCK(&protos); 02814 AST_RWLIST_TRAVERSE(&protos, cur, list) { 02815 if (!strcmp(cur->type, proto->type)) { 02816 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 02817 AST_RWLIST_UNLOCK(&protos); 02818 return -1; 02819 } 02820 } 02821 AST_RWLIST_INSERT_HEAD(&protos, proto, list); 02822 AST_RWLIST_UNLOCK(&protos); 02823 02824 return 0; 02825 }
|
|
|
Unregister an RTP channel client.
Definition at line 2801 of file rtp.c. References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and protos. Referenced by load_module(), unload_module(), and unregister_rtp_and_udptl(). 02802 { 02803 AST_RWLIST_WRLOCK(&protos); 02804 AST_RWLIST_REMOVE(&protos, proto, list); 02805 AST_RWLIST_UNLOCK(&protos); 02806 }
|
|
|
Setting RTP payload types from lines in a SDP description:.
Definition at line 1446 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock(). Referenced by process_sdp(). 01447 { 01448 int i; 01449 01450 if (!rtp) 01451 return; 01452 01453 rtp_bridge_lock(rtp); 01454 01455 for (i = 0; i < MAX_RTP_PT; ++i) { 01456 rtp->current_RTP_PT[i].isAstFormat = 0; 01457 rtp->current_RTP_PT[i].code = 0; 01458 } 01459 01460 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01461 rtp->rtp_lookup_code_cache_code = 0; 01462 rtp->rtp_lookup_code_cache_result = 0; 01463 01464 rtp_bridge_unlock(rtp); 01465 }
|
|
||||||||||||
|
Copy payload types between RTP structures.
Definition at line 1486 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock(). Referenced by ast_rtp_make_compatible(). 01487 { 01488 unsigned int i; 01489 01490 rtp_bridge_lock(dest); 01491 rtp_bridge_lock(src); 01492 01493 for (i=0; i < MAX_RTP_PT; ++i) { 01494 dest->current_RTP_PT[i].isAstFormat = 01495 src->current_RTP_PT[i].isAstFormat; 01496 dest->current_RTP_PT[i].code = 01497 src->current_RTP_PT[i].code; 01498 } 01499 dest->rtp_lookup_code_cache_isAstFormat = 0; 01500 dest->rtp_lookup_code_cache_code = 0; 01501 dest->rtp_lookup_code_cache_result = 0; 01502 01503 rtp_bridge_unlock(src); 01504 rtp_bridge_unlock(dest); 01505 }
|
|
|
Set payload types to defaults.
Definition at line 1467 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), and static_RTP_PT. 01468 { 01469 int i; 01470 01471 rtp_bridge_lock(rtp); 01472 01473 /* Initialize to default payload types */ 01474 for (i = 0; i < MAX_RTP_PT; ++i) { 01475 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 01476 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 01477 } 01478 01479 rtp->rtp_lookup_code_cache_isAstFormat = 0; 01480 rtp->rtp_lookup_code_cache_code = 0; 01481 rtp->rtp_lookup_code_cache_result = 0; 01482 01483 rtp_bridge_unlock(rtp); 01484 }
|
|
||||||||||||||||
|
Write RTP packet with audio or video media frames into UDP packet.
Definition at line 2603 of file rtp.c. References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_rtcp_calc_interval(), ast_rtcp_write(), ast_sched_add(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_frame::has_timing_info, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtpdebug, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_rtp::them, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount. Referenced by ast_rtp_write(). 02604 { 02605 unsigned char *rtpheader; 02606 int hdrlen = 12; 02607 int res; 02608 unsigned int ms; 02609 int pred; 02610 int mark = 0; 02611 02612 ms = calc_txstamp(rtp, &f->delivery); 02613 /* Default prediction */ 02614 if (f->subclass < AST_FORMAT_MAX_AUDIO) { 02615 pred = rtp->lastts + f->samples; 02616 02617 /* Re-calculate last TS */ 02618 rtp->lastts = rtp->lastts + ms * 8; 02619 if (ast_tvzero(f->delivery)) { 02620 /* If this isn't an absolute delivery time, Check if it is close to our prediction, 02621 and if so, go with our prediction */ 02622 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) 02623 rtp->lastts = pred; 02624 else { 02625 if (option_debug > 2) 02626 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); 02627 mark = 1; 02628 } 02629 } 02630 } else { 02631 mark = f->subclass & 0x1; 02632 pred = rtp->lastovidtimestamp + f->samples; 02633 /* Re-calculate last TS */ 02634 rtp->lastts = rtp->lastts + ms * 90; 02635 /* If it's close to our prediction, go for it */ 02636 if (ast_tvzero(f->delivery)) { 02637 if (abs(rtp->lastts - pred) < 7200) { 02638 rtp->lastts = pred; 02639 rtp->lastovidtimestamp += f->samples; 02640 } else { 02641 if (option_debug > 2) 02642 ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples); 02643 rtp->lastovidtimestamp = rtp->lastts; 02644 } 02645 } 02646 } 02647 /* If the timestamp for non-digit packets has moved beyond the timestamp 02648 for digits, update the digit timestamp. 02649 */ 02650 if (rtp->lastts > rtp->lastdigitts) 02651 rtp->lastdigitts = rtp->lastts; 02652 02653 if (f->has_timing_info) 02654 rtp->lastts = f->ts * 8; 02655 02656 /* Get a pointer to the header */ 02657 rtpheader = (unsigned char *)(f->data - hdrlen); 02658 02659 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23))); 02660 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts)); 02661 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc)); 02662 02663 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02664 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02665 if (res <0) { 02666 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) { 02667 if (option_debug) 02668 ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 02669 } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) { 02670 /* Only give this error message once if we are not RTP debugging */ 02671 if (option_debug || rtpdebug) 02672 ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 02673 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN); 02674 } 02675 } else { 02676 rtp->txcount++; 02677 rtp->txoctetcount +=(res - hdrlen); 02678 02679 if (rtp->rtcp && rtp->rtcp->schedid < 1) 02680 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 02681 } 02682 02683 if (rtp_debug_test_addr(&rtp->them)) 02684 ast_verbose("Sent RTP packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02685 ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen); 02686 } 02687 02688 rtp->seqno++; 02689 02690 return 0; 02691 }
|
|
|
Definition at line 1144 of file rtp.c. References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, CRASH, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, event, ext, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_frame::has_timing_info, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len, ast_frame::len, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::rtcp, rtp_debug_test_addr(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtp::them, ast_rtcp::them, ast_rtp::themssrc, and ast_frame::ts. Referenced by gtalk_rtp_read(), jingle_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read(). 01145 { 01146 int res; 01147 struct sockaddr_in sin; 01148 socklen_t len; 01149 unsigned int seqno; 01150 int version; 01151 int payloadtype; 01152 int tseqno; 01153 int hdrlen = 12; 01154 int padding; 01155 int mark; 01156 int ext; 01157 unsigned int ssrc; 01158 unsigned int timestamp; 01159 unsigned int *rtpheader; 01160 struct rtpPayloadType rtpPT; 01161 struct ast_rtp *bridged = NULL; 01162 01163 /* If time is up, kill it */ 01164 if (rtp->sending_digit) 01165 ast_rtp_senddigit_continuation(rtp); 01166 01167 len = sizeof(sin); 01168 01169 /* Cache where the header will go */ 01170 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 01171 0, (struct sockaddr *)&sin, &len); 01172 01173 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 01174 if (res < 0) { 01175 if (errno != EAGAIN) 01176 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 01177 if (errno == EBADF) 01178 CRASH; 01179 return &ast_null_frame; 01180 } 01181 01182 if (res < hdrlen) { 01183 ast_log(LOG_WARNING, "RTP Read too short\n"); 01184 return &ast_null_frame; 01185 } 01186 01187 /* Get fields */ 01188 seqno = ntohl(rtpheader[0]); 01189 01190 /* Check RTP version */ 01191 version = (seqno & 0xC0000000) >> 30; 01192 if (!version) { 01193 if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) && 01194 (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) { 01195 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 01196 } 01197 return &ast_null_frame; 01198 } 01199 01200 #if 0 /* Allow to receive RTP stream with closed transmission path */ 01201 /* If we don't have the other side's address, then ignore this */ 01202 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 01203 return &ast_null_frame; 01204 #endif 01205 01206 /* Send to whoever send to us if NAT is turned on */ 01207 if (rtp->nat) { 01208 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 01209 (rtp->them.sin_port != sin.sin_port)) { 01210 rtp->them = sin; 01211 if (rtp->rtcp) { 01212 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them)); 01213 rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1); 01214 } 01215 rtp->rxseqno = 0; 01216 ast_set_flag(rtp, FLAG_NAT_ACTIVE); 01217 if (option_debug || rtpdebug) 01218 ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 01219 } 01220 } 01221 01222 /* If we are bridged to another RTP stream, send direct */ 01223 if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen)) 01224 return &ast_null_frame; 01225 01226 if (version != 2) 01227 return &ast_null_frame; 01228 01229 payloadtype = (seqno & 0x7f0000) >> 16; 01230 padding = seqno & (1 << 29); 01231 mark = seqno & (1 << 23); 01232 ext = seqno & (1 << 28); 01233 seqno &= 0xffff; 01234 timestamp = ntohl(rtpheader[1]); 01235 ssrc = ntohl(rtpheader[2]); 01236 01237 if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { 01238 if (option_debug || rtpdebug) 01239 ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n"); 01240 mark = 1; 01241 } 01242 01243 rtp->rxssrc = ssrc; 01244 01245 if (padding) { 01246 /* Remove padding bytes */ 01247 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1]; 01248 } 01249 01250 if (ext) { 01251 /* RTP Extension present */ 01252 hdrlen += 4; 01253 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2; 01254 if (option_debug) { 01255 int profile; 01256 profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16; 01257 if (profile == 0x505a) 01258 ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n"); 01259 else 01260 ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile); 01261 } 01262 } 01263 01264 if (res < hdrlen) { 01265 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 01266 return &ast_null_frame; 01267 } 01268 01269 rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */ 01270 01271 tseqno = rtp->lastrxseqno +1; 01272 01273 if (rtp->rxcount==1) { 01274 /* This is the first RTP packet successfully received from source */ 01275 rtp->seedrxseqno = seqno; 01276 } 01277 01278 /* Do not schedule RR if RTCP isn't run */ 01279 if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) { 01280 /* Schedule transmission of Receiver Report */ 01281 rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp); 01282 } 01283 01284 if (tseqno > RTP_SEQ_MOD) { /* if tseqno is greater than RTP_SEQ_MOD it would indicate that the sender cycled */ 01285 rtp->cycles += RTP_SEQ_MOD; 01286 ast_verbose("SEQNO cycled: %u\t%d\n", rtp->cycles, seqno); 01287 } 01288 01289 rtp->lastrxseqno = seqno; 01290 01291 if (rtp->themssrc==0) 01292 rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */ 01293 01294 if (rtp_debug_test_addr(&sin)) 01295 ast_verbose("Got RTP packet from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 01296 ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 01297 01298 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 01299 if (!rtpPT.isAstFormat) { 01300 struct ast_frame *f = NULL; 01301 01302 /* This is special in-band data that's not one of our codecs */ 01303 if (rtpPT.code == AST_RTP_DTMF) { 01304 /* It's special -- rfc2833 process it */ 01305 if (rtp_debug_test_addr(&sin)) { 01306 unsigned char *data; 01307 unsigned int event; 01308 unsigned int event_end; 01309 unsigned int duration; 01310 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen; 01311 event = ntohl(*((unsigned int *)(data))); 01312 event >>= 24; 01313 event_end = ntohl(*((unsigned int *)(data))); 01314 event_end <<= 8; 01315 event_end >>= 24; 01316 duration = ntohl(*((unsigned int *)(data))); 01317 duration &= 0xFFFF; 01318 ast_verbose("Got RTP RFC2833 from %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration); 01319 } 01320 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno); 01321 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 01322 /* It's really special -- process it the Cisco way */ 01323 if (rtp->lasteventseqn <= seqno || (rtp->lasteventseqn >= 65530 && seqno <= 6)) { 01324 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01325 rtp->lasteventseqn = seqno; 01326 } 01327 } else if (rtpPT.code == AST_RTP_CN) { 01328 /* Comfort Noise */ 01329 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 01330 } else { 01331 ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr)); 01332 } 01333 return f ? f : &ast_null_frame; 01334 } 01335 rtp->lastrxformat = rtp->f.subclass = rtpPT.code; 01336 rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; 01337 01338 if (!rtp->lastrxts) 01339 rtp->lastrxts = timestamp; 01340 01341 rtp->rxseqno = seqno; 01342 01343 /* Record received timestamp as last received now */ 01344 rtp->lastrxts = timestamp; 01345 01346 rtp->f.mallocd = 0; 01347 rtp->f.datalen = res - hdrlen; 01348 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 01349 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 01350 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 01351 rtp->f.samples = ast_codec_get_samples(&rtp->f); 01352 if (rtp->f.subclass == AST_FORMAT_SLINEAR) 01353 ast_frame_byteswap_be(&rtp->f); 01354 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 01355 /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ 01356 rtp->f.has_timing_info = 1; 01357 rtp->f.ts = timestamp / 8; 01358 rtp->f.len = rtp->f.samples / 8; 01359 rtp->f.seqno = seqno; 01360 } else { 01361 /* Video -- samples is # of samples vs. 90000 */ 01362 if (!rtp->lastividtimestamp) 01363 rtp->lastividtimestamp = timestamp; 01364 rtp->f.samples = timestamp - rtp->lastividtimestamp; 01365 rtp->lastividtimestamp = timestamp; 01366 rtp->f.delivery.tv_sec = 0; 01367 rtp->f.delivery.tv_usec = 0; 01368 if (mark) 01369 rtp->f.subclass |= 0x1; 01370 01371 } 01372 rtp->f.src = "RTP"; 01373 return &rtp->f; 01374 }
|
|
|
Initialize RTP subsystem Definition at line 3599 of file rtp.c. References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, dtmftimeout, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, s, and VERBOSE_PREFIX_2. Referenced by ast_rtp_init(). 03600 { 03601 struct ast_config *cfg; 03602 const char *s; 03603 03604 rtpstart = 5000; 03605 rtpend = 31000; 03606 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03607 cfg = ast_config_load("rtp.conf"); 03608 if (cfg) { 03609 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 03610 rtpstart = atoi(s); 03611 if (rtpstart < 1024) 03612 rtpstart = 1024; 03613 if (rtpstart > 65535) 03614 rtpstart = 65535; 03615 } 03616 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 03617 rtpend = atoi(s); 03618 if (rtpend < 1024) 03619 rtpend = 1024; 03620 if (rtpend > 65535) 03621 rtpend = 65535; 03622 } 03623 if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) { 03624 rtcpinterval = atoi(s); 03625 if (rtcpinterval == 0) 03626 rtcpinterval = 0; /* Just so we're clear... it's zero */ 03627 if (rtcpinterval < RTCP_MIN_INTERVALMS) 03628 rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */ 03629 if (rtcpinterval > RTCP_MAX_INTERVALMS) 03630 rtcpinterval = RTCP_MAX_INTERVALMS; 03631 } 03632 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 03633 #ifdef SO_NO_CHECK 03634 if (ast_false(s)) 03635 nochecksums = 1; 03636 else 03637 nochecksums = 0; 03638 #else 03639 if (ast_false(s)) 03640 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 03641 #endif 03642 } 03643 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) { 03644 dtmftimeout = atoi(s); 03645 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) { 03646 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n", 03647 dtmftimeout, DEFAULT_DTMF_TIMEOUT); 03648 dtmftimeout = DEFAULT_DTMF_TIMEOUT; 03649 }; 03650 } 03651 ast_config_destroy(cfg); 03652 } 03653 if (rtpstart >= rtpend) { 03654 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n"); 03655 rtpstart = 5000; 03656 rtpend = 31000; 03657 } 03658 if (option_verbose > 1) 03659 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 03660 return 0; 03661 }
|
|
|
Definition at line 2073 of file rtp.c. References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lasteventendseqn, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore. 02074 { 02075 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore)); 02076 memset(&rtp->txcore, 0, sizeof(rtp->txcore)); 02077 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute)); 02078 rtp->lastts = 0; 02079 rtp->lastdigitts = 0; 02080 rtp->lastrxts = 0; 02081 rtp->lastividtimestamp = 0; 02082 rtp->lastovidtimestamp = 0; 02083 rtp->lasteventseqn = 0; 02084 rtp->lasteventendseqn = 0; 02085 rtp->lasttxformat = 0; 02086 rtp->lastrxformat = 0; 02087 rtp->dtmfcount = 0; 02088 rtp->dtmfsamples = 0; 02089 rtp->seqno = 0; 02090 rtp->rxseqno = 0; 02091 }
|
|
||||||||||||
|
generate comfort noice (CNG)
Definition at line 2568 of file rtp.c. References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them. Referenced by check_rtp_timeout(). 02569 { 02570 unsigned int *rtpheader; 02571 int hdrlen = 12; 02572 int res; 02573 int payload; 02574 char data[256]; 02575 level = 127 - (level & 0x7f); 02576 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); 02577 02578 /* If we have no peer, return immediately */ 02579 if (!rtp->them.sin_addr.s_addr) 02580 return 0; 02581 02582 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02583 02584 /* Get a pointer to the header */ 02585 rtpheader = (unsigned int *)data; 02586 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 02587 rtpheader[1] = htonl(rtp->lastts); 02588 rtpheader[2] = htonl(rtp->ssrc); 02589 data[12] = level; 02590 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 02591 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 02592 if (res <0) 02593 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 02594 if (rtp_debug_test_addr(&rtp->them)) 02595 ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n" 02596 , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); 02597 02598 } 02599 return 0; 02600 }
|
|
||||||||||||
|
Send begin frames for DTMF.
Definition at line 2171 of file rtp.c. References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_duration, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them. Referenced by oh323_digit_begin(), and sip_senddigit_begin(). 02172 { 02173 unsigned int *rtpheader; 02174 int hdrlen = 12, res = 0, i = 0, payload = 0; 02175 char data[256]; 02176 02177 if ((digit <= '9') && (digit >= '0')) 02178 digit -= '0'; 02179 else if (digit == '*') 02180 digit = 10; 02181 else if (digit == '#') 02182 digit = 11; 02183 else if ((digit >= 'A') && (digit <= 'D')) 02184 digit = digit - 'A' + 12; 02185 else if ((digit >= 'a') && (digit <= 'd')) 02186 digit = digit - 'a' + 12; 02187 else { 02188 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02189 return 0; 02190 } 02191 02192 /* If we have no peer, return immediately */ 02193 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02194 return 0; 02195 02196 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 02197 02198 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02199 rtp->send_duration = 160; 02200 02201 /* Get a pointer to the header */ 02202 rtpheader = (unsigned int *)data; 02203 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno)); 02204 rtpheader[1] = htonl(rtp->lastdigitts); 02205 rtpheader[2] = htonl(rtp->ssrc); 02206 02207 for (i = 0; i < 2; i++) { 02208 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02209 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02210 if (res < 0) 02211 ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n", 02212 ast_inet_ntoa(rtp->them.sin_addr), 02213 ntohs(rtp->them.sin_port), strerror(errno)); 02214 if (rtp_debug_test_addr(&rtp->them)) 02215 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02216 ast_inet_ntoa(rtp->them.sin_addr), 02217 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02218 /* Increment sequence number */ 02219 rtp->seqno++; 02220 /* Increment duration */ 02221 rtp->send_duration += 160; 02222 /* Clear marker bit and set seqno */ 02223 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno)); 02224 } 02225 02226 /* Since we received a begin, we can safely store the digit and disable any compensation */ 02227 rtp->sending_digit = 1; 02228 rtp->send_digit = digit; 02229 rtp->send_payload = payload; 02230 02231 return 0; 02232 }
|
|
|
Send continuation frame for DTMF.
Definition at line 2235 of file rtp.c. References ast_inet_ntoa(), ast_log(), ast_verbose(), ast_rtp::lastdigitts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them. Referenced by ast_rtp_read(). 02236 { 02237 unsigned int *rtpheader; 02238 int hdrlen = 12, res = 0; 02239 char data[256]; 02240 02241 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02242 return 0; 02243 02244 /* Setup packet to send */ 02245 rtpheader = (unsigned int *)data; 02246 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02247 rtpheader[1] = htonl(rtp->lastdigitts); 02248 rtpheader[2] = htonl(rtp->ssrc); 02249 rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration)); 02250 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02251 02252 /* Transmit */ 02253 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02254 if (res < 0) 02255 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02256 ast_inet_ntoa(rtp->them.sin_addr), 02257 ntohs(rtp->them.sin_port), strerror(errno)); 02258 if (rtp_debug_test_addr(&rtp->them)) 02259 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02260 ast_inet_ntoa(rtp->them.sin_addr), 02261 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02262 02263 /* Increment sequence number */ 02264 rtp->seqno++; 02265 /* Increment duration */ 02266 rtp->send_duration += 160; 02267 02268 return 0; 02269 }
|
|
||||||||||||
|
Send end packets for DTMF.
Definition at line 2272 of file rtp.c. References ast_inet_ntoa(), ast_log(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them. Referenced by oh323_digit_end(), and sip_senddigit_end(). 02273 { 02274 unsigned int *rtpheader; 02275 int hdrlen = 12, res = 0, i = 0; 02276 char data[256]; 02277 02278 /* If no address, then bail out */ 02279 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 02280 return 0; 02281 02282 if ((digit <= '9') && (digit >= '0')) 02283 digit -= '0'; 02284 else if (digit == '*') 02285 digit = 10; 02286 else if (digit == '#') 02287 digit = 11; 02288 else if ((digit >= 'A') && (digit <= 'D')) 02289 digit = digit - 'A' + 12; 02290 else if ((digit >= 'a') && (digit <= 'd')) 02291 digit = digit - 'a' + 12; 02292 else { 02293 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 02294 return 0; 02295 } 02296 02297 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000)); 02298 02299 rtpheader = (unsigned int *)data; 02300 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno)); 02301 rtpheader[1] = htonl(rtp->lastdigitts); 02302 rtpheader[2] = htonl(rtp->ssrc); 02303 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration)); 02304 /* Set end bit */ 02305 rtpheader[3] |= htonl((1 << 23)); 02306 rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno)); 02307 /* Send 3 termination packets */ 02308 for (i = 0; i < 3; i++) { 02309 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them)); 02310 if (res < 0) 02311 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n", 02312 ast_inet_ntoa(rtp->them.sin_addr), 02313 ntohs(rtp->them.sin_port), strerror(errno)); 02314 if (rtp_debug_test_addr(&rtp->them)) 02315 ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n", 02316 ast_inet_ntoa(rtp->them.sin_addr), 02317 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen); 02318 } 02319 rtp->sending_digit = 0; 02320 rtp->send_digit = 0; 02321 /* Increment lastdigitts */ 02322 rtp->lastdigitts += 960; 02323 rtp->seqno++; 02324 02325 return res; 02326 }
|
|
||||||||||||
|
Definition at line 587 of file rtp.c. References ast_rtp::callback. Referenced by start_rtp(). 00588 { 00589 rtp->callback = callback; 00590 }
|
|
||||||||||||
|
Definition at line 582 of file rtp.c. References ast_rtp::data. Referenced by start_rtp(). 00583 { 00584 rtp->data = data; 00585 }
|
|
||||||||||||
|
Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
Definition at line 1668 of file rtp.c. References ast_rtp::current_RTP_PT, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT. Referenced by gtalk_newcall(), jingle_newcall(), and process_sdp(). 01669 { 01670 if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 01671 return; /* bogus payload type */ 01672 01673 rtp_bridge_lock(rtp); 01674 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 01675 rtp_bridge_unlock(rtp); 01676 }
|
|
||||||||||||
|
Definition at line 2016 of file rtp.c. References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtp::them, and ast_rtcp::them. Referenced by handle_open_receive_channel_ack_message(), process_sdp(), and setup_rtp_connection(). 02017 { 02018 rtp->them.sin_port = them->sin_port; 02019 rtp->them.sin_addr = them->sin_addr; 02020 if (rtp->rtcp) { 02021 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 02022 rtp->rtcp->them.sin_addr = them->sin_addr; 02023 } 02024 rtp->rxseqno = 0; 02025 }
|
|
||||||||||||
|
Set rtp hold timeout.
Definition at line 549 of file rtp.c. References ast_rtp::rtpholdtimeout. Referenced by check_rtp_timeout(), create_addr_from_peer(), dialog_activate_media(), and sip_alloc(). 00550 { 00551 rtp->rtpholdtimeout = timeout; 00552 }
|
|
||||||||||||
|
set RTP keepalive interval
Definition at line 555 of file rtp.c. References ast_rtp::rtpkeepalive. Referenced by create_addr_from_peer(), dialog_activate_media(), and sip_alloc(). 00556 { 00557 rtp->rtpkeepalive = period; 00558 }
|
|
||||||||||||||||||||||||
|
Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
Definition at line 1681 of file rtp.c. References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, rtp_bridge_lock(), subtype, and type. Referenced by __oh323_rtp_create(), gtalk_newcall(), jingle_newcall(), process_sdp(), set_dtmf_payload(), and setup_rtp_connection(). 01684 { 01685 unsigned int i; 01686 01687 if (pt < 0 || pt > MAX_RTP_PT) 01688 return; /* bogus payload type */ 01689 01690 rtp_bridge_lock(rtp); 01691 01692 for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) { 01693 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 01694 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 01695 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 01696 if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) && 01697 mimeTypes[i].payloadType.isAstFormat && 01698 (options & AST_RTP_OPT_G726_NONSTANDARD)) 01699 rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2; 01700 break; 01701 } 01702 } 01703 01704 rtp_bridge_unlock(rtp); 01705 01706 return; 01707 }
|
|
||||||||||||
|
Set rtp timeout.
Definition at line 543 of file rtp.c. References ast_rtp::rtptimeout. Referenced by check_rtp_timeout(), create_addr_from_peer(), dialog_activate_media(), and sip_alloc(). 00544 { 00545 rtp->rtptimeout = timeout; 00546 }
|
|
|
Definition at line 536 of file rtp.c. References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout. Referenced by handle_response_answer(), and handle_response_invite(). 00537 { 00538 rtp->rtptimeout = (-1) * rtp->rtptimeout; 00539 rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; 00540 }
|
|
||||||||||||
|
Indicate whether this RTP session is carrying DTMF or not.
Definition at line 602 of file rtp.c. References ast_set2_flag, and FLAG_HAS_DTMF. Referenced by create_addr_from_peer(), dialog_activate_media(), handle_request_invite(), and sip_alloc(). 00603 { 00604 ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF); 00605 }
|
|
||||||||||||
|
Compensate for devices that send RFC2833 packets all at once.
Definition at line 607 of file rtp.c. References ast_set2_flag, and FLAG_DTMF_COMPENSATE. Referenced by create_addr_from_peer(), dialog_activate_media(), handle_request_invite(), and sip_alloc(). 00608 { 00609 ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE); 00610 }
|
|
||||||||||||
|
Definition at line 592 of file rtp.c. References ast_rtp::nat. Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().
|
|
||||||||||||
|
Enable STUN capability.
Definition at line 612 of file rtp.c. References ast_set2_flag, and FLAG_HAS_STUN. Referenced by gtalk_new(). 00613 { 00614 ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN); 00615 }
|
|
||||||||||||
|
Definition at line 2007 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s. Referenced by __oh323_rtp_create(), dialog_activate_media(), and sip_alloc(). 02008 { 02009 int res; 02010 02011 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 02012 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 02013 return res; 02014 }
|
|
|
Stop RTP session, do not destroy structure Definition at line 2056 of file rtp.c. References ast_clear_flag, ast_sched_del(), FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::them, and ast_rtcp::them. Referenced by setup_rtp_connection(), and stop_media_flows(). 02057 { 02058 if (rtp->rtcp && rtp->rtcp->schedid > 0) { 02059 ast_sched_del(rtp->sched, rtp->rtcp->schedid); 02060 rtp->rtcp->schedid = -1; 02061 } 02062 02063 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 02064 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 02065 if (rtp->rtcp) { 02066 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr)); 02067 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port)); 02068 } 02069 02070 ast_clear_flag(rtp, FLAG_P2P_SENT_MARK); 02071 }
|
|
||||||||||||||||
|
Send STUN request (??).
Definition at line 404 of file rtp.c. References append_attr_string(), stun_attr::attr, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME. Referenced by gtalk_update_stun(), and jingle_update_stun(). 00405 { 00406 struct stun_header *req; 00407 unsigned char reqdata[1024]; 00408 int reqlen, reqleft; 00409 struct stun_attr *attr; 00410 00411 req = (struct stun_header *)reqdata; 00412 stun_req_id(req); 00413 reqlen = 0; 00414 reqleft = sizeof(reqdata) - sizeof(struct stun_header); 00415 req->msgtype = 0; 00416 req->msglen = 0; 00417 attr = (struct stun_attr *)req->ies; 00418 if (username) 00419 append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft); 00420 req->msglen = htons(reqlen); 00421 req->msgtype = htons(STUN_BINDREQ); 00422 stun_send(rtp->s, suggestion, req); 00423 }
|
|
||||||||||||
|
Definition at line 2722 of file rtp.c. References ast_codec_pref_getsize(), AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_getformatname(), |