#include <asterisk/frame.h>
#include <asterisk/io.h>
#include <asterisk/sched.h>
#include <asterisk/channel.h>
#include <netinet/in.h>
Go to the source code of this file.
Data Structures | |
struct | ast_rtp_protocol |
Defines | |
#define | AST_RTP_DTMF (1 << 0) |
#define | AST_RTP_CN (1 << 1) |
#define | AST_RTP_CISCO_DTMF (1 << 2) |
#define | AST_RTP_MAX AST_RTP_CISCO_DTMF |
Typedefs | |
typedef int(* | ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data) |
Functions | |
ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them) |
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us) |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f) |
ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
int | ast_rtp_fd (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
int | ast_rtp_senddigit (struct ast_rtp *rtp, char digit) |
int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
void | ast_rtp_pt_clear (struct ast_rtp *rtp) |
void | ast_rtp_pt_default (struct ast_rtp *rtp) |
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt) |
void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype) |
rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
int | ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code) |
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
char * | ast_rtp_lookup_mime_subtype (int isAstFormat, int code) |
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
int | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
void | ast_rtp_stop (struct ast_rtp *rtp) |
void | ast_rtp_init (void) |
void | ast_rtp_reload (void) |
|
DTMF (Cisco Proprietary) Definition at line 34 of file rtp.h. Referenced by ast_rtp_read(). |
|
'Comfort Noise' (RFC3389) Definition at line 32 of file rtp.h. Referenced by ast_rtp_read(). |
|
DTMF (RFC2833) Definition at line 30 of file rtp.h. Referenced by ast_rtp_read(). |
|
Maximum RTP-specific code |
|
Definition at line 49 of file rtp.h. Referenced by ast_rtp_set_callback(). |
|
Definition at line 107 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s.
|
|
Definition at line 321 of file rtp.c. References AST_FRAME_NULL, ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::them, and ast_rtcp::them.
00322 { 00323 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00324 int len; 00325 int hdrlen = 8; 00326 int res; 00327 struct sockaddr_in sin; 00328 unsigned int rtcpdata[1024]; 00329 00330 if (!rtp->rtcp) 00331 return &null_frame; 00332 00333 len = sizeof(sin); 00334 00335 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00336 0, (struct sockaddr *)&sin, &len); 00337 00338 if (res < 0) { 00339 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 00340 if (errno == EBADF) 00341 CRASH; 00342 return &null_frame; 00343 } 00344 00345 if (res < hdrlen) { 00346 ast_log(LOG_WARNING, "RTP Read too short\n"); 00347 return &null_frame; 00348 } 00349 00350 if (rtp->nat) { 00351 /* Send to whoever sent to us */ 00352 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00353 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00354 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00355 ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00356 } 00357 } 00358 if (option_debug) 00359 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00360 return &null_frame; 00361 } |
|
Definition at line 1157 of file rtp.c. References ast_autoservice_start(), ast_autoservice_stop(), AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, ast_check_hangup(), AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_read(), ast_rtp_get_peer(), ast_waitfor_n(), ast_write(), ast_frame::frametype, inaddrcmp(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel_pvt::pvt, and ast_channel::pvt.
01158 { 01159 struct ast_frame *f; 01160 struct ast_channel *who, *cs[3]; 01161 struct ast_rtp *p0, *p1; 01162 struct ast_rtp *vp0, *vp1; 01163 struct ast_rtp_protocol *pr0, *pr1; 01164 struct sockaddr_in ac0, ac1; 01165 struct sockaddr_in vac0, vac1; 01166 struct sockaddr_in t0, t1; 01167 struct sockaddr_in vt0, vt1; 01168 01169 void *pvt0, *pvt1; 01170 int to; 01171 memset(&vt0, 0, sizeof(vt0)); 01172 memset(&vt1, 0, sizeof(vt1)); 01173 memset(&vac0, 0, sizeof(vac0)); 01174 memset(&vac1, 0, sizeof(vac1)); 01175 01176 /* XXX Wait a half a second for things to settle up 01177 this really should be fixed XXX */ 01178 ast_autoservice_start(c0); 01179 ast_autoservice_start(c1); 01180 usleep(500000); 01181 ast_autoservice_stop(c0); 01182 ast_autoservice_stop(c1); 01183 01184 /* if need DTMF, cant native bridge */ 01185 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01186 return -2; 01187 ast_mutex_lock(&c0->lock); 01188 ast_mutex_lock(&c1->lock); 01189 pr0 = get_proto(c0); 01190 pr1 = get_proto(c1); 01191 if (!pr0) { 01192 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01193 ast_mutex_unlock(&c0->lock); 01194 ast_mutex_unlock(&c1->lock); 01195 return -1; 01196 } 01197 if (!pr1) { 01198 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01199 ast_mutex_unlock(&c0->lock); 01200 ast_mutex_unlock(&c1->lock); 01201 return -1; 01202 } 01203 pvt0 = c0->pvt->pvt; 01204 pvt1 = c1->pvt->pvt; 01205 p0 = pr0->get_rtp_info(c0); 01206 if (pr0->get_vrtp_info) 01207 vp0 = pr0->get_vrtp_info(c0); 01208 else 01209 vp0 = NULL; 01210 p1 = pr1->get_rtp_info(c1); 01211 if (pr1->get_vrtp_info) 01212 vp1 = pr1->get_vrtp_info(c1); 01213 else 01214 vp1 = NULL; 01215 if (!p0 || !p1) { 01216 /* Somebody doesn't want to play... */ 01217 ast_mutex_unlock(&c0->lock); 01218 ast_mutex_unlock(&c1->lock); 01219 return -2; 01220 } 01221 if (pr0->get_codec && pr1->get_codec) { 01222 int codec0,codec1; 01223 codec0 = pr0->get_codec(c0); 01224 codec1 = pr1->get_codec(c1); 01225 /* Hey, we can't do reinvite if both parties speak diffrent codecs */ 01226 if (!(codec0 & codec1)) { 01227 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1); 01228 ast_mutex_unlock(&c0->lock); 01229 ast_mutex_unlock(&c1->lock); 01230 return -2; 01231 } 01232 } 01233 if (pr0->set_rtp_peer(c0, p1, vp1)) 01234 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01235 else { 01236 /* Store RTP peer */ 01237 ast_rtp_get_peer(p1, &ac1); 01238 if (vp1) 01239 ast_rtp_get_peer(p1, &vac1); 01240 } 01241 if (pr1->set_rtp_peer(c1, p0, vp0)) 01242 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01243 else { 01244 /* Store RTP peer */ 01245 ast_rtp_get_peer(p0, &ac0); 01246 if (vp0) 01247 ast_rtp_get_peer(p0, &vac0); 01248 } 01249 ast_mutex_unlock(&c0->lock); 01250 ast_mutex_unlock(&c1->lock); 01251 cs[0] = c0; 01252 cs[1] = c1; 01253 cs[2] = NULL; 01254 for (;;) { 01255 if ((c0->pvt->pvt != pvt0) || 01256 (c1->pvt->pvt != pvt1) || 01257 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01258 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01259 if (c0->pvt->pvt == pvt0) { 01260 if (pr0->set_rtp_peer(c0, NULL, NULL)) 01261 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01262 } 01263 if (c1->pvt->pvt == pvt1) { 01264 if (pr1->set_rtp_peer(c1, NULL, NULL)) 01265 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01266 } 01267 /* Tell it to try again later */ 01268 return -3; 01269 } 01270 to = -1; 01271 ast_rtp_get_peer(p1, &t1); 01272 ast_rtp_get_peer(p0, &t0); 01273 if (vp1) 01274 ast_rtp_get_peer(vp1, &vt1); 01275 if (vp0) 01276 ast_rtp_get_peer(vp0, &vt0); 01277 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1))) { 01278 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address\n", c1->name); 01279 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL)) 01280 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01281 memcpy(&ac1, &t1, sizeof(ac1)); 01282 memcpy(&vac1, &vt1, sizeof(vac1)); 01283 } 01284 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01285 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address\n", c0->name); 01286 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL)) 01287 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01288 memcpy(&ac0, &t0, sizeof(ac0)); 01289 memcpy(&vac0, &vt0, sizeof(vac0)); 01290 } 01291 who = ast_waitfor_n(cs, 2, &to); 01292 if (!who) { 01293 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01294 /* check for hagnup / whentohangup */ 01295 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01296 break; 01297 continue; 01298 } 01299 f = ast_read(who); 01300 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01301 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01302 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01303 *fo = f; 01304 *rc = who; 01305 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01306 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) { 01307 if (pr0->set_rtp_peer(c0, NULL, NULL)) 01308 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01309 } 01310 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) { 01311 if (pr1->set_rtp_peer(c1, NULL, NULL)) 01312 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01313 } 01314 /* That's all we needed */ 01315 return 0; 01316 } else { 01317 if ((f->frametype == AST_FRAME_DTMF) || 01318 (f->frametype == AST_FRAME_VOICE) || 01319 (f->frametype == AST_FRAME_VIDEO)) { 01320 /* Forward voice or DTMF frames if they happen upon us */ 01321 if (who == c0) { 01322 ast_write(c1, f); 01323 } else if (who == c1) { 01324 ast_write(c0, f); 01325 } 01326 } 01327 ast_frfree(f); 01328 } 01329 /* Swap priority not that it's a big deal at this point */ 01330 cs[2] = cs[0]; 01331 cs[0] = cs[1]; 01332 cs[1] = cs[2]; 01333 01334 } 01335 return -1; 01336 } |
|
Definition at line 820 of file rtp.c. References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, and ast_rtp::smoother.
|
|
Definition at line 102 of file rtp.c. References ast_rtp::s.
00103 { 00104 return rtp->s; 00105 } |
|
Definition at line 629 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
00630 { 00631 int pt; 00632 00633 *astFormats = *nonAstFormats = 0; 00634 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00635 if (rtp->current_RTP_PT[pt].isAstFormat) { 00636 *astFormats |= rtp->current_RTP_PT[pt].code; 00637 } else { 00638 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00639 } 00640 } 00641 } |
|
Definition at line 798 of file rtp.c. References ast_rtp::them. Referenced by ast_rtp_bridge().
|
|
Definition at line 805 of file rtp.c. References ast_rtp::us.
|
|
Definition at line 1371 of file rtp.c. References ast_rtp_reload(). Referenced by main().
01372 { 01373 ast_rtp_reload(); 01374 } |
|
Definition at line 653 of file rtp.c. References rtpPayloadType::code, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result. Referenced by ast_rtp_write().
00653 { 00654 int pt; 00655 00656 /* Looks up an RTP code out of our *static* outbound list */ 00657 00658 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00659 code == rtp->rtp_lookup_code_cache_code) { 00660 // Use our cached mapping, to avoid the overhead of the loop below 00661 return rtp->rtp_lookup_code_cache_result; 00662 } 00663 00664 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00665 if (static_RTP_PT[pt].code == code && 00666 static_RTP_PT[pt].isAstFormat == isAstFormat) { 00667 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00668 rtp->rtp_lookup_code_cache_code = code; 00669 rtp->rtp_lookup_code_cache_result = pt; 00670 return pt; 00671 } 00672 } 00673 return -1; 00674 } |
|
Definition at line 676 of file rtp.c.
00676 { 00677 int i; 00678 00679 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00680 if (mimeTypes[i].payloadType.code == code && 00681 mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00682 return mimeTypes[i].subtype; 00683 } 00684 } 00685 return ""; 00686 } |
|
Definition at line 643 of file rtp.c. References ast_rtp_lookup_pt(), rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT. Referenced by ast_rtp_lookup_pt(), and ast_rtp_read().
00643 { 00644 if (pt < 0 || pt > MAX_RTP_PT) { 00645 struct rtpPayloadType result; 00646 result.isAstFormat = result.code = 0; 00647 return result; // bogus payload type 00648 } 00649 /* Gotta use our static one, since that's what we sent against */ 00650 return static_RTP_PT[pt]; 00651 } |
|
Definition at line 708 of file rtp.c. References ast_io_add(), AST_IO_IN, ast_log(), ast_rtp_pt_default(), free, LOG_WARNING, and malloc.
00709 { 00710 struct ast_rtp *rtp; 00711 int x; 00712 int flags; 00713 int startplace; 00714 rtp = malloc(sizeof(struct ast_rtp)); 00715 if (!rtp) 00716 return NULL; 00717 memset(rtp, 0, sizeof(struct ast_rtp)); 00718 rtp->them.sin_family = AF_INET; 00719 rtp->us.sin_family = AF_INET; 00720 rtp->s = socket(AF_INET, SOCK_DGRAM, 0); 00721 rtp->ssrc = rand(); 00722 rtp->seqno = rand() & 0xffff; 00723 if (rtp->s < 0) { 00724 free(rtp); 00725 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00726 return NULL; 00727 } 00728 if (sched && rtcpenable) { 00729 rtp->sched = sched; 00730 rtp->rtcp = ast_rtcp_new(); 00731 } 00732 flags = fcntl(rtp->s, F_GETFL); 00733 fcntl(rtp->s, F_SETFL, flags | O_NONBLOCK); 00734 /* Find us a place */ 00735 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00736 x = x & ~1; 00737 startplace = x; 00738 for (;;) { 00739 /* Must be an even port number by RTP spec */ 00740 rtp->us.sin_port = htons(x); 00741 if (rtp->rtcp) 00742 rtp->rtcp->us.sin_port = htons(x + 1); 00743 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us)) && 00744 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00745 break; 00746 if (errno != EADDRINUSE) { 00747 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00748 close(rtp->s); 00749 if (rtp->rtcp) { 00750 close(rtp->rtcp->s); 00751 free(rtp->rtcp); 00752 } 00753 free(rtp); 00754 return NULL; 00755 } 00756 x += 2; 00757 if (x > rtpend) 00758 x = (rtpstart + 1) & ~1; 00759 if (x == startplace) { 00760 ast_log(LOG_WARNING, "No RTP ports remaining\n"); 00761 close(rtp->s); 00762 if (rtp->rtcp) { 00763 close(rtp->rtcp->s); 00764 free(rtp->rtcp); 00765 } 00766 free(rtp); 00767 return NULL; 00768 } 00769 } 00770 if (io && sched && callbackmode) { 00771 /* Operate this one in a callback mode */ 00772 rtp->sched = sched; 00773 rtp->io = io; 00774 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 00775 } 00776 ast_rtp_pt_default(rtp); 00777 return rtp; 00778 } |
|
Definition at line 1128 of file rtp.c. References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.
01129 { 01130 struct ast_rtp_protocol *cur; 01131 cur = protos; 01132 while(cur) { 01133 if (cur->type == proto->type) { 01134 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01135 return -1; 01136 } 01137 cur = cur->next; 01138 } 01139 proto->next = protos; 01140 protos = proto; 01141 return 0; 01142 } |
|
Definition at line 1110 of file rtp.c. References ast_rtp_protocol::next.
01111 { 01112 struct ast_rtp_protocol *cur, *prev; 01113 cur = protos; 01114 prev = NULL; 01115 while(cur) { 01116 if (cur == proto) { 01117 if (prev) 01118 prev->next = proto->next; 01119 else 01120 protos = proto->next; 01121 return; 01122 } 01123 prev = cur; 01124 cur = cur->next; 01125 } 01126 } |
|
Definition at line 571 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.
00572 { 00573 int i; 00574 00575 for (i = 0; i < MAX_RTP_PT; ++i) { 00576 rtp->current_RTP_PT[i].isAstFormat = 0; 00577 rtp->current_RTP_PT[i].code = 0; 00578 } 00579 00580 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00581 rtp->rtp_lookup_code_cache_code = 0; 00582 rtp->rtp_lookup_code_cache_result = 0; 00583 } |
|
Definition at line 585 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result. Referenced by ast_rtp_new().
00586 { 00587 int i; 00588 /* Initialize to default payload types */ 00589 for (i = 0; i < MAX_RTP_PT; ++i) { 00590 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00591 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00592 } 00593 00594 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00595 rtp->rtp_lookup_code_cache_code = 0; 00596 rtp->rtp_lookup_code_cache_result = 0; 00597 } |
|
Definition at line 363 of file rtp.c. References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_rtp::dtmfcount, ast_rtp::f, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::s, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.
00364 { 00365 int res; 00366 struct sockaddr_in sin; 00367 int len; 00368 unsigned int seqno; 00369 int payloadtype; 00370 int hdrlen = 12; 00371 int mark; 00372 unsigned int timestamp; 00373 unsigned int *rtpheader; 00374 static struct ast_frame *f, null_frame = { AST_FRAME_NULL, }; 00375 struct rtpPayloadType rtpPT; 00376 00377 len = sizeof(sin); 00378 00379 /* Cache where the header will go */ 00380 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 00381 0, (struct sockaddr *)&sin, &len); 00382 00383 00384 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 00385 if (res < 0) { 00386 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 00387 if (errno == EBADF) 00388 CRASH; 00389 return &null_frame; 00390 } 00391 if (res < hdrlen) { 00392 ast_log(LOG_WARNING, "RTP Read too short\n"); 00393 return &null_frame; 00394 } 00395 if (rtp->nat) { 00396 /* Send to whoever sent to us */ 00397 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00398 (rtp->them.sin_port != sin.sin_port)) { 00399 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00400 ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00401 } 00402 } 00403 /* Ignore if the other side hasn't been given an address 00404 yet. */ 00405 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 00406 return &null_frame; 00407 00408 /* Get fields */ 00409 seqno = ntohl(rtpheader[0]); 00410 payloadtype = (seqno & 0x7f0000) >> 16; 00411 mark = seqno & (1 << 23); 00412 seqno &= 0xffff; 00413 timestamp = ntohl(rtpheader[1]); 00414 00415 #if 0 00416 printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); 00417 #endif 00418 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 00419 if (!rtpPT.isAstFormat) { 00420 // This is special in-band data that's not one of our codecs 00421 if (rtpPT.code == AST_RTP_DTMF) { 00422 /* It's special -- rfc2833 process it */ 00423 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00424 if (f) return f; else return &null_frame; 00425 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 00426 /* It's really special -- process it the Cisco way */ 00427 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00428 if (f) return f; else return &null_frame; 00429 } else if (rtpPT.code == AST_RTP_CN) { 00430 /* Comfort Noise */ 00431 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00432 if (f) return f; else return &null_frame; 00433 } else { 00434 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype); 00435 return &null_frame; 00436 } 00437 } 00438 rtp->f.subclass = rtpPT.code; 00439 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) 00440 rtp->f.frametype = AST_FRAME_VOICE; 00441 else 00442 rtp->f.frametype = AST_FRAME_VIDEO; 00443 rtp->lastrxformat = rtp->f.subclass; 00444 00445 if (!rtp->lastrxts) 00446 rtp->lastrxts = timestamp; 00447 00448 if (rtp->dtmfcount) { 00449 #if 0 00450 printf("dtmfcount was %d\n", rtp->dtmfcount); 00451 #endif 00452 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 00453 if (rtp->dtmfcount < 0) 00454 rtp->dtmfcount = 0; 00455 #if 0 00456 if (dtmftimeout != rtp->dtmfcount) 00457 printf("dtmfcount is %d\n", rtp->dtmfcount); 00458 #endif 00459 } 00460 rtp->lastrxts = timestamp; 00461 00462 /* Send any pending DTMF */ 00463 if (rtp->resp && !rtp->dtmfcount) { 00464 ast_log(LOG_DEBUG, "Sending pending DTMF\n"); 00465 return send_dtmf(rtp); 00466 } 00467 rtp->f.mallocd = 0; 00468 rtp->f.datalen = res - hdrlen; 00469 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 00470 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 00471 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 00472 switch(rtp->f.subclass) { 00473 case AST_FORMAT_ULAW: 00474 case AST_FORMAT_ALAW: 00475 rtp->f.samples = rtp->f.datalen; 00476 break; 00477 case AST_FORMAT_SLINEAR: 00478 rtp->f.samples = rtp->f.datalen / 2; 00479 break; 00480 case AST_FORMAT_GSM: 00481 rtp->f.samples = 160 * (rtp->f.datalen / 33); 00482 break; 00483 case AST_FORMAT_ILBC: 00484 rtp->f.samples = 240 * (rtp->f.datalen / 50); 00485 break; 00486 case AST_FORMAT_ADPCM: 00487 rtp->f.samples = rtp->f.datalen * 2; 00488 break; 00489 case AST_FORMAT_G729A: 00490 rtp->f.samples = rtp->f.datalen * 8; 00491 break; 00492 case AST_FORMAT_G723_1: 00493 rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen); 00494 break; 00495 case AST_FORMAT_SPEEX: 00496 rtp->f.samples = 160; 00497 // assumes that the RTP packet contained one Speex frame 00498 break; 00499 default: 00500 ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass)); 00501 break; 00502 } 00503 } else { 00504 /* Video -- samples is # of samples vs. 90000 */ 00505 if (!rtp->lastividtimestamp) 00506 rtp->lastividtimestamp = timestamp; 00507 rtp->f.samples = timestamp - rtp->lastividtimestamp; 00508 rtp->lastividtimestamp = timestamp; 00509 if (mark) 00510 rtp->f.subclass |= 0x1; 00511 00512 } 00513 rtp->f.src = "RTP"; 00514 return &rtp->f; 00515 } |
|
Definition at line 1338 of file rtp.c. References ast_destroy(), ast_load(), ast_log(), ast_variable_retrieve(), ast_verbose(), LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2. Referenced by ast_module_reload(), and ast_rtp_init().
01339 { 01340 struct ast_config *cfg; 01341 char *s; 01342 rtpstart = 5000; 01343 rtpend = 31000; 01344 cfg = ast_load("rtp.conf"); 01345 if (cfg) { 01346 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01347 rtpstart = atoi(s); 01348 if (rtpstart < 1024) 01349 rtpstart = 1024; 01350 if (rtpstart > 65535) 01351 rtpstart = 65535; 01352 } 01353 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01354 rtpend = atoi(s); 01355 if (rtpend < 1024) 01356 rtpend = 1024; 01357 if (rtpend > 65535) 01358 rtpend = 65535; 01359 } 01360 ast_destroy(cfg); 01361 } 01362 if (rtpstart >= rtpend) { 01363 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n"); 01364 rtpstart = 5000; 01365 rtpend = 31000; 01366 } 01367 if (option_verbose > 1) 01368 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01369 } |
|
Definition at line 851 of file rtp.c. References ast_log(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_NOTICE, LOG_WARNING, ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
00852 { 00853 unsigned int *rtpheader; 00854 int hdrlen = 12; 00855 int res; 00856 int ms; 00857 int pred; 00858 int x; 00859 char data[256]; 00860 00861 if ((digit <= '9') && (digit >= '0')) 00862 digit -= '0'; 00863 else if (digit == '*') 00864 digit = 10; 00865 else if (digit == '#') 00866 digit = 11; 00867 else if ((digit >= 'A') && (digit <= 'D')) 00868 digit = digit - 'A' + 12; 00869 else if ((digit >= 'a') && (digit <= 'd')) 00870 digit = digit - 'a' + 12; 00871 else { 00872 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00873 return -1; 00874 } 00875 00876 00877 /* If we have no peer, return immediately */ 00878 if (!rtp->them.sin_addr.s_addr) 00879 return 0; 00880 00881 gettimeofday(&rtp->dtmfmute, NULL); 00882 rtp->dtmfmute.tv_usec += (500 * 1000); 00883 if (rtp->dtmfmute.tv_usec > 1000000) { 00884 rtp->dtmfmute.tv_usec -= 1000000; 00885 rtp->dtmfmute.tv_sec += 1; 00886 } 00887 00888 ms = calc_txstamp(rtp); 00889 /* Default prediction */ 00890 pred = rtp->lastts + ms * 8; 00891 00892 /* Get a pointer to the header */ 00893 rtpheader = (unsigned int *)data; 00894 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (101 << 16) | (rtp->seqno++)); 00895 rtpheader[1] = htonl(rtp->lastts); 00896 rtpheader[2] = htonl(rtp->ssrc); 00897 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 00898 for (x=0;x<4;x++) { 00899 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 00900 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 00901 if (res <0) 00902 ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); 00903 #if 0 00904 printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00905 #endif 00906 } 00907 if (x ==0) { 00908 /* Clear marker bit and increment seqno */ 00909 rtpheader[0] = htonl((2 << 30) | (101 << 16) | (rtp->seqno++)); 00910 /* Make duration 800 (100ms) */ 00911 rtpheader[3] |= htonl((800)); 00912 /* Set the End bit for the last 3 */ 00913 rtpheader[3] |= htonl((1 << 23)); 00914 } 00915 } 00916 return 0; 00917 } |
|
Definition at line 155 of file rtp.c. References ast_rtp_callback, and ast_rtp::callback.
00156 { 00157 rtp->callback = callback; 00158 } |
|
Definition at line 150 of file rtp.c. References ast_rtp::data.
00151 { 00152 rtp->data = data; 00153 } |
|
Definition at line 602 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.
00602 { 00603 if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type 00604 00605 if (static_RTP_PT[pt].code != 0) { 00606 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00607 } 00608 } |
|
Definition at line 788 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.
|
|
Definition at line 612 of file rtp.c. References ast_rtp::current_RTP_PT, MAX_RTP_PT, and subtype.
00613 { 00614 int i; 00615 00616 if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type 00617 00618 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00619 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00620 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00621 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00622 return; 00623 } 00624 } 00625 } |
|
Definition at line 160 of file rtp.c. References ast_rtp::nat.
00161 { 00162 rtp->nat = nat; 00163 } |
|
Definition at line 780 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s.
|
|
Definition at line 810 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.
00811 { 00812 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00813 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00814 if (rtp->rtcp) { 00815 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00816 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00817 } 00818 } |
|
Definition at line 997 of file rtp.c. References AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_ILBC, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_smoother_feed(), ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_frame::datalen, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.
00998 { 00999 struct ast_frame *f; 01000 int codec; 01001 int hdrlen = 12; 01002 int subclass; 01003 01004 01005 /* If we have no peer, return immediately */ 01006 if (!rtp->them.sin_addr.s_addr) 01007 return 0; 01008 01009 /* If there is no data length, return immediately */ 01010 if (!_f->datalen) 01011 return 0; 01012 01013 /* Make sure we have enough space for RTP header */ 01014 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01015 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01016 return -1; 01017 } 01018 01019 subclass = _f->subclass; 01020 if (_f->frametype == AST_FRAME_VIDEO) 01021 subclass &= ~0x1; 01022 01023 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01024 if (codec < 0) { 01025 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01026 return -1; 01027 } 01028 01029 if (rtp->lasttxformat != subclass) { 01030 /* New format, reset the smoother */ 01031 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01032 rtp->lasttxformat = subclass; 01033 if (rtp->smoother) 01034 ast_smoother_free(rtp->smoother); 01035 rtp->smoother = NULL; 01036 } 01037 01038 01039 switch(subclass) { 01040 case AST_FORMAT_ULAW: 01041 case AST_FORMAT_ALAW: 01042 if (!rtp->smoother) { 01043 rtp->smoother = ast_smoother_new(160); 01044 } 01045 if (!rtp->smoother) { 01046 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01047 return -1; 01048 } 01049 ast_smoother_feed(rtp->smoother, _f); 01050 01051 while((f = ast_smoother_read(rtp->smoother))) 01052 ast_rtp_raw_write(rtp, f, codec); 01053 break; 01054 case AST_FORMAT_G729A: 01055 if (!rtp->smoother) { 01056 rtp->smoother = ast_smoother_new(20); 01057 } 01058 if (!rtp->smoother) { 01059 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01060 return -1; 01061 } 01062 ast_smoother_feed(rtp->smoother, _f); 01063 01064 while((f = ast_smoother_read(rtp->smoother))) 01065 ast_rtp_raw_write(rtp, f, codec); 01066 break; 01067 case AST_FORMAT_GSM: 01068 if (!rtp->smoother) { 01069 rtp->smoother = ast_smoother_new(33); 01070 } 01071 if (!rtp->smoother) { 01072 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01073 return -1; 01074 } 01075 ast_smoother_feed(rtp->smoother, _f); 01076 while((f = ast_smoother_read(rtp->smoother))) 01077 ast_rtp_raw_write(rtp, f, codec); 01078 break; 01079 case AST_FORMAT_ILBC: 01080 if (!rtp->smoother) { 01081 rtp->smoother = ast_smoother_new(50); 01082 } 01083 if (!rtp->smoother) { 01084 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01085 return -1; 01086 } 01087 ast_smoother_feed(rtp->smoother, _f); 01088 while((f = ast_smoother_read(rtp->smoother))) 01089 ast_rtp_raw_write(rtp, f, codec); 01090 break; 01091 default: 01092 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01093 // fall through to... 01094 case AST_FORMAT_H261: 01095 case AST_FORMAT_H263: 01096 case AST_FORMAT_G723_1: 01097 case AST_FORMAT_SPEEX: 01098 // Don't buffer outgoing frames; send them one-per-packet: 01099 if (_f->offset < hdrlen) { 01100 f = ast_frdup(_f); 01101 } else { 01102 f = _f; 01103 } 01104 ast_rtp_raw_write(rtp, f, codec); 01105 } 01106 01107 return 0; 01108 } |