#include <stdio.h>
#include <stdlib.h>
#include <pthread.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/channel_pvt.h>
#include <asterisk/config.h>
Go to the source code of this file.
Data Structures | |
struct | ast_rtcp |
struct | ast_rtp |
struct | rtpPayloadType |
Defines | |
#define | RTP_MTU 1200 |
#define | TYPE_HIGH 0x0 |
#define | TYPE_LOW 0x1 |
#define | TYPE_SILENCE 0x2 |
#define | TYPE_DONTSEND 0x3 |
#define | TYPE_MASK 0x3 |
#define | MAX_RTP_PT 256 |
Functions | |
int | ast_rtp_fd (struct ast_rtp *rtp) |
int | ast_rtcp_fd (struct ast_rtp *rtp) |
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data) |
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback) |
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat) |
ast_frame * | ast_rtcp_read (struct ast_rtp *rtp) |
ast_frame * | ast_rtp_read (struct ast_rtp *rtp) |
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) |
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats) |
rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt) |
int | ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code) |
char * | ast_rtp_lookup_mime_subtype (int isAstFormat, int code) |
ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode) |
int | ast_rtp_settos (struct ast_rtp *rtp, int tos) |
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_stop (struct ast_rtp *rtp) |
void | ast_rtp_destroy (struct ast_rtp *rtp) |
int | ast_rtp_senddigit (struct ast_rtp *rtp, char digit) |
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f) |
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto) |
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto) |
int | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) |
void | ast_rtp_reload (void) |
void | ast_rtp_init (void) |
|
Definition at line 57 of file rtp.c. Referenced by ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_default(), ast_rtp_set_m_type(), and ast_rtp_set_rtpmap_type(). |
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 106 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s.
|
|
Definition at line 310 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_rtcp::them, and ast_rtp::them.
00311 { 00312 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00313 int len; 00314 int hdrlen = 8; 00315 int res; 00316 struct sockaddr_in sin; 00317 unsigned int rtcpdata[1024]; 00318 00319 if (!rtp->rtcp) 00320 return &null_frame; 00321 00322 len = sizeof(sin); 00323 00324 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00325 0, (struct sockaddr *)&sin, &len); 00326 00327 if (res < 0) { 00328 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 00329 if (errno == EBADF) 00330 CRASH; 00331 return &null_frame; 00332 } 00333 00334 if (res < hdrlen) { 00335 ast_log(LOG_WARNING, "RTP Read too short\n"); 00336 return &null_frame; 00337 } 00338 00339 if (rtp->nat) { 00340 /* Send to whoever sent to us */ 00341 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00342 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00343 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00344 ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port)); 00345 } 00346 } 00347 if (option_debug) 00348 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00349 return &null_frame; 00350 } |
|
Definition at line 1134 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, and ast_channel_pvt::pvt.
01135 { 01136 struct ast_frame *f; 01137 struct ast_channel *who, *cs[3]; 01138 struct ast_rtp *p0, *p1; 01139 struct ast_rtp *vp0, *vp1; 01140 struct ast_rtp_protocol *pr0, *pr1; 01141 struct sockaddr_in ac0, ac1; 01142 struct sockaddr_in vac0, vac1; 01143 struct sockaddr_in t0, t1; 01144 struct sockaddr_in vt0, vt1; 01145 01146 void *pvt0, *pvt1; 01147 int to; 01148 memset(&vt0, 0, sizeof(vt0)); 01149 memset(&vt1, 0, sizeof(vt1)); 01150 memset(&vac0, 0, sizeof(vac0)); 01151 memset(&vac1, 0, sizeof(vac1)); 01152 01153 /* XXX Wait a half a second for things to settle up 01154 this really should be fixed XXX */ 01155 ast_autoservice_start(c0); 01156 ast_autoservice_start(c1); 01157 usleep(500000); 01158 ast_autoservice_stop(c0); 01159 ast_autoservice_stop(c1); 01160 01161 /* if need DTMF, cant native bridge */ 01162 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01163 return -2; 01164 ast_mutex_lock(&c0->lock); 01165 ast_mutex_lock(&c1->lock); 01166 pr0 = get_proto(c0); 01167 pr1 = get_proto(c1); 01168 if (!pr0) { 01169 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01170 ast_mutex_unlock(&c0->lock); 01171 ast_mutex_unlock(&c1->lock); 01172 return -1; 01173 } 01174 if (!pr1) { 01175 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01176 ast_mutex_unlock(&c0->lock); 01177 ast_mutex_unlock(&c1->lock); 01178 return -1; 01179 } 01180 pvt0 = c0->pvt->pvt; 01181 pvt1 = c1->pvt->pvt; 01182 p0 = pr0->get_rtp_info(c0); 01183 if (pr0->get_vrtp_info) 01184 vp0 = pr0->get_vrtp_info(c0); 01185 else 01186 vp0 = NULL; 01187 p1 = pr1->get_rtp_info(c1); 01188 if (pr1->get_vrtp_info) 01189 vp1 = pr1->get_vrtp_info(c1); 01190 else 01191 vp1 = NULL; 01192 if (!p0 || !p1) { 01193 /* Somebody doesn't want to play... */ 01194 ast_mutex_unlock(&c0->lock); 01195 ast_mutex_unlock(&c1->lock); 01196 return -2; 01197 } 01198 if (pr0->get_codec && pr1->get_codec) { 01199 int codec0,codec1; 01200 codec0 = pr0->get_codec(c0); 01201 codec1 = pr1->get_codec(c1); 01202 /* Hey, we can't do reinvite if both parties speak diffrent codecs */ 01203 if (codec0 != codec1) { 01204 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1); 01205 ast_mutex_unlock(&c0->lock); 01206 ast_mutex_unlock(&c1->lock); 01207 return -2; 01208 } 01209 } 01210 if (pr0->set_rtp_peer(c0, p1, vp1)) 01211 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01212 else { 01213 /* Store RTP peer */ 01214 ast_rtp_get_peer(p1, &ac1); 01215 if (vp1) 01216 ast_rtp_get_peer(p1, &vac1); 01217 } 01218 if (pr1->set_rtp_peer(c1, p0, vp0)) 01219 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01220 else { 01221 /* Store RTP peer */ 01222 ast_rtp_get_peer(p0, &ac0); 01223 if (vp0) 01224 ast_rtp_get_peer(p0, &vac0); 01225 } 01226 ast_mutex_unlock(&c0->lock); 01227 ast_mutex_unlock(&c1->lock); 01228 cs[0] = c0; 01229 cs[1] = c1; 01230 cs[2] = NULL; 01231 for (;;) { 01232 if ((c0->pvt->pvt != pvt0) || 01233 (c1->pvt->pvt != pvt1) || 01234 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01235 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01236 if (c0->pvt->pvt == pvt0) { 01237 if (pr0->set_rtp_peer(c0, NULL, NULL)) 01238 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01239 } 01240 if (c1->pvt->pvt == pvt1) { 01241 if (pr1->set_rtp_peer(c1, NULL, NULL)) 01242 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01243 } 01244 /* Tell it to try again later */ 01245 return -3; 01246 } 01247 to = -1; 01248 ast_rtp_get_peer(p1, &t1); 01249 ast_rtp_get_peer(p0, &t0); 01250 if (vp1) 01251 ast_rtp_get_peer(vp1, &vt1); 01252 if (vp0) 01253 ast_rtp_get_peer(vp0, &vt0); 01254 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1))) { 01255 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address\n", c1->name); 01256 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL)) 01257 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01258 memcpy(&ac1, &t1, sizeof(ac1)); 01259 memcpy(&vac1, &vt1, sizeof(vac1)); 01260 } 01261 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01262 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address\n", c0->name); 01263 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL)) 01264 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01265 memcpy(&ac0, &t0, sizeof(ac0)); 01266 memcpy(&vac0, &vt0, sizeof(vac0)); 01267 } 01268 who = ast_waitfor_n(cs, 2, &to); 01269 if (!who) { 01270 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01271 /* check for hagnup / whentohangup */ 01272 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01273 break; 01274 continue; 01275 } 01276 f = ast_read(who); 01277 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01278 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01279 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01280 *fo = f; 01281 *rc = who; 01282 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01283 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) { 01284 if (pr0->set_rtp_peer(c0, NULL, NULL)) 01285 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01286 } 01287 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) { 01288 if (pr1->set_rtp_peer(c1, NULL, NULL)) 01289 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01290 } 01291 /* That's all we needed */ 01292 return 0; 01293 } else { 01294 if ((f->frametype == AST_FRAME_DTMF) || 01295 (f->frametype == AST_FRAME_VOICE) || 01296 (f->frametype == AST_FRAME_VIDEO)) { 01297 /* Forward voice or DTMF frames if they happen upon us */ 01298 if (who == c0) { 01299 ast_write(c1, f); 01300 } else if (who == c1) { 01301 ast_write(c0, f); 01302 } 01303 } 01304 ast_frfree(f); 01305 } 01306 /* Swap priority not that it's a big deal at this point */ 01307 cs[2] = cs[0]; 01308 cs[0] = cs[1]; 01309 cs[1] = cs[2]; 01310 01311 } 01312 return -1; 01313 } |
|
Definition at line 804 of file rtp.c. References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, and ast_rtp::smoother.
|
|
Definition at line 101 of file rtp.c. References ast_rtp::s.
00102 { 00103 return rtp->s; 00104 } |
|
Definition at line 613 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.
00614 { 00615 int pt; 00616 00617 *astFormats = *nonAstFormats = 0; 00618 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00619 if (rtp->current_RTP_PT[pt].isAstFormat) { 00620 *astFormats |= rtp->current_RTP_PT[pt].code; 00621 } else { 00622 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00623 } 00624 } 00625 } |
|
Definition at line 782 of file rtp.c. References ast_rtp::them. Referenced by ast_rtp_bridge().
|
|
Definition at line 789 of file rtp.c. References ast_rtp::us.
|
|
Definition at line 1348 of file rtp.c. References ast_rtp_reload(). Referenced by main().
01349 { 01350 ast_rtp_reload(); 01351 } |
|
Definition at line 637 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().
00637 { 00638 int pt; 00639 00640 /* Looks up an RTP code out of our *static* outbound list */ 00641 00642 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00643 code == rtp->rtp_lookup_code_cache_code) { 00644 // Use our cached mapping, to avoid the overhead of the loop below 00645 return rtp->rtp_lookup_code_cache_result; 00646 } 00647 00648 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00649 if (static_RTP_PT[pt].code == code && 00650 static_RTP_PT[pt].isAstFormat == isAstFormat) { 00651 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00652 rtp->rtp_lookup_code_cache_code = code; 00653 rtp->rtp_lookup_code_cache_result = pt; 00654 return pt; 00655 } 00656 } 00657 return -1; 00658 } |
|
Definition at line 660 of file rtp.c.
00660 { 00661 int i; 00662 00663 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00664 if (mimeTypes[i].payloadType.code == code && 00665 mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00666 return mimeTypes[i].subtype; 00667 } 00668 } 00669 return ""; 00670 } |
|
Definition at line 627 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().
00627 { 00628 if (pt < 0 || pt > MAX_RTP_PT) { 00629 struct rtpPayloadType result; 00630 result.isAstFormat = result.code = 0; 00631 return result; // bogus payload type 00632 } 00633 /* Gotta use our static one, since that's what we sent against */ 00634 return static_RTP_PT[pt]; 00635 } |
|
Definition at line 692 of file rtp.c. References ast_io_add(), AST_IO_IN, ast_log(), ast_rtp_pt_default(), free, LOG_WARNING, and malloc.
00693 { 00694 struct ast_rtp *rtp; 00695 int x; 00696 int flags; 00697 int startplace; 00698 rtp = malloc(sizeof(struct ast_rtp)); 00699 if (!rtp) 00700 return NULL; 00701 memset(rtp, 0, sizeof(struct ast_rtp)); 00702 rtp->them.sin_family = AF_INET; 00703 rtp->us.sin_family = AF_INET; 00704 rtp->s = socket(AF_INET, SOCK_DGRAM, 0); 00705 rtp->ssrc = rand(); 00706 rtp->seqno = rand() & 0xffff; 00707 if (rtp->s < 0) { 00708 free(rtp); 00709 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00710 return NULL; 00711 } 00712 if (sched && rtcpenable) { 00713 rtp->sched = sched; 00714 rtp->rtcp = ast_rtcp_new(); 00715 } 00716 flags = fcntl(rtp->s, F_GETFL); 00717 fcntl(rtp->s, F_SETFL, flags | O_NONBLOCK); 00718 /* Find us a place */ 00719 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00720 x = x & ~1; 00721 startplace = x; 00722 for (;;) { 00723 /* Must be an even port number by RTP spec */ 00724 rtp->us.sin_port = htons(x); 00725 if (rtp->rtcp) 00726 rtp->rtcp->us.sin_port = htons(x + 1); 00727 if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us)) && 00728 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00729 break; 00730 if (errno != EADDRINUSE) { 00731 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00732 close(rtp->s); 00733 if (rtp->rtcp) { 00734 close(rtp->rtcp->s); 00735 free(rtp->rtcp); 00736 } 00737 free(rtp); 00738 return NULL; 00739 } 00740 x += 2; 00741 if (x > rtpend) 00742 x = (rtpstart + 1) & ~1; 00743 if (x == startplace) { 00744 ast_log(LOG_WARNING, "No RTP ports remaining\n"); 00745 close(rtp->s); 00746 if (rtp->rtcp) { 00747 close(rtp->rtcp->s); 00748 free(rtp->rtcp); 00749 } 00750 free(rtp); 00751 return NULL; 00752 } 00753 } 00754 if (io && sched && callbackmode) { 00755 /* Operate this one in a callback mode */ 00756 rtp->sched = sched; 00757 rtp->io = io; 00758 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 00759 } 00760 ast_rtp_pt_default(rtp); 00761 return rtp; 00762 } |
|
Definition at line 1105 of file rtp.c. References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.
01106 { 01107 struct ast_rtp_protocol *cur; 01108 cur = protos; 01109 while(cur) { 01110 if (cur->type == proto->type) { 01111 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01112 return -1; 01113 } 01114 cur = cur->next; 01115 } 01116 proto->next = protos; 01117 protos = proto; 01118 return 0; 01119 } |
|
Definition at line 1087 of file rtp.c. References ast_rtp_protocol::next.
01088 { 01089 struct ast_rtp_protocol *cur, *prev; 01090 cur = protos; 01091 prev = NULL; 01092 while(cur) { 01093 if (cur == proto) { 01094 if (prev) 01095 prev->next = proto->next; 01096 else 01097 protos = proto->next; 01098 return; 01099 } 01100 prev = cur; 01101 cur = cur->next; 01102 } 01103 } |
|
Definition at line 555 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.
00556 { 00557 int i; 00558 00559 for (i = 0; i < MAX_RTP_PT; ++i) { 00560 rtp->current_RTP_PT[i].isAstFormat = 0; 00561 rtp->current_RTP_PT[i].code = 0; 00562 } 00563 00564 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00565 rtp->rtp_lookup_code_cache_code = 0; 00566 rtp->rtp_lookup_code_cache_result = 0; 00567 } |
|
Definition at line 569 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().
00570 { 00571 int i; 00572 /* Initialize to default payload types */ 00573 for (i = 0; i < MAX_RTP_PT; ++i) { 00574 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00575 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00576 } 00577 00578 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00579 rtp->rtp_lookup_code_cache_code = 0; 00580 rtp->rtp_lookup_code_cache_result = 0; 00581 } |
|
Definition at line 352 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.
00353 { 00354 int res; 00355 struct sockaddr_in sin; 00356 int len; 00357 unsigned int seqno; 00358 int payloadtype; 00359 int hdrlen = 12; 00360 int mark; 00361 unsigned int timestamp; 00362 unsigned int *rtpheader; 00363 static struct ast_frame *f, null_frame = { AST_FRAME_NULL, }; 00364 struct rtpPayloadType rtpPT; 00365 00366 len = sizeof(sin); 00367 00368 /* Cache where the header will go */ 00369 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 00370 0, (struct sockaddr *)&sin, &len); 00371 00372 00373 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 00374 if (res < 0) { 00375 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 00376 if (errno == EBADF) 00377 CRASH; 00378 return &null_frame; 00379 } 00380 if (res < hdrlen) { 00381 ast_log(LOG_WARNING, "RTP Read too short\n"); 00382 return &null_frame; 00383 } 00384 if (rtp->nat) { 00385 /* Send to whoever sent to us */ 00386 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00387 (rtp->them.sin_port != sin.sin_port)) { 00388 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00389 ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00390 } 00391 } 00392 /* Get fields */ 00393 seqno = ntohl(rtpheader[0]); 00394 payloadtype = (seqno & 0x7f0000) >> 16; 00395 mark = seqno & (1 << 23); 00396 seqno &= 0xffff; 00397 timestamp = ntohl(rtpheader[1]); 00398 00399 #if 0 00400 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); 00401 #endif 00402 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 00403 if (!rtpPT.isAstFormat) { 00404 // This is special in-band data that's not one of our codecs 00405 if (rtpPT.code == AST_RTP_DTMF) { 00406 /* It's special -- rfc2833 process it */ 00407 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00408 if (f) return f; else return &null_frame; 00409 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 00410 /* It's really special -- process it the Cisco way */ 00411 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00412 if (f) return f; else return &null_frame; 00413 } else if (rtpPT.code == AST_RTP_CN) { 00414 /* Comfort Noise */ 00415 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00416 if (f) return f; else return &null_frame; 00417 } else { 00418 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype); 00419 return &null_frame; 00420 } 00421 } 00422 rtp->f.subclass = rtpPT.code; 00423 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) 00424 rtp->f.frametype = AST_FRAME_VOICE; 00425 else 00426 rtp->f.frametype = AST_FRAME_VIDEO; 00427 rtp->lastrxformat = rtp->f.subclass; 00428 00429 if (!rtp->lastrxts) 00430 rtp->lastrxts = timestamp; 00431 00432 if (rtp->dtmfcount) { 00433 #if 0 00434 printf("dtmfcount was %d\n", rtp->dtmfcount); 00435 #endif 00436 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 00437 if (rtp->dtmfcount < 0) 00438 rtp->dtmfcount = 0; 00439 #if 0 00440 if (dtmftimeout != rtp->dtmfcount) 00441 printf("dtmfcount is %d\n", rtp->dtmfcount); 00442 #endif 00443 } 00444 rtp->lastrxts = timestamp; 00445 00446 /* Send any pending DTMF */ 00447 if (rtp->resp && !rtp->dtmfcount) { 00448 ast_log(LOG_DEBUG, "Sending pending DTMF\n"); 00449 return send_dtmf(rtp); 00450 } 00451 rtp->f.mallocd = 0; 00452 rtp->f.datalen = res - hdrlen; 00453 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 00454 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 00455 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 00456 switch(rtp->f.subclass) { 00457 case AST_FORMAT_ULAW: 00458 case AST_FORMAT_ALAW: 00459 rtp->f.samples = rtp->f.datalen; 00460 break; 00461 case AST_FORMAT_SLINEAR: 00462 rtp->f.samples = rtp->f.datalen / 2; 00463 break; 00464 case AST_FORMAT_GSM: 00465 rtp->f.samples = 160 * (rtp->f.datalen / 33); 00466 break; 00467 case AST_FORMAT_ILBC: 00468 rtp->f.samples = 240 * (rtp->f.datalen / 50); 00469 break; 00470 case AST_FORMAT_ADPCM: 00471 rtp->f.samples = rtp->f.datalen * 2; 00472 break; 00473 case AST_FORMAT_G729A: 00474 rtp->f.samples = rtp->f.datalen * 8; 00475 break; 00476 case AST_FORMAT_G723_1: 00477 rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen); 00478 break; 00479 case AST_FORMAT_SPEEX: 00480 rtp->f.samples = 160; 00481 // assumes that the RTP packet contained one Speex frame 00482 break; 00483 default: 00484 ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass)); 00485 break; 00486 } 00487 } else { 00488 /* Video -- samples is # of samples vs. 90000 */ 00489 if (!rtp->lastividtimestamp) 00490 rtp->lastividtimestamp = timestamp; 00491 rtp->f.samples = timestamp - rtp->lastividtimestamp; 00492 rtp->lastividtimestamp = timestamp; 00493 if (mark) 00494 rtp->f.subclass |= 0x1; 00495 00496 } 00497 rtp->f.src = "RTP"; 00498 return &rtp->f; 00499 } |
|
Definition at line 1315 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().
01316 { 01317 struct ast_config *cfg; 01318 char *s; 01319 rtpstart = 5000; 01320 rtpend = 31000; 01321 cfg = ast_load("rtp.conf"); 01322 if (cfg) { 01323 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01324 rtpstart = atoi(s); 01325 if (rtpstart < 1024) 01326 rtpstart = 1024; 01327 if (rtpstart > 65535) 01328 rtpstart = 65535; 01329 } 01330 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01331 rtpend = atoi(s); 01332 if (rtpend < 1024) 01333 rtpend = 1024; 01334 if (rtpend > 65535) 01335 rtpend = 65535; 01336 } 01337 ast_destroy(cfg); 01338 } 01339 if (rtpstart >= rtpend) { 01340 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n"); 01341 rtpstart = 5000; 01342 rtpend = 31000; 01343 } 01344 if (option_verbose > 1) 01345 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01346 } |
|
Definition at line 835 of file rtp.c. References ast_log(), ast_rtp::lastts, LOG_NOTICE, LOG_WARNING, ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.
00836 { 00837 unsigned int *rtpheader; 00838 int hdrlen = 12; 00839 int res; 00840 int ms; 00841 int pred; 00842 int x; 00843 char data[256]; 00844 00845 if ((digit <= '9') && (digit >= '0')) 00846 digit -= '0'; 00847 else if (digit == '*') 00848 digit = 10; 00849 else if (digit == '#') 00850 digit = 11; 00851 else if ((digit >= 'A') && (digit <= 'D')) 00852 digit = digit - 'A' + 12; 00853 else if ((digit >= 'a') && (digit <= 'd')) 00854 digit = digit - 'a' + 12; 00855 else { 00856 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00857 return -1; 00858 } 00859 00860 00861 /* If we have no peer, return immediately */ 00862 if (!rtp->them.sin_addr.s_addr) 00863 return 0; 00864 00865 ms = calc_txstamp(rtp); 00866 /* Default prediction */ 00867 pred = rtp->lastts + ms * 8; 00868 00869 /* Get a pointer to the header */ 00870 rtpheader = (unsigned int *)data; 00871 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (101 << 16) | (rtp->seqno++)); 00872 rtpheader[1] = htonl(rtp->lastts); 00873 rtpheader[2] = htonl(rtp->ssrc); 00874 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 00875 for (x=0;x<4;x++) { 00876 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 00877 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 00878 if (res <0) 00879 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)); 00880 #if 0 00881 printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); 00882 #endif 00883 } 00884 if (x ==0) { 00885 /* Clear marker bit and increment seqno */ 00886 rtpheader[0] = htonl((2 << 30) | (101 << 16) | (rtp->seqno++)); 00887 /* Make duration 240 */ 00888 rtpheader[3] |= htonl((240)); 00889 /* Set the End bit for the last 3 */ 00890 rtpheader[3] |= htonl((1 << 23)); 00891 } 00892 } 00893 return 0; 00894 } |
|
Definition at line 154 of file rtp.c. References ast_rtp_callback, and ast_rtp::callback.
00155 { 00156 rtp->callback = callback; 00157 } |
|
Definition at line 149 of file rtp.c. References ast_rtp::data.
00150 { 00151 rtp->data = data; 00152 } |
|
Definition at line 586 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.
00586 { 00587 if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type 00588 00589 if (static_RTP_PT[pt].code != 0) { 00590 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00591 } 00592 } |
|
Definition at line 772 of file rtp.c. References ast_rtp::rtcp, ast_rtp::them, and ast_rtcp::them.
|
|
Definition at line 596 of file rtp.c. References ast_rtp::current_RTP_PT, MAX_RTP_PT, subtype, and type.
00597 { 00598 int i; 00599 00600 if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type 00601 00602 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00603 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00604 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00605 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00606 return; 00607 } 00608 } 00609 } |
|
Definition at line 159 of file rtp.c. References ast_rtp::nat.
00160 { 00161 rtp->nat = nat; 00162 } |
|
Definition at line 764 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s.
|
|
Definition at line 794 of file rtp.c. References ast_rtp::rtcp, ast_rtp::them, and ast_rtcp::them.
00795 { 00796 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00797 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00798 if (rtp->rtcp) { 00799 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00800 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00801 } 00802 } |
|
Definition at line 974 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.
00975 { 00976 struct ast_frame *f; 00977 int codec; 00978 int hdrlen = 12; 00979 int subclass; 00980 00981 00982 /* If we have no peer, return immediately */ 00983 if (!rtp->them.sin_addr.s_addr) 00984 return 0; 00985 00986 /* If there is no data length, return immediately */ 00987 if (!_f->datalen) 00988 return 0; 00989 00990 /* Make sure we have enough space for RTP header */ 00991 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 00992 ast_log(LOG_WARNING, "RTP can only send voice\n"); 00993 return -1; 00994 } 00995 00996 subclass = _f->subclass; 00997 if (_f->frametype == AST_FRAME_VIDEO) 00998 subclass &= ~0x1; 00999 01000 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01001 if (codec < 0) { 01002 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01003 return -1; 01004 } 01005 01006 if (rtp->lasttxformat != subclass) { 01007 /* New format, reset the smoother */ 01008 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01009 rtp->lasttxformat = subclass; 01010 if (rtp->smoother) 01011 ast_smoother_free(rtp->smoother); 01012 rtp->smoother = NULL; 01013 } 01014 01015 01016 switch(subclass) { 01017 case AST_FORMAT_ULAW: 01018 case AST_FORMAT_ALAW: 01019 if (!rtp->smoother) { 01020 rtp->smoother = ast_smoother_new(160); 01021 } 01022 if (!rtp->smoother) { 01023 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01024 return -1; 01025 } 01026 ast_smoother_feed(rtp->smoother, _f); 01027 01028 while((f = ast_smoother_read(rtp->smoother))) 01029 ast_rtp_raw_write(rtp, f, codec); 01030 break; 01031 case AST_FORMAT_G729A: 01032 if (!rtp->smoother) { 01033 rtp->smoother = ast_smoother_new(20); 01034 } 01035 if (!rtp->smoother) { 01036 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01037 return -1; 01038 } 01039 ast_smoother_feed(rtp->smoother, _f); 01040 01041 while((f = ast_smoother_read(rtp->smoother))) 01042 ast_rtp_raw_write(rtp, f, codec); 01043 break; 01044 case AST_FORMAT_GSM: 01045 if (!rtp->smoother) { 01046 rtp->smoother = ast_smoother_new(33); 01047 } 01048 if (!rtp->smoother) { 01049 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01050 return -1; 01051 } 01052 ast_smoother_feed(rtp->smoother, _f); 01053 while((f = ast_smoother_read(rtp->smoother))) 01054 ast_rtp_raw_write(rtp, f, codec); 01055 break; 01056 case AST_FORMAT_ILBC: 01057 if (!rtp->smoother) { 01058 rtp->smoother = ast_smoother_new(50); 01059 } 01060 if (!rtp->smoother) { 01061 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01062 return -1; 01063 } 01064 ast_smoother_feed(rtp->smoother, _f); 01065 while((f = ast_smoother_read(rtp->smoother))) 01066 ast_rtp_raw_write(rtp, f, codec); 01067 break; 01068 default: 01069 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01070 // fall through to... 01071 case AST_FORMAT_H261: 01072 case AST_FORMAT_H263: 01073 case AST_FORMAT_G723_1: 01074 case AST_FORMAT_SPEEX: 01075 // Don't buffer outgoing frames; send them one-per-packet: 01076 if (_f->offset < hdrlen) { 01077 f = ast_frdup(_f); 01078 } else { 01079 f = _f; 01080 } 01081 ast_rtp_raw_write(rtp, f, codec); 01082 } 01083 01084 return 0; 01085 } |
|
|
|
Definition at line 506 of file rtp.c. Referenced by ast_rtp_set_rtpmap_type(). |
|
Definition at line 505 of file rtp.c. Referenced by __ast_request_and_dial(), ast_channel_register(), ast_channel_register_ex(), ast_channel_unregister(), ast_readfile(), ast_request(), ast_request_and_dial(), ast_rtp_set_rtpmap_type(), ast_search_dns(), ast_writefile(), and ast_writestream(). |