#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.
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) |
| ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in) |
| 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_offered_from_local (struct ast_rtp *rtp, int local) |
| 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(), and ast_rtp_senddigit(). |
|
|
Maximum RTP-specific code |
|
|
|
|
|
Definition at line 119 of file rtp.c. References ast_rtp::rtcp, and ast_rtcp::s.
|
|
|
Definition at line 335 of file rtp.c. References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::them, and ast_rtcp::them. 00336 {
00337 static struct ast_frame null_frame = { AST_FRAME_NULL, };
00338 int len;
00339 int hdrlen = 8;
00340 int res;
00341 struct sockaddr_in sin;
00342 unsigned int rtcpdata[1024];
00343 char iabuf[INET_ADDRSTRLEN];
00344
00345 if (!rtp->rtcp)
00346 return &null_frame;
00347
00348 len = sizeof(sin);
00349
00350 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
00351 0, (struct sockaddr *)&sin, &len);
00352
00353 if (res < 0) {
00354 if (errno == EAGAIN)
00355 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n");
00356 else
00357 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00358 if (errno == EBADF)
00359 CRASH;
00360 return &null_frame;
00361 }
00362
00363 if (res < hdrlen) {
00364 ast_log(LOG_WARNING, "RTP Read too short\n");
00365 return &null_frame;
00366 }
00367
00368 if (rtp->nat) {
00369 /* Send to whoever sent to us */
00370 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00371 (rtp->rtcp->them.sin_port != sin.sin_port)) {
00372 memcpy(&rtp->them, &sin, sizeof(rtp->them));
00373 ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00374 }
00375 }
00376 if (option_debug)
00377 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00378 return &null_frame;
00379 }
|
|
||||||||||||||||||||||||
|
Definition at line 1336 of file rtp.c. References 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_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_read(), ast_rtp_get_peer(), ast_waitfor_n(), ast_write(), ast_frame::frametype, ast_rtp_protocol::get_codec, ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel_pvt::pvt, ast_channel::pvt, and ast_rtp_protocol::set_rtp_peer. 01337 {
01338 struct ast_frame *f;
01339 struct ast_channel *who, *cs[3];
01340 struct ast_rtp *p0, *p1;
01341 struct ast_rtp *vp0, *vp1;
01342 struct ast_rtp_protocol *pr0, *pr1;
01343 struct sockaddr_in ac0, ac1;
01344 struct sockaddr_in vac0, vac1;
01345 struct sockaddr_in t0, t1;
01346 struct sockaddr_in vt0, vt1;
01347 char iabuf[INET_ADDRSTRLEN];
01348
01349 void *pvt0, *pvt1;
01350 int to;
01351 int codec0,codec1, oldcodec0, oldcodec1;
01352
01353 memset(&vt0, 0, sizeof(vt0));
01354 memset(&vt1, 0, sizeof(vt1));
01355 memset(&vac0, 0, sizeof(vac0));
01356 memset(&vac1, 0, sizeof(vac1));
01357
01358 /* if need DTMF, cant native bridge */
01359 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
01360 return -2;
01361 ast_mutex_lock(&c0->lock);
01362 while(ast_mutex_trylock(&c1->lock)) {
01363 ast_mutex_unlock(&c0->lock);
01364 usleep(1);
01365 ast_mutex_lock(&c0->lock);
01366 }
01367 pr0 = get_proto(c0);
01368 pr1 = get_proto(c1);
01369 if (!pr0) {
01370 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01371 ast_mutex_unlock(&c0->lock);
01372 ast_mutex_unlock(&c1->lock);
01373 return -1;
01374 }
01375 if (!pr1) {
01376 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01377 ast_mutex_unlock(&c0->lock);
01378 ast_mutex_unlock(&c1->lock);
01379 return -1;
01380 }
01381 pvt0 = c0->pvt->pvt;
01382 pvt1 = c1->pvt->pvt;
01383 p0 = pr0->get_rtp_info(c0);
01384 if (pr0->get_vrtp_info)
01385 vp0 = pr0->get_vrtp_info(c0);
01386 else
01387 vp0 = NULL;
01388 p1 = pr1->get_rtp_info(c1);
01389 if (pr1->get_vrtp_info)
01390 vp1 = pr1->get_vrtp_info(c1);
01391 else
01392 vp1 = NULL;
01393 if (!p0 || !p1) {
01394 /* Somebody doesn't want to play... */
01395 ast_mutex_unlock(&c0->lock);
01396 ast_mutex_unlock(&c1->lock);
01397 return -2;
01398 }
01399 if (pr0->get_codec)
01400 codec0 = pr0->get_codec(c0);
01401 else
01402 codec0 = 0;
01403 if (pr1->get_codec)
01404 codec1 = pr1->get_codec(c1);
01405 else
01406 codec1 = 0;
01407 if (pr0->get_codec && pr1->get_codec) {
01408 /* Hey, we can't do reinvite if both parties speak diffrent codecs */
01409 if (!(codec0 & codec1)) {
01410 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1);
01411 ast_mutex_unlock(&c0->lock);
01412 ast_mutex_unlock(&c1->lock);
01413 return -2;
01414 }
01415 }
01416 if (pr0->set_rtp_peer(c0, p1, vp1, codec1))
01417 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01418 else {
01419 /* Store RTP peer */
01420 ast_rtp_get_peer(p1, &ac1);
01421 if (vp1)
01422 ast_rtp_get_peer(vp1, &vac1);
01423 }
01424 if (pr1->set_rtp_peer(c1, p0, vp0, codec0))
01425 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01426 else {
01427 /* Store RTP peer */
01428 ast_rtp_get_peer(p0, &ac0);
01429 if (vp0)
01430 ast_rtp_get_peer(vp0, &vac0);
01431 }
01432 ast_mutex_unlock(&c0->lock);
01433 ast_mutex_unlock(&c1->lock);
01434 cs[0] = c0;
01435 cs[1] = c1;
01436 cs[2] = NULL;
01437 oldcodec0 = codec0;
01438 oldcodec1 = codec1;
01439 for (;;) {
01440 if ((c0->pvt->pvt != pvt0) ||
01441 (c1->pvt->pvt != pvt1) ||
01442 (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01443 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
01444 if (c0->pvt->pvt == pvt0) {
01445 if (pr0->set_rtp_peer(c0, NULL, NULL, 0))
01446 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01447 }
01448 if (c1->pvt->pvt == pvt1) {
01449 if (pr1->set_rtp_peer(c1, NULL, NULL, 0))
01450 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01451 }
01452 /* Tell it to try again later */
01453 return -3;
01454 }
01455 to = -1;
01456 ast_rtp_get_peer(p1, &t1);
01457 ast_rtp_get_peer(p0, &t0);
01458 if (pr0->get_codec)
01459 codec0 = pr0->get_codec(c0);
01460 if (pr1->get_codec)
01461 codec1 = pr1->get_codec(c1);
01462 if (vp1)
01463 ast_rtp_get_peer(vp1, &vt1);
01464 if (vp0)
01465 ast_rtp_get_peer(vp0, &vt0);
01466 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
01467 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01468 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
01469 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
01470 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
01471 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01472 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
01473 ast_log(LOG_DEBUG, "Oooh, '%s' wasv %s:%d/(format %d)\n",
01474 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
01475 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1))
01476 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
01477 memcpy(&ac1, &t1, sizeof(ac1));
01478 memcpy(&vac1, &vt1, sizeof(vac1));
01479 oldcodec1 = codec1;
01480 }
01481 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
01482 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01483 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
01484 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01485 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
01486 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0))
01487 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
01488 memcpy(&ac0, &t0, sizeof(ac0));
01489 memcpy(&vac0, &vt0, sizeof(vac0));
01490 oldcodec0 = codec0;
01491 }
01492 who = ast_waitfor_n(cs, 2, &to);
01493 if (!who) {
01494 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
01495 /* check for hagnup / whentohangup */
01496 if (ast_check_hangup(c0) || ast_check_hangup(c1))
01497 break;
01498 continue;
01499 }
01500 f = ast_read(who);
01501 if (!f || ((f->frametype == AST_FRAME_DTMF) &&
01502 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
01503 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
01504 *fo = f;
01505 *rc = who;
01506 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
01507 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) {
01508 if (pr0->set_rtp_peer(c0, NULL, NULL, 0))
01509 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01510 }
01511 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) {
01512 if (pr1->set_rtp_peer(c1, NULL, NULL, 0))
01513 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01514 }
01515 /* That's all we needed */
01516 return 0;
01517 } else {
01518 if ((f->frametype == AST_FRAME_DTMF) ||
01519 (f->frametype == AST_FRAME_VOICE) ||
01520 (f->frametype == AST_FRAME_VIDEO)) {
01521 /* Forward voice or DTMF frames if they happen upon us */
01522 if (who == c0) {
01523 ast_write(c1, f);
01524 } else if (who == c1) {
01525 ast_write(c0, f);
01526 }
01527 }
01528 ast_frfree(f);
01529 }
01530 /* Swap priority not that it's a big deal at this point */
01531 cs[2] = cs[0];
01532 cs[0] = cs[1];
01533 cs[1] = cs[2];
01534
01535 }
01536 return -1;
01537 }
|
|
|
Definition at line 956 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. 00957 {
00958 if (rtp->smoother)
00959 ast_smoother_free(rtp->smoother);
00960 if (rtp->ioid)
00961 ast_io_remove(rtp->io, rtp->ioid);
00962 if (rtp->s > -1)
00963 close(rtp->s);
00964 if (rtp->rtcp) {
00965 close(rtp->rtcp->s);
00966 free(rtp->rtcp);
00967 }
00968 free(rtp);
00969 }
|
|
|
Definition at line 114 of file rtp.c. References ast_rtp::s. 00115 {
00116 return rtp->s;
00117 }
|
|
||||||||||||||||
|
Definition at line 714 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, and rtpPayloadType::isAstFormat. 00715 {
00716 int pt;
00717
00718 *astFormats = *nonAstFormats = 0;
00719 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00720 if (rtp->current_RTP_PT[pt].isAstFormat) {
00721 *astFormats |= rtp->current_RTP_PT[pt].code;
00722 } else {
00723 *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00724 }
00725 }
00726 }
|
|
||||||||||||
|
Definition at line 934 of file rtp.c. References ast_rtp::them. Referenced by ast_rtp_bridge(). 00935 {
00936 them->sin_family = AF_INET;
00937 them->sin_port = rtp->them.sin_port;
00938 them->sin_addr = rtp->them.sin_addr;
00939 }
|
|
||||||||||||
|
Definition at line 941 of file rtp.c. References ast_rtp::us.
|
|
|
Definition at line 1586 of file rtp.c. References ast_rtp_reload(). Referenced by main(). 01587 {
01588 ast_rtp_reload();
01589 }
|
|
||||||||||||||||
|
Definition at line 753 of file rtp.c. References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, 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_senddigit(), and ast_rtp_write(). 00753 {
00754 int pt;
00755
00756
00757 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00758 code == rtp->rtp_lookup_code_cache_code) {
00759 /* Use our cached mapping, to avoid the overhead of the loop below */
00760 return rtp->rtp_lookup_code_cache_result;
00761 }
00762
00763 /* Check the dynamic list first */
00764 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00765 if (rtp->current_RTP_PT[pt].code == code &&
00766 rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00767 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00768 rtp->rtp_lookup_code_cache_code = code;
00769 rtp->rtp_lookup_code_cache_result = pt;
00770 return pt;
00771 }
00772 }
00773
00774 /* Then the static list */
00775 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00776 if (static_RTP_PT[pt].code == code &&
00777 static_RTP_PT[pt].isAstFormat == isAstFormat) {
00778 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00779 rtp->rtp_lookup_code_cache_code = code;
00780 rtp->rtp_lookup_code_cache_result = pt;
00781 return pt;
00782 }
00783 }
00784 return -1;
00785 }
|
|
||||||||||||
|
Definition at line 787 of file rtp.c. References rtpPayloadType::code, and payloadType. 00787 {
00788 int i;
00789
00790 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00791 if (mimeTypes[i].payloadType.code == code &&
00792 mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00793 return mimeTypes[i].subtype;
00794 }
00795 }
00796 return "";
00797 }
|
|
||||||||||||
|
Definition at line 735 of file rtp.c. References rtpPayloadType::code, and rtpPayloadType::isAstFormat. Referenced by ast_rtp_read(). 00736 {
00737 struct rtpPayloadType result;
00738
00739 result.isAstFormat = result.code = 0;
00740 if (pt < 0 || pt > MAX_RTP_PT) {
00741 return result; /* bogus payload type */
00742 }
00743 /* Start with the negotiated codecs */
00744 if (!rtp->rtp_offered_from_local)
00745 result = rtp->current_RTP_PT[pt];
00746 /* If it doesn't exist, check our static RTP type list, just in case */
00747 if (!result.code)
00748 result = static_RTP_PT[pt];
00749 return result;
00750 }
|
|
||||||||||||||||||||
|
Definition at line 909 of file rtp.c. References ast_rtp_new_with_bindaddr(). 00910 {
00911 struct in_addr ia;
00912 memset(&ia, 0, sizeof(ia));
00913 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
00914 }
|
|
||||||||||||||||||||||||
|
Definition at line 833 of file rtp.c. References ast_io_add(), AST_IO_IN, ast_log(), ast_rtp_pt_default(), free, LOG_WARNING, and malloc. Referenced by ast_rtp_new(). 00834 {
00835 struct ast_rtp *rtp;
00836 int x;
00837 int first;
00838 int startplace;
00839 rtp = malloc(sizeof(struct ast_rtp));
00840 if (!rtp)
00841 return NULL;
00842 memset(rtp, 0, sizeof(struct ast_rtp));
00843 rtp->them.sin_family = AF_INET;
00844 rtp->us.sin_family = AF_INET;
00845 rtp->s = rtp_socket();
00846 rtp->ssrc = rand();
00847 rtp->seqno = rand() & 0xffff;
00848 if (rtp->s < 0) {
00849 free(rtp);
00850 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00851 return NULL;
00852 }
00853 if (sched && rtcpenable) {
00854 rtp->sched = sched;
00855 rtp->rtcp = ast_rtcp_new();
00856 }
00857 /* Find us a place */
00858 x = (rand() % (rtpend-rtpstart)) + rtpstart;
00859 x = x & ~1;
00860 startplace = x;
00861 for (;;) {
00862 /* Must be an even port number by RTP spec */
00863 rtp->us.sin_port = htons(x);
00864 rtp->us.sin_addr = addr;
00865 if (rtp->rtcp)
00866 rtp->rtcp->us.sin_port = htons(x + 1);
00867 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
00868 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
00869 break;
00870 if (!first) {
00871 /* Primary bind succeeded! Gotta recreate it */
00872 close(rtp->s);
00873 rtp->s = rtp_socket();
00874 }
00875 if (errno != EADDRINUSE) {
00876 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
00877 close(rtp->s);
00878 if (rtp->rtcp) {
00879 close(rtp->rtcp->s);
00880 free(rtp->rtcp);
00881 }
00882 free(rtp);
00883 return NULL;
00884 }
00885 x += 2;
00886 if (x > rtpend)
00887 x = (rtpstart + 1) & ~1;
00888 if (x == startplace) {
00889 ast_log(LOG_WARNING, "No RTP ports remaining\n");
00890 close(rtp->s);
00891 if (rtp->rtcp) {
00892 close(rtp->rtcp->s);
00893 free(rtp->rtcp);
00894 }
00895 free(rtp);
00896 return NULL;
00897 }
00898 }
00899 if (io && sched && callbackmode) {
00900 /* Operate this one in a callback mode */
00901 rtp->sched = sched;
00902 rtp->io = io;
00903 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
00904 }
00905 ast_rtp_pt_default(rtp);
00906 return rtp;
00907 }
|
|
||||||||||||
|
Definition at line 728 of file rtp.c. References ast_log(), and LOG_WARNING. 00728 {
00729 if (rtp)
00730 rtp->rtp_offered_from_local = local;
00731 else
00732 ast_log(LOG_WARNING, "rtp structure is null\n");
00733 }
|
|
|
Definition at line 1307 of file rtp.c. References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type. 01308 {
01309 struct ast_rtp_protocol *cur;
01310 cur = protos;
01311 while(cur) {
01312 if (cur->type == proto->type) {
01313 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01314 return -1;
01315 }
01316 cur = cur->next;
01317 }
01318 proto->next = protos;
01319 protos = proto;
01320 return 0;
01321 }
|
|
|
Definition at line 1289 of file rtp.c. References ast_rtp_protocol::next. 01290 {
01291 struct ast_rtp_protocol *cur, *prev;
01292 cur = protos;
01293 prev = NULL;
01294 while(cur) {
01295 if (cur == proto) {
01296 if (prev)
01297 prev->next = proto->next;
01298 else
01299 protos = proto->next;
01300 return;
01301 }
01302 prev = cur;
01303 cur = cur->next;
01304 }
01305 }
|
|
|
Definition at line 656 of file rtp.c. 00657 {
00658 int i;
00659
00660 for (i = 0; i < MAX_RTP_PT; ++i) {
00661 rtp->current_RTP_PT[i].isAstFormat = 0;
00662 rtp->current_RTP_PT[i].code = 0;
00663 }
00664
00665 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00666 rtp->rtp_lookup_code_cache_code = 0;
00667 rtp->rtp_lookup_code_cache_result = 0;
00668 }
|
|
|
Definition at line 670 of file rtp.c. References rtpPayloadType::code, and rtpPayloadType::isAstFormat. Referenced by ast_rtp_new_with_bindaddr(). 00671 {
00672 int i;
00673 /* Initialize to default payload types */
00674 for (i = 0; i < MAX_RTP_PT; ++i) {
00675 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00676 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00677 }
00678
00679 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00680 rtp->rtp_lookup_code_cache_code = 0;
00681 rtp->rtp_lookup_code_cache_result = 0;
00682 }
|
|
|
Definition at line 403 of file rtp.c. References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_LPC10, 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_inet_ntoa(), 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_frame::delivery, ast_rtp::dtmfcount, ast_rtp::f, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, 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. 00404 {
00405 int res;
00406 struct sockaddr_in sin;
00407 int len;
00408 unsigned int seqno;
00409 int version;
00410 int payloadtype;
00411 int hdrlen = 12;
00412 int mark;
00413 int ext;
00414 char iabuf[INET_ADDRSTRLEN];
00415 unsigned int timestamp;
00416 unsigned int *rtpheader;
00417 static struct ast_frame *f, null_frame = { AST_FRAME_NULL, };
00418 struct rtpPayloadType rtpPT;
00419
00420 len = sizeof(sin);
00421
00422 /* XXX SYMPTON CURE, DIRTY FIX, CHECK, BEGIN */
00423 if (!rtp)
00424 return &null_frame;
00425 /* XXX SYMPTON CURE, DIRTY FIX, CHECK, END */
00426
00427 /* Cache where the header will go */
00428 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
00429 0, (struct sockaddr *)&sin, &len);
00430
00431
00432 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
00433 if (res < 0) {
00434 if (errno == EAGAIN)
00435 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n");
00436 else
00437 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00438 if (errno == EBADF)
00439 CRASH;
00440 return &null_frame;
00441 }
00442 if (res < hdrlen) {
00443 ast_log(LOG_WARNING, "RTP Read too short\n");
00444 return &null_frame;
00445 }
00446
00447 /* Ignore if the other side hasn't been given an address
00448 yet. */
00449 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
00450 return &null_frame;
00451
00452 if (rtp->nat) {
00453 /* Send to whoever sent to us */
00454 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00455 (rtp->them.sin_port != sin.sin_port)) {
00456 memcpy(&rtp->them, &sin, sizeof(rtp->them));
00457 ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
00458 }
00459 }
00460
00461 /* Get fields */
00462 seqno = ntohl(rtpheader[0]);
00463
00464 /* Check RTP version */
00465 version = (seqno & 0xC0000000) >> 30;
00466 if (version != 2)
00467 return &null_frame;
00468
00469 payloadtype = (seqno & 0x7f0000) >> 16;
00470 mark = seqno & (1 << 23);
00471 ext = seqno & (1 << 28);
00472 seqno &= 0xffff;
00473 timestamp = ntohl(rtpheader[1]);
00474 if (ext) {
00475 /* RTP Extension present */
00476 hdrlen += 4;
00477 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2;
00478 }
00479
00480 if (res < hdrlen) {
00481 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
00482 return &null_frame;
00483 }
00484
00485 #if 0
00486 printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
00487 #endif
00488 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
00489 if (!rtpPT.isAstFormat) {
00490 /* This is special in-band data that's not one of our codecs */
00491 if (rtpPT.code == AST_RTP_DTMF) {
00492 /* It's special -- rfc2833 process it */
00493 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00494 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00495 rtp->lasteventseqn = seqno;
00496 } else f = NULL;
00497 if (f) return f; else return &null_frame;
00498 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
00499 /* It's really special -- process it the Cisco way */
00500 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00501 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00502 rtp->lasteventseqn = seqno;
00503 } else f = NULL;
00504 if (f) return f; else return &null_frame;
00505 } else if (rtpPT.code == AST_RTP_CN) {
00506 /* Comfort Noise */
00507 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00508 if (f) return f; else return &null_frame;
00509 } else {
00510 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
00511 return &null_frame;
00512 }
00513 }
00514 rtp->f.subclass = rtpPT.code;
00515 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
00516 rtp->f.frametype = AST_FRAME_VOICE;
00517 else
00518 rtp->f.frametype = AST_FRAME_VIDEO;
00519 rtp->lastrxformat = rtp->f.subclass;
00520
00521 if (!rtp->lastrxts)
00522 rtp->lastrxts = timestamp;
00523
00524 if (rtp->dtmfcount) {
00525 #if 0
00526 printf("dtmfcount was %d\n", rtp->dtmfcount);
00527 #endif
00528 rtp->dtmfcount -= (timestamp - rtp->lastrxts);
00529 if (rtp->dtmfcount < 0)
00530 rtp->dtmfcount = 0;
00531 #if 0
00532 if (dtmftimeout != rtp->dtmfcount)
00533 printf("dtmfcount is %d\n", rtp->dtmfcount);
00534 #endif
00535 }
00536 rtp->lastrxts = timestamp;
00537
00538 /* Send any pending DTMF */
00539 if (rtp->resp && !rtp->dtmfcount) {
00540 ast_log(LOG_DEBUG, "Sending pending DTMF\n");
00541 return send_dtmf(rtp);
00542 }
00543 rtp->f.mallocd = 0;
00544 rtp->f.datalen = res - hdrlen;
00545 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
00546 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
00547 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
00548 switch(rtp->f.subclass) {
00549 case AST_FORMAT_ULAW:
00550 case AST_FORMAT_ALAW:
00551 rtp->f.samples = rtp->f.datalen;
00552 break;
00553 case AST_FORMAT_SLINEAR:
00554 rtp->f.samples = rtp->f.datalen / 2;
00555 break;
00556 case AST_FORMAT_GSM:
00557 rtp->f.samples = 160 * (rtp->f.datalen / 33);
00558 break;
00559 case AST_FORMAT_ILBC:
00560 rtp->f.samples = 240 * (rtp->f.datalen / 50);
00561 break;
00562 case AST_FORMAT_ADPCM:
00563 case AST_FORMAT_G726:
00564 rtp->f.samples = rtp->f.datalen * 2;
00565 break;
00566 case AST_FORMAT_G729A:
00567 rtp->f.samples = rtp->f.datalen * 8;
00568 break;
00569 case AST_FORMAT_G723_1:
00570 rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen);
00571 break;
00572 case AST_FORMAT_SPEEX:
00573 /* assumes that the RTP packet contained one Speex frame */
00574 rtp->f.samples = 160;
00575 break;
00576 case AST_FORMAT_LPC10:
00577 rtp->f.samples = 22 * 8;
00578 rtp->f.samples += (((char *)(rtp->f.data))[7] & 0x1) * 8;
00579 break;
00580 default:
00581 ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass));
00582 break;
00583 }
00584 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
00585 } else {
00586 /* Video -- samples is # of samples vs. 90000 */
00587 if (!rtp->lastividtimestamp)
00588 rtp->lastividtimestamp = timestamp;
00589 rtp->f.samples = timestamp - rtp->lastividtimestamp;
00590 rtp->lastividtimestamp = timestamp;
00591 rtp->f.delivery.tv_sec = 0;
00592 rtp->f.delivery.tv_usec = 0;
00593 if (mark)
00594 rtp->f.subclass |= 0x1;
00595
00596 }
00597 rtp->f.src = "RTP";
00598 return &rtp->f;
00599 }
|
|
|
Definition at line 1539 of file rtp.c. References ast_destroy(), ast_load(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verbose(), LOG_WARNING, option_verbose, and VERBOSE_PREFIX_2. Referenced by ast_module_reload(), ast_rtp_init(), and main(). 01540 {
01541 struct ast_config *cfg;
01542 char *s;
01543 rtpstart = 5000;
01544 rtpend = 31000;
01545 #ifdef SO_NO_CHECK
01546 checksums = 1;
01547 #endif
01548 cfg = ast_load("rtp.conf");
01549 if (cfg) {
01550 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01551 rtpstart = atoi(s);
01552 if (rtpstart < 1024)
01553 rtpstart = 1024;
01554 if (rtpstart > 65535)
01555 rtpstart = 65535;
01556 }
01557 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01558 rtpend = atoi(s);
01559 if (rtpend < 1024)
01560 rtpend = 1024;
01561 if (rtpend > 65535)
01562 rtpend = 65535;
01563 }
01564 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
01565 #ifdef SO_NO_CHECK
01566 if (ast_true(s))
01567 checksums = 1;
01568 else
01569 checksums = 0;
01570 #else
01571 if (ast_true(s))
01572 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
01573 #endif
01574 }
01575 ast_destroy(cfg);
01576 }
01577 if (rtpstart >= rtpend) {
01578 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n");
01579 rtpstart = 5000;
01580 rtpend = 31000;
01581 }
01582 if (option_verbose > 1)
01583 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01584 }
|
|
||||||||||||
|
Definition at line 997 of file rtp.c. References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_NOTICE, LOG_WARNING, ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them. 00998 {
00999 unsigned int *rtpheader;
01000 int hdrlen = 12;
01001 int res;
01002 int x;
01003 int payload;
01004 char data[256];
01005 char iabuf[INET_ADDRSTRLEN];
01006
01007 if ((digit <= '9') && (digit >= '0'))
01008 digit -= '0';
01009 else if (digit == '*')
01010 digit = 10;
01011 else if (digit == '#')
01012 digit = 11;
01013 else if ((digit >= 'A') && (digit <= 'D'))
01014 digit = digit - 'A' + 12;
01015 else if ((digit >= 'a') && (digit <= 'd'))
01016 digit = digit - 'a' + 12;
01017 else {
01018 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
01019 return -1;
01020 }
01021 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
01022
01023 /* If we have no peer, return immediately */
01024 if (!rtp->them.sin_addr.s_addr)
01025 return 0;
01026
01027 gettimeofday(&rtp->dtmfmute, NULL);
01028 rtp->dtmfmute.tv_usec += (500 * 1000);
01029 if (rtp->dtmfmute.tv_usec > 1000000) {
01030 rtp->dtmfmute.tv_usec -= 1000000;
01031 rtp->dtmfmute.tv_sec += 1;
01032 }
01033
01034 /* Get a pointer to the header */
01035 rtpheader = (unsigned int *)data;
01036 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
01037 rtpheader[1] = htonl(rtp->lastts);
01038 rtpheader[2] = htonl(rtp->ssrc);
01039 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
01040 for (x=0;x<6;x++) {
01041 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01042 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01043 if (res <0)
01044 ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
01045 #if 0
01046 printf("Sent %d bytes of RTP data to %s:%d\n", res, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
01047 #endif
01048 }
01049 if (x == 2) {
01050 /* Clear marker bit and increment seqno */
01051 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++));
01052 /* Make duration 800 (100ms) */
01053 rtpheader[3] |= htonl((800));
01054 /* Set the End bit for the last 3 */
01055 rtpheader[3] |= htonl((1 << 23));
01056 } else if ( x < 5) {
01057 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++));
01058 }
01059 }
01060 return 0;
01061 }
|
|
||||||||||||
|
Definition at line 167 of file rtp.c. References ast_rtp::callback. 00168 {
00169 rtp->callback = callback;
00170 }
|
|
||||||||||||
|
Definition at line 162 of file rtp.c. References ast_rtp::data. 00163 {
00164 rtp->data = data;
00165 }
|
|
||||||||||||
|
Definition at line 687 of file rtp.c. References rtpPayloadType::code. 00687 {
00688 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */
00689
00690 if (static_RTP_PT[pt].code != 0) {
00691 rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00692 }
00693 }
|
|
||||||||||||
|
Definition at line 924 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them. 00925 {
00926 rtp->them.sin_port = them->sin_port;
00927 rtp->them.sin_addr = them->sin_addr;
00928 if (rtp->rtcp) {
00929 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
00930 rtp->rtcp->them.sin_addr = them->sin_addr;
00931 }
00932 }
|
|
||||||||||||||||||||
|
Definition at line 697 of file rtp.c. References ast_rtp::current_RTP_PT, subtype, and type. 00698 {
00699 int i;
00700
00701 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */
00702
00703 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00704 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00705 strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00706 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00707 return;
00708 }
00709 }
00710 }
|
|
||||||||||||
|
Definition at line 172 of file rtp.c. References ast_rtp::nat. 00173 {
00174 rtp->nat = nat;
00175 }
|
|
||||||||||||
|
Definition at line 916 of file rtp.c. References ast_log(), LOG_WARNING, and ast_rtp::s. 00917 {
00918 int res;
00919 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
00920 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
00921 return res;
00922 }
|
|
|
Definition at line 946 of file rtp.c. References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them. 00947 {
00948 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00949 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00950 if (rtp->rtcp) {
00951 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00952 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00953 }
00954 }
|
|
||||||||||||
|
Definition at line 1159 of file rtp.c. References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_ILBC, AST_FORMAT_LPC10, 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_FLAG_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::offset, ast_frame::subclass, and ast_rtp::them. 01160 {
01161 struct ast_frame *f;
01162 int codec;
01163 int hdrlen = 12;
01164 int subclass;
01165
01166
01167 /* If we have no peer, return immediately */
01168 if (!rtp->them.sin_addr.s_addr)
01169 return 0;
01170
01171 /* If there is no data length, return immediately */
01172 if (!_f->datalen)
01173 return 0;
01174
01175 /* Make sure we have enough space for RTP header */
01176 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
01177 ast_log(LOG_WARNING, "RTP can only send voice\n");
01178 return -1;
01179 }
01180
01181 subclass = _f->subclass;
01182 if (_f->frametype == AST_FRAME_VIDEO)
01183 subclass &= ~0x1;
01184
01185 codec = ast_rtp_lookup_code(rtp, 1, subclass);
01186 if (codec < 0) {
01187 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
01188 return -1;
01189 }
01190
01191 if (rtp->lasttxformat != subclass) {
01192 /* New format, reset the smoother */
01193 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01194 rtp->lasttxformat = subclass;
01195 if (rtp->smoother)
01196 ast_smoother_free(rtp->smoother);
01197 rtp->smoother = NULL;
01198 }
01199
01200
01201 switch(subclass) {
01202 case AST_FORMAT_ULAW:
01203 case AST_FORMAT_ALAW:
01204 if (!rtp->smoother) {
01205 rtp->smoother = ast_smoother_new(160);
01206 }
01207 if (!rtp->smoother) {
01208 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01209 return -1;
01210 }
01211 ast_smoother_feed(rtp->smoother, _f);
01212
01213 while((f = ast_smoother_read(rtp->smoother)))
01214 ast_rtp_raw_write(rtp, f, codec);
01215 break;
01216 case AST_FORMAT_ADPCM:
01217 case AST_FORMAT_G726:
01218 if (!rtp->smoother) {
01219 rtp->smoother = ast_smoother_new(80);
01220 }
01221 if (!rtp->smoother) {
01222 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01223 return -1;
01224 }
01225 ast_smoother_feed(rtp->smoother, _f);
01226
01227 while((f = ast_smoother_read(rtp->smoother)))
01228 ast_rtp_raw_write(rtp, f, codec);
01229 break;
01230 case AST_FORMAT_G729A:
01231 if (!rtp->smoother) {
01232 rtp->smoother = ast_smoother_new(20);
01233 if (rtp->smoother)
01234 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
01235 }
01236 if (!rtp->smoother) {
01237 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
01238 return -1;
01239 }
01240 ast_smoother_feed(rtp->smoother, _f);
01241
01242 while((f = ast_smoother_read(rtp->smoother)))
01243 ast_rtp_raw_write(rtp, f, codec);
01244 break;
01245 case AST_FORMAT_GSM:
01246 if (!rtp->smoother) {
01247 rtp->smoother = ast_smoother_new(33);
01248 }
01249 if (!rtp->smoother) {
01250 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
01251 return -1;
01252 }
01253 ast_smoother_feed(rtp->smoother, _f);
01254 while((f = ast_smoother_read(rtp->smoother)))
01255 ast_rtp_raw_write(rtp, f, codec);
01256 break;
01257 case AST_FORMAT_ILBC:
01258 if (!rtp->smoother) {
01259 rtp->smoother = ast_smoother_new(50);
01260 }
01261 if (!rtp->smoother) {
01262 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
01263 return -1;
01264 }
01265 ast_smoother_feed(rtp->smoother, _f);
01266 while((f = ast_smoother_read(rtp->smoother)))
01267 ast_rtp_raw_write(rtp, f, codec);
01268 break;
01269 default:
01270 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
01271 /* fall through to... */
01272 case AST_FORMAT_H261:
01273 case AST_FORMAT_H263:
01274 case AST_FORMAT_G723_1:
01275 case AST_FORMAT_LPC10:
01276 case AST_FORMAT_SPEEX:
01277 /* Don't buffer outgoing frames; send them one-per-packet: */
01278 if (_f->offset < hdrlen) {
01279 f = ast_frdup(_f);
01280 } else {
01281 f = _f;
01282 }
01283 ast_rtp_raw_write(rtp, f, codec);
01284 }
01285
01286 return 0;
01287 }
|
1.4.2