Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

rtp.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <asterisk/rtp.h>
#include <asterisk/frame.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/acl.h>
#include <asterisk/channel_pvt.h>
#include <asterisk/config.h>
#include <asterisk/lock.h>
#include <asterisk/utils.h>

Go to the source code of this file.

Data Structures

struct  rtpPayloadType
struct  ast_rtp
struct  ast_rtcp

Defines

#define MAX_TIMESTAMP_SKEW   640
#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
#define FLAG_3389_WARNING   (1 << 0)

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_frameast_rtcp_read (struct ast_rtp *rtp)
ast_frameast_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)
void ast_rtp_offered_from_local (struct ast_rtp *rtp, int local)
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_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
ast_rtpast_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)


Define Documentation

#define FLAG_3389_WARNING   (1 << 0)
 

Definition at line 67 of file rtp.c.

#define MAX_RTP_PT   256
 

Definition at line 65 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().

#define MAX_TIMESTAMP_SKEW   640
 

Definition at line 41 of file rtp.c.

#define RTP_MTU   1200
 

Definition at line 43 of file rtp.c.

#define TYPE_DONTSEND   0x3
 

Definition at line 48 of file rtp.c.

#define TYPE_HIGH   0x0
 

Definition at line 45 of file rtp.c.

#define TYPE_LOW   0x1
 

Definition at line 46 of file rtp.c.

#define TYPE_MASK   0x3
 

Definition at line 49 of file rtp.c.

#define TYPE_SILENCE   0x2
 

Definition at line 47 of file rtp.c.


Function Documentation

int ast_rtcp_fd struct ast_rtp rtp  ) 
 

Definition at line 119 of file rtp.c.

References ast_rtp::rtcp, and ast_rtcp::s.

00120 { 00121 if (rtp->rtcp) 00122 return rtp->rtcp->s; 00123 return -1; 00124 }

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

Definition at line 326 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_rtcp::them, and ast_rtp::them.

00327 { 00328 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00329 int len; 00330 int hdrlen = 8; 00331 int res; 00332 struct sockaddr_in sin; 00333 unsigned int rtcpdata[1024]; 00334 char iabuf[INET_ADDRSTRLEN]; 00335 00336 if (!rtp->rtcp) 00337 return &null_frame; 00338 00339 len = sizeof(sin); 00340 00341 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata), 00342 0, (struct sockaddr *)&sin, &len); 00343 00344 if (res < 0) { 00345 if (errno == EAGAIN) 00346 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n"); 00347 else 00348 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 00349 if (errno == EBADF) 00350 CRASH; 00351 return &null_frame; 00352 } 00353 00354 if (res < hdrlen) { 00355 ast_log(LOG_WARNING, "RTP Read too short\n"); 00356 return &null_frame; 00357 } 00358 00359 if (rtp->nat) { 00360 /* Send to whoever sent to us */ 00361 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00362 (rtp->rtcp->them.sin_port != sin.sin_port)) { 00363 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00364 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)); 00365 } 00366 } 00367 if (option_debug) 00368 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res); 00369 return &null_frame; 00370 }

int ast_rtp_bridge struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc
 

Definition at line 1318 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_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::pvt, and ast_channel_pvt::pvt.

01319 { 01320 struct ast_frame *f; 01321 struct ast_channel *who, *cs[3]; 01322 struct ast_rtp *p0, *p1; 01323 struct ast_rtp *vp0, *vp1; 01324 struct ast_rtp_protocol *pr0, *pr1; 01325 struct sockaddr_in ac0, ac1; 01326 struct sockaddr_in vac0, vac1; 01327 struct sockaddr_in t0, t1; 01328 struct sockaddr_in vt0, vt1; 01329 char iabuf[INET_ADDRSTRLEN]; 01330 01331 void *pvt0, *pvt1; 01332 int to; 01333 int codec0,codec1, oldcodec0, oldcodec1; 01334 01335 memset(&vt0, 0, sizeof(vt0)); 01336 memset(&vt1, 0, sizeof(vt1)); 01337 memset(&vac0, 0, sizeof(vac0)); 01338 memset(&vac1, 0, sizeof(vac1)); 01339 01340 /* if need DTMF, cant native bridge */ 01341 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 01342 return -2; 01343 ast_mutex_lock(&c0->lock); 01344 while(ast_mutex_trylock(&c1->lock)) { 01345 ast_mutex_unlock(&c0->lock); 01346 usleep(1); 01347 ast_mutex_lock(&c0->lock); 01348 } 01349 pr0 = get_proto(c0); 01350 pr1 = get_proto(c1); 01351 if (!pr0) { 01352 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name); 01353 ast_mutex_unlock(&c0->lock); 01354 ast_mutex_unlock(&c1->lock); 01355 return -1; 01356 } 01357 if (!pr1) { 01358 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name); 01359 ast_mutex_unlock(&c0->lock); 01360 ast_mutex_unlock(&c1->lock); 01361 return -1; 01362 } 01363 pvt0 = c0->pvt->pvt; 01364 pvt1 = c1->pvt->pvt; 01365 p0 = pr0->get_rtp_info(c0); 01366 if (pr0->get_vrtp_info) 01367 vp0 = pr0->get_vrtp_info(c0); 01368 else 01369 vp0 = NULL; 01370 p1 = pr1->get_rtp_info(c1); 01371 if (pr1->get_vrtp_info) 01372 vp1 = pr1->get_vrtp_info(c1); 01373 else 01374 vp1 = NULL; 01375 if (!p0 || !p1) { 01376 /* Somebody doesn't want to play... */ 01377 ast_mutex_unlock(&c0->lock); 01378 ast_mutex_unlock(&c1->lock); 01379 return -2; 01380 } 01381 if (pr0->get_codec) 01382 codec0 = pr0->get_codec(c0); 01383 else 01384 codec0 = 0; 01385 if (pr1->get_codec) 01386 codec1 = pr1->get_codec(c1); 01387 else 01388 codec1 = 0; 01389 if (pr0->get_codec && pr1->get_codec) { 01390 /* Hey, we can't do reinvite if both parties speak diffrent codecs */ 01391 if (!(codec0 & codec1)) { 01392 ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1); 01393 ast_mutex_unlock(&c0->lock); 01394 ast_mutex_unlock(&c1->lock); 01395 return -2; 01396 } 01397 } 01398 if (pr0->set_rtp_peer(c0, p1, vp1, codec1)) 01399 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name); 01400 else { 01401 /* Store RTP peer */ 01402 ast_rtp_get_peer(p1, &ac1); 01403 if (vp1) 01404 ast_rtp_get_peer(vp1, &vac1); 01405 } 01406 if (pr1->set_rtp_peer(c1, p0, vp0, codec0)) 01407 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name); 01408 else { 01409 /* Store RTP peer */ 01410 ast_rtp_get_peer(p0, &ac0); 01411 if (vp0) 01412 ast_rtp_get_peer(vp0, &vac0); 01413 } 01414 ast_mutex_unlock(&c0->lock); 01415 ast_mutex_unlock(&c1->lock); 01416 cs[0] = c0; 01417 cs[1] = c1; 01418 cs[2] = NULL; 01419 oldcodec0 = codec0; 01420 oldcodec1 = codec1; 01421 for (;;) { 01422 if ((c0->pvt->pvt != pvt0) || 01423 (c1->pvt->pvt != pvt1) || 01424 (c0->masq || c0->masqr || c1->masq || c1->masqr)) { 01425 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n"); 01426 if (c0->pvt->pvt == pvt0) { 01427 if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 01428 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01429 } 01430 if (c1->pvt->pvt == pvt1) { 01431 if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 01432 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01433 } 01434 /* Tell it to try again later */ 01435 return -3; 01436 } 01437 to = -1; 01438 ast_rtp_get_peer(p1, &t1); 01439 ast_rtp_get_peer(p0, &t0); 01440 if (pr0->get_codec) 01441 codec0 = pr0->get_codec(c0); 01442 if (pr1->get_codec) 01443 codec1 = pr1->get_codec(c1); 01444 if (vp1) 01445 ast_rtp_get_peer(vp1, &vt1); 01446 if (vp0) 01447 ast_rtp_get_peer(vp0, &vt0); 01448 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) { 01449 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01450 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1); 01451 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n", 01452 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1); 01453 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01454 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1); 01455 ast_log(LOG_DEBUG, "Oooh, '%s' wasv %s:%d/(format %d)\n", 01456 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1); 01457 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1)) 01458 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name); 01459 memcpy(&ac1, &t1, sizeof(ac1)); 01460 memcpy(&vac1, &vt1, sizeof(vac1)); 01461 oldcodec1 = codec1; 01462 } 01463 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) { 01464 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n", 01465 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0); 01466 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n", 01467 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0); 01468 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0)) 01469 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name); 01470 memcpy(&ac0, &t0, sizeof(ac0)); 01471 memcpy(&vac0, &vt0, sizeof(vac0)); 01472 oldcodec0 = codec0; 01473 } 01474 who = ast_waitfor_n(cs, 2, &to); 01475 if (!who) { 01476 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 01477 /* check for hagnup / whentohangup */ 01478 if (ast_check_hangup(c0) || ast_check_hangup(c1)) 01479 break; 01480 continue; 01481 } 01482 f = ast_read(who); 01483 if (!f || ((f->frametype == AST_FRAME_DTMF) && 01484 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 01485 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) { 01486 *fo = f; 01487 *rc = who; 01488 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup"); 01489 if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) { 01490 if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 01491 ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name); 01492 } 01493 if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) { 01494 if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 01495 ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name); 01496 } 01497 /* That's all we needed */ 01498 return 0; 01499 } else { 01500 if ((f->frametype == AST_FRAME_DTMF) || 01501 (f->frametype == AST_FRAME_VOICE) || 01502 (f->frametype == AST_FRAME_VIDEO)) { 01503 /* Forward voice or DTMF frames if they happen upon us */ 01504 if (who == c0) { 01505 ast_write(c1, f); 01506 } else if (who == c1) { 01507 ast_write(c0, f); 01508 } 01509 } 01510 ast_frfree(f); 01511 } 01512 /* Swap priority not that it's a big deal at this point */ 01513 cs[2] = cs[0]; 01514 cs[0] = cs[1]; 01515 cs[1] = cs[2]; 01516 01517 } 01518 return -1; 01519 }

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Definition at line 935 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.

00936 { 00937 if (rtp->smoother) 00938 ast_smoother_free(rtp->smoother); 00939 if (rtp->ioid) 00940 ast_io_remove(rtp->io, rtp->ioid); 00941 if (rtp->s > -1) 00942 close(rtp->s); 00943 if (rtp->rtcp) { 00944 close(rtp->rtcp->s); 00945 free(rtp->rtcp); 00946 } 00947 free(rtp); 00948 }

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 114 of file rtp.c.

References ast_rtp::s.

00115 { 00116 return rtp->s; 00117 }

void ast_rtp_get_current_formats struct ast_rtp rtp,
int *  astFormats,
int *  nonAstFormats
 

Definition at line 693 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

00694 { 00695 int pt; 00696 00697 *astFormats = *nonAstFormats = 0; 00698 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00699 if (rtp->current_RTP_PT[pt].isAstFormat) { 00700 *astFormats |= rtp->current_RTP_PT[pt].code; 00701 } else { 00702 *nonAstFormats |= rtp->current_RTP_PT[pt].code; 00703 } 00704 } 00705 }

void ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 913 of file rtp.c.

References ast_rtp::them.

Referenced by ast_rtp_bridge().

00914 { 00915 them->sin_family = AF_INET; 00916 them->sin_port = rtp->them.sin_port; 00917 them->sin_addr = rtp->them.sin_addr; 00918 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 920 of file rtp.c.

References ast_rtp::us.

00921 { 00922 memcpy(us, &rtp->us, sizeof(rtp->us)); 00923 }

void ast_rtp_init void   ) 
 

Definition at line 1568 of file rtp.c.

References ast_rtp_reload().

Referenced by main().

01569 { 01570 ast_rtp_reload(); 01571 }

int ast_rtp_lookup_code struct ast_rtp rtp,
int  isAstFormat,
int  code
 

Definition at line 732 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_senddigit(), and ast_rtp_write().

00732 { 00733 int pt; 00734 00735 00736 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat && 00737 code == rtp->rtp_lookup_code_cache_code) { 00738 /* Use our cached mapping, to avoid the overhead of the loop below */ 00739 return rtp->rtp_lookup_code_cache_result; 00740 } 00741 00742 /* Check the dynamic list first */ 00743 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00744 if (rtp->current_RTP_PT[pt].code == code && 00745 rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) { 00746 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00747 rtp->rtp_lookup_code_cache_code = code; 00748 rtp->rtp_lookup_code_cache_result = pt; 00749 return pt; 00750 } 00751 } 00752 00753 /* Then the static list */ 00754 for (pt = 0; pt < MAX_RTP_PT; ++pt) { 00755 if (static_RTP_PT[pt].code == code && 00756 static_RTP_PT[pt].isAstFormat == isAstFormat) { 00757 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat; 00758 rtp->rtp_lookup_code_cache_code = code; 00759 rtp->rtp_lookup_code_cache_result = pt; 00760 return pt; 00761 } 00762 } 00763 return -1; 00764 }

char* ast_rtp_lookup_mime_subtype int  isAstFormat,
int  code
 

Definition at line 766 of file rtp.c.

00766 { 00767 int i; 00768 00769 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00770 if (mimeTypes[i].payloadType.code == code && 00771 mimeTypes[i].payloadType.isAstFormat == isAstFormat) { 00772 return mimeTypes[i].subtype; 00773 } 00774 } 00775 return ""; 00776 }

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

Definition at line 714 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().

00715 { 00716 struct rtpPayloadType result; 00717 00718 result.isAstFormat = result.code = 0; 00719 if (pt < 0 || pt > MAX_RTP_PT) { 00720 return result; /* bogus payload type */ 00721 } 00722 /* Start with the negotiated codecs */ 00723 if (!rtp->rtp_offered_from_local) 00724 result = rtp->current_RTP_PT[pt]; 00725 /* If it doesn't exist, check our static RTP type list, just in case */ 00726 if (!result.code) 00727 result = static_RTP_PT[pt]; 00728 return result; 00729 }

struct ast_rtp* ast_rtp_new struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode
 

Definition at line 888 of file rtp.c.

References ast_rtp_new_with_bindaddr().

00889 { 00890 struct in_addr ia; 00891 memset(&ia, 0, sizeof(ia)); 00892 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia); 00893 }

struct ast_rtp* ast_rtp_new_with_bindaddr struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode,
struct in_addr  addr
 

Definition at line 812 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().

00813 { 00814 struct ast_rtp *rtp; 00815 int x; 00816 int first; 00817 int startplace; 00818 rtp = malloc(sizeof(struct ast_rtp)); 00819 if (!rtp) 00820 return NULL; 00821 memset(rtp, 0, sizeof(struct ast_rtp)); 00822 rtp->them.sin_family = AF_INET; 00823 rtp->us.sin_family = AF_INET; 00824 rtp->s = rtp_socket(); 00825 rtp->ssrc = rand(); 00826 rtp->seqno = rand() & 0xffff; 00827 if (rtp->s < 0) { 00828 free(rtp); 00829 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00830 return NULL; 00831 } 00832 if (sched && rtcpenable) { 00833 rtp->sched = sched; 00834 rtp->rtcp = ast_rtcp_new(); 00835 } 00836 /* Find us a place */ 00837 x = (rand() % (rtpend-rtpstart)) + rtpstart; 00838 x = x & ~1; 00839 startplace = x; 00840 for (;;) { 00841 /* Must be an even port number by RTP spec */ 00842 rtp->us.sin_port = htons(x); 00843 rtp->us.sin_addr = addr; 00844 if (rtp->rtcp) 00845 rtp->rtcp->us.sin_port = htons(x + 1); 00846 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) && 00847 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))) 00848 break; 00849 if (!first) { 00850 /* Primary bind succeeded! Gotta recreate it */ 00851 close(rtp->s); 00852 rtp->s = rtp_socket(); 00853 } 00854 if (errno != EADDRINUSE) { 00855 ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno)); 00856 close(rtp->s); 00857 if (rtp->rtcp) { 00858 close(rtp->rtcp->s); 00859 free(rtp->rtcp); 00860 } 00861 free(rtp); 00862 return NULL; 00863 } 00864 x += 2; 00865 if (x > rtpend) 00866 x = (rtpstart + 1) & ~1; 00867 if (x == startplace) { 00868 ast_log(LOG_WARNING, "No RTP ports remaining\n"); 00869 close(rtp->s); 00870 if (rtp->rtcp) { 00871 close(rtp->rtcp->s); 00872 free(rtp->rtcp); 00873 } 00874 free(rtp); 00875 return NULL; 00876 } 00877 } 00878 if (io && sched && callbackmode) { 00879 /* Operate this one in a callback mode */ 00880 rtp->sched = sched; 00881 rtp->io = io; 00882 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp); 00883 } 00884 ast_rtp_pt_default(rtp); 00885 return rtp; 00886 }

void ast_rtp_offered_from_local struct ast_rtp rtp,
int  local
 

Definition at line 707 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local.

00707 { 00708 if (rtp) 00709 rtp->rtp_offered_from_local = local; 00710 else 00711 ast_log(LOG_WARNING, "rtp structure is null\n"); 00712 }

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

Definition at line 1289 of file rtp.c.

References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.

01290 { 01291 struct ast_rtp_protocol *cur; 01292 cur = protos; 01293 while(cur) { 01294 if (cur->type == proto->type) { 01295 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type); 01296 return -1; 01297 } 01298 cur = cur->next; 01299 } 01300 proto->next = protos; 01301 protos = proto; 01302 return 0; 01303 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Definition at line 1271 of file rtp.c.

References ast_rtp_protocol::next.

01272 { 01273 struct ast_rtp_protocol *cur, *prev; 01274 cur = protos; 01275 prev = NULL; 01276 while(cur) { 01277 if (cur == proto) { 01278 if (prev) 01279 prev->next = proto->next; 01280 else 01281 protos = proto->next; 01282 return; 01283 } 01284 prev = cur; 01285 cur = cur->next; 01286 } 01287 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

Definition at line 635 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.

00636 { 00637 int i; 00638 00639 for (i = 0; i < MAX_RTP_PT; ++i) { 00640 rtp->current_RTP_PT[i].isAstFormat = 0; 00641 rtp->current_RTP_PT[i].code = 0; 00642 } 00643 00644 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00645 rtp->rtp_lookup_code_cache_code = 0; 00646 rtp->rtp_lookup_code_cache_result = 0; 00647 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

Definition at line 649 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_with_bindaddr().

00650 { 00651 int i; 00652 /* Initialize to default payload types */ 00653 for (i = 0; i < MAX_RTP_PT; ++i) { 00654 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat; 00655 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code; 00656 } 00657 00658 rtp->rtp_lookup_code_cache_isAstFormat = 0; 00659 rtp->rtp_lookup_code_cache_code = 0; 00660 rtp->rtp_lookup_code_cache_result = 0; 00661 }

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

Definition at line 394 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.

00395 { 00396 int res; 00397 struct sockaddr_in sin; 00398 int len; 00399 unsigned int seqno; 00400 int payloadtype; 00401 int hdrlen = 12; 00402 int mark; 00403 int ext; 00404 char iabuf[INET_ADDRSTRLEN]; 00405 unsigned int timestamp; 00406 unsigned int *rtpheader; 00407 static struct ast_frame *f, null_frame = { AST_FRAME_NULL, }; 00408 struct rtpPayloadType rtpPT; 00409 00410 len = sizeof(sin); 00411 00412 /* Cache where the header will go */ 00413 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 00414 0, (struct sockaddr *)&sin, &len); 00415 00416 00417 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET); 00418 if (res < 0) { 00419 if (errno == EAGAIN) 00420 ast_log(LOG_NOTICE, "RTP: Received packet with bad UDP checksum\n"); 00421 else 00422 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); 00423 if (errno == EBADF) 00424 CRASH; 00425 return &null_frame; 00426 } 00427 if (res < hdrlen) { 00428 ast_log(LOG_WARNING, "RTP Read too short\n"); 00429 return &null_frame; 00430 } 00431 00432 /* Ignore if the other side hasn't been given an address 00433 yet. */ 00434 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port) 00435 return &null_frame; 00436 00437 if (rtp->nat) { 00438 /* Send to whoever sent to us */ 00439 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) || 00440 (rtp->them.sin_port != sin.sin_port)) { 00441 memcpy(&rtp->them, &sin, sizeof(rtp->them)); 00442 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)); 00443 } 00444 } 00445 00446 /* Get fields */ 00447 seqno = ntohl(rtpheader[0]); 00448 payloadtype = (seqno & 0x7f0000) >> 16; 00449 mark = seqno & (1 << 23); 00450 ext = seqno & (1 << 28); 00451 seqno &= 0xffff; 00452 timestamp = ntohl(rtpheader[1]); 00453 if (ext) { 00454 /* RTP Extension present */ 00455 hdrlen += 4; 00456 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2; 00457 } 00458 00459 if (res < hdrlen) { 00460 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen); 00461 return &null_frame; 00462 } 00463 00464 #if 0 00465 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); 00466 #endif 00467 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); 00468 if (!rtpPT.isAstFormat) { 00469 /* This is special in-band data that's not one of our codecs */ 00470 if (rtpPT.code == AST_RTP_DTMF) { 00471 /* It's special -- rfc2833 process it */ 00472 if (rtp->lasteventseqn <= seqno) { 00473 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00474 rtp->lasteventseqn = seqno; 00475 } 00476 if (f) return f; else return &null_frame; 00477 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) { 00478 /* It's really special -- process it the Cisco way */ 00479 if (rtp->lasteventseqn <= seqno) { 00480 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00481 rtp->lasteventseqn = seqno; 00482 } 00483 if (f) return f; else return &null_frame; 00484 } else if (rtpPT.code == AST_RTP_CN) { 00485 /* Comfort Noise */ 00486 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen); 00487 if (f) return f; else return &null_frame; 00488 } else { 00489 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype); 00490 return &null_frame; 00491 } 00492 } 00493 rtp->f.subclass = rtpPT.code; 00494 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) 00495 rtp->f.frametype = AST_FRAME_VOICE; 00496 else 00497 rtp->f.frametype = AST_FRAME_VIDEO; 00498 rtp->lastrxformat = rtp->f.subclass; 00499 00500 if (!rtp->lastrxts) 00501 rtp->lastrxts = timestamp; 00502 00503 if (rtp->dtmfcount) { 00504 #if 0 00505 printf("dtmfcount was %d\n", rtp->dtmfcount); 00506 #endif 00507 rtp->dtmfcount -= (timestamp - rtp->lastrxts); 00508 if (rtp->dtmfcount < 0) 00509 rtp->dtmfcount = 0; 00510 #if 0 00511 if (dtmftimeout != rtp->dtmfcount) 00512 printf("dtmfcount is %d\n", rtp->dtmfcount); 00513 #endif 00514 } 00515 rtp->lastrxts = timestamp; 00516 00517 /* Send any pending DTMF */ 00518 if (rtp->resp && !rtp->dtmfcount) { 00519 ast_log(LOG_DEBUG, "Sending pending DTMF\n"); 00520 return send_dtmf(rtp); 00521 } 00522 rtp->f.mallocd = 0; 00523 rtp->f.datalen = res - hdrlen; 00524 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; 00525 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; 00526 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { 00527 switch(rtp->f.subclass) { 00528 case AST_FORMAT_ULAW: 00529 case AST_FORMAT_ALAW: 00530 rtp->f.samples = rtp->f.datalen; 00531 break; 00532 case AST_FORMAT_SLINEAR: 00533 rtp->f.samples = rtp->f.datalen / 2; 00534 break; 00535 case AST_FORMAT_GSM: 00536 rtp->f.samples = 160 * (rtp->f.datalen / 33); 00537 break; 00538 case AST_FORMAT_ILBC: 00539 rtp->f.samples = 240 * (rtp->f.datalen / 50); 00540 break; 00541 case AST_FORMAT_ADPCM: 00542 case AST_FORMAT_G726: 00543 rtp->f.samples = rtp->f.datalen * 2; 00544 break; 00545 case AST_FORMAT_G729A: 00546 rtp->f.samples = rtp->f.datalen * 8; 00547 break; 00548 case AST_FORMAT_G723_1: 00549 rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen); 00550 break; 00551 case AST_FORMAT_SPEEX: 00552 /* assumes that the RTP packet contained one Speex frame */ 00553 rtp->f.samples = 160; 00554 break; 00555 case AST_FORMAT_LPC10: 00556 rtp->f.samples = 22 * 8; 00557 rtp->f.samples += (((char *)(rtp->f.data))[7] & 0x1) * 8; 00558 break; 00559 default: 00560 ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass)); 00561 break; 00562 } 00563 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); 00564 } else { 00565 /* Video -- samples is # of samples vs. 90000 */ 00566 if (!rtp->lastividtimestamp) 00567 rtp->lastividtimestamp = timestamp; 00568 rtp->f.samples = timestamp - rtp->lastividtimestamp; 00569 rtp->lastividtimestamp = timestamp; 00570 rtp->f.delivery.tv_sec = 0; 00571 rtp->f.delivery.tv_usec = 0; 00572 if (mark) 00573 rtp->f.subclass |= 0x1; 00574 00575 } 00576 rtp->f.src = "RTP"; 00577 return &rtp->f; 00578 }

void ast_rtp_reload void   ) 
 

Definition at line 1521 of file rtp.c.

References ast_destroy(), ast_load(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verbose(), LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2.

Referenced by ast_module_reload(), ast_rtp_init(), and main().

01522 { 01523 struct ast_config *cfg; 01524 char *s; 01525 rtpstart = 5000; 01526 rtpend = 31000; 01527 #ifdef SO_NO_CHECK 01528 checksums = 1; 01529 #endif 01530 cfg = ast_load("rtp.conf"); 01531 if (cfg) { 01532 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { 01533 rtpstart = atoi(s); 01534 if (rtpstart < 1024) 01535 rtpstart = 1024; 01536 if (rtpstart > 65535) 01537 rtpstart = 65535; 01538 } 01539 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) { 01540 rtpend = atoi(s); 01541 if (rtpend < 1024) 01542 rtpend = 1024; 01543 if (rtpend > 65535) 01544 rtpend = 65535; 01545 } 01546 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) { 01547 #ifdef SO_NO_CHECK 01548 if (ast_true(s)) 01549 checksums = 1; 01550 else 01551 checksums = 0; 01552 #else 01553 if (ast_true(s)) 01554 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n"); 01555 #endif 01556 } 01557 ast_destroy(cfg); 01558 } 01559 if (rtpstart >= rtpend) { 01560 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n"); 01561 rtpstart = 5000; 01562 rtpend = 31000; 01563 } 01564 if (option_verbose > 1) 01565 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend); 01566 }

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

Definition at line 976 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.

00977 { 00978 unsigned int *rtpheader; 00979 int hdrlen = 12; 00980 int res; 00981 int ms; 00982 int x; 00983 int payload; 00984 char data[256]; 00985 char iabuf[INET_ADDRSTRLEN]; 00986 00987 if ((digit <= '9') && (digit >= '0')) 00988 digit -= '0'; 00989 else if (digit == '*') 00990 digit = 10; 00991 else if (digit == '#') 00992 digit = 11; 00993 else if ((digit >= 'A') && (digit <= 'D')) 00994 digit = digit - 'A' + 12; 00995 else if ((digit >= 'a') && (digit <= 'd')) 00996 digit = digit - 'a' + 12; 00997 else { 00998 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit); 00999 return -1; 01000 } 01001 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF); 01002 01003 /* If we have no peer, return immediately */ 01004 if (!rtp->them.sin_addr.s_addr) 01005 return 0; 01006 01007 gettimeofday(&rtp->dtmfmute, NULL); 01008 rtp->dtmfmute.tv_usec += (500 * 1000); 01009 if (rtp->dtmfmute.tv_usec > 1000000) { 01010 rtp->dtmfmute.tv_usec -= 1000000; 01011 rtp->dtmfmute.tv_sec += 1; 01012 } 01013 01014 ms = calc_txstamp(rtp, NULL); 01015 /* Default prediction */ 01016 rtp->lastts = rtp->lastts + ms * 8; 01017 01018 /* Get a pointer to the header */ 01019 rtpheader = (unsigned int *)data; 01020 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); 01021 rtpheader[1] = htonl(rtp->lastts); 01022 rtpheader[2] = htonl(rtp->ssrc); 01023 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0)); 01024 for (x=0;x<4;x++) { 01025 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { 01026 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); 01027 if (res <0) 01028 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)); 01029 #if 0 01030 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)); 01031 #endif 01032 } 01033 if (x ==0) { 01034 /* Clear marker bit and increment seqno */ 01035 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno++)); 01036 /* Make duration 800 (100ms) */ 01037 rtpheader[3] |= htonl((800)); 01038 /* Set the End bit for the last 3 */ 01039 rtpheader[3] |= htonl((1 << 23)); 01040 } 01041 } 01042 return 0; 01043 }

void ast_rtp_set_callback struct ast_rtp rtp,
ast_rtp_callback  callback
 

Definition at line 167 of file rtp.c.

References ast_rtp_callback, and ast_rtp::callback.

00168 { 00169 rtp->callback = callback; 00170 }

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 162 of file rtp.c.

References ast_rtp::data.

00163 { 00164 rtp->data = data; 00165 }

void ast_rtp_set_m_type struct ast_rtp rtp,
int  pt
 

Definition at line 666 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.

00666 { 00667 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */ 00668 00669 if (static_RTP_PT[pt].code != 0) { 00670 rtp->current_RTP_PT[pt] = static_RTP_PT[pt]; 00671 } 00672 }

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 903 of file rtp.c.

References ast_rtp::rtcp, ast_rtp::them, and ast_rtcp::them.

00904 { 00905 rtp->them.sin_port = them->sin_port; 00906 rtp->them.sin_addr = them->sin_addr; 00907 if (rtp->rtcp) { 00908 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1); 00909 rtp->rtcp->them.sin_addr = them->sin_addr; 00910 } 00911 }

void ast_rtp_set_rtpmap_type struct ast_rtp rtp,
int  pt,
char *  mimeType,
char *  mimeSubtype
 

Definition at line 676 of file rtp.c.

References ast_rtp::current_RTP_PT, MAX_RTP_PT, subtype, and type.

00677 { 00678 int i; 00679 00680 if (pt < 0 || pt > MAX_RTP_PT) return; /* bogus payload type */ 00681 00682 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) { 00683 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 && 00684 strcasecmp(mimeType, mimeTypes[i].type) == 0) { 00685 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType; 00686 return; 00687 } 00688 } 00689 }

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

Definition at line 172 of file rtp.c.

References ast_rtp::nat.

00173 { 00174 rtp->nat = nat; 00175 }

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 895 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::s.

00896 { 00897 int res; 00898 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 00899 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos); 00900 return res; 00901 }

void ast_rtp_stop struct ast_rtp rtp  ) 
 

Definition at line 925 of file rtp.c.

References ast_rtp::rtcp, ast_rtp::them, and ast_rtcp::them.

00926 { 00927 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00928 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00929 if (rtp->rtcp) { 00930 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr)); 00931 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port)); 00932 } 00933 }

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame _f
 

Definition at line 1141 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, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

01142 { 01143 struct ast_frame *f; 01144 int codec; 01145 int hdrlen = 12; 01146 int subclass; 01147 01148 01149 /* If we have no peer, return immediately */ 01150 if (!rtp->them.sin_addr.s_addr) 01151 return 0; 01152 01153 /* If there is no data length, return immediately */ 01154 if (!_f->datalen) 01155 return 0; 01156 01157 /* Make sure we have enough space for RTP header */ 01158 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) { 01159 ast_log(LOG_WARNING, "RTP can only send voice\n"); 01160 return -1; 01161 } 01162 01163 subclass = _f->subclass; 01164 if (_f->frametype == AST_FRAME_VIDEO) 01165 subclass &= ~0x1; 01166 01167 codec = ast_rtp_lookup_code(rtp, 1, subclass); 01168 if (codec < 0) { 01169 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass)); 01170 return -1; 01171 } 01172 01173 if (rtp->lasttxformat != subclass) { 01174 /* New format, reset the smoother */ 01175 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass)); 01176 rtp->lasttxformat = subclass; 01177 if (rtp->smoother) 01178 ast_smoother_free(rtp->smoother); 01179 rtp->smoother = NULL; 01180 } 01181 01182 01183 switch(subclass) { 01184 case AST_FORMAT_ULAW: 01185 case AST_FORMAT_ALAW: 01186 if (!rtp->smoother) { 01187 rtp->smoother = ast_smoother_new(160); 01188 } 01189 if (!rtp->smoother) { 01190 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01191 return -1; 01192 } 01193 ast_smoother_feed(rtp->smoother, _f); 01194 01195 while((f = ast_smoother_read(rtp->smoother))) 01196 ast_rtp_raw_write(rtp, f, codec); 01197 break; 01198 case AST_FORMAT_ADPCM: 01199 case AST_FORMAT_G726: 01200 if (!rtp->smoother) { 01201 rtp->smoother = ast_smoother_new(80); 01202 } 01203 if (!rtp->smoother) { 01204 ast_log(LOG_WARNING, "Unable to create smoother :(\n"); 01205 return -1; 01206 } 01207 ast_smoother_feed(rtp->smoother, _f); 01208 01209 while((f = ast_smoother_read(rtp->smoother))) 01210 ast_rtp_raw_write(rtp, f, codec); 01211 break; 01212 case AST_FORMAT_G729A: 01213 if (!rtp->smoother) { 01214 rtp->smoother = ast_smoother_new(20); 01215 if (rtp->smoother) 01216 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729); 01217 } 01218 if (!rtp->smoother) { 01219 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n"); 01220 return -1; 01221 } 01222 ast_smoother_feed(rtp->smoother, _f); 01223 01224 while((f = ast_smoother_read(rtp->smoother))) 01225 ast_rtp_raw_write(rtp, f, codec); 01226 break; 01227 case AST_FORMAT_GSM: 01228 if (!rtp->smoother) { 01229 rtp->smoother = ast_smoother_new(33); 01230 } 01231 if (!rtp->smoother) { 01232 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n"); 01233 return -1; 01234 } 01235 ast_smoother_feed(rtp->smoother, _f); 01236 while((f = ast_smoother_read(rtp->smoother))) 01237 ast_rtp_raw_write(rtp, f, codec); 01238 break; 01239 case AST_FORMAT_ILBC: 01240 if (!rtp->smoother) { 01241 rtp->smoother = ast_smoother_new(50); 01242 } 01243 if (!rtp->smoother) { 01244 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n"); 01245 return -1; 01246 } 01247 ast_smoother_feed(rtp->smoother, _f); 01248 while((f = ast_smoother_read(rtp->smoother))) 01249 ast_rtp_raw_write(rtp, f, codec); 01250 break; 01251 default: 01252 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass)); 01253 /* fall through to... */ 01254 case AST_FORMAT_H261: 01255 case AST_FORMAT_H263: 01256 case AST_FORMAT_G723_1: 01257 case AST_FORMAT_LPC10: 01258 case AST_FORMAT_SPEEX: 01259 /* Don't buffer outgoing frames; send them one-per-packet: */ 01260 if (_f->offset < hdrlen) { 01261 f = ast_frdup(_f); 01262 } else { 01263 f = _f; 01264 } 01265 ast_rtp_raw_write(rtp, f, codec); 01266 } 01267 01268 return 0; 01269 }


Variable Documentation

struct rtpPayloadType payloadType
 

Definition at line 583 of file rtp.c.

char* subtype
 

Definition at line 585 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type
 

Definition at line 584 of file rtp.c.

Referenced by __ast_request_and_dial(), ast_channel_register(), ast_channel_register_ex(), ast_channel_unregister(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_readfile(), ast_request(), ast_request_and_dial(), ast_rtp_set_rtpmap_type(), ast_search_dns(), ast_writefile(), and ast_writestream().


Generated on Fri Sep 24 21:03:54 2004 for Asterisk by doxygen 1.3.8