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  ast_rtcp
struct  ast_rtp
struct  rtpPayloadType

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.

#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_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_NOTICE, and LOG_WARNING.

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_channel::_softhangup, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, ast_check_hangup(), ast_frfree(), 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::masq, ast_channel::masqr, ast_channel::name, ast_channel::pvt, ast_channel_pvt::pvt, and ast_rtp_protocol::set_rtp_peer.

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, and rtpPayloadType::isAstFormat.

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, 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 rtpPayloadType::code, and rtpPayloadType::isAstFormat.

Referenced by 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, ast_rtp::io, ast_rtp::ioid, LOG_WARNING, malloc, ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtp::us, and ast_rtcp::us.

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, 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, 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_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_frame::frametype, rtpPayloadType::isAstFormat, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

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, 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, and ast_rtp::current_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, 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_frdup(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_smoother_feed(), 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_channel_register(), ast_channel_register_ex(), ast_channel_unregister(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_rtp_set_rtpmap_type(), ast_search_dns(), and ast_writestream().


Generated on Thu Oct 28 11:33:06 2004 for Asterisk by doxygen1.2.15