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

rtp.h File Reference

#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_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
ast_rtpast_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_frameast_rtp_read (struct ast_rtp *rtp)
ast_frameast_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)


Define Documentation

#define AST_RTP_CISCO_DTMF   (1 << 2)
 

DTMF (Cisco Proprietary)

Definition at line 34 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_CN   (1 << 1)
 

'Comfort Noise' (RFC3389)

Definition at line 32 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_DTMF   (1 << 0)
 

DTMF (RFC2833)

Definition at line 30 of file rtp.h.

Referenced by ast_rtp_read(), and ast_rtp_senddigit().

#define AST_RTP_MAX   AST_RTP_CISCO_DTMF
 

Maximum RTP-specific code

Definition at line 36 of file rtp.h.


Typedef Documentation

typedef int(* ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data)
 

Definition at line 49 of file rtp.h.


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 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 }

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 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 }

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

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 }

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 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 }

void ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

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 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 941 of file rtp.c.

References ast_rtp::us.

00942 {
00943    memcpy(us, &rtp->us, sizeof(rtp->us));
00944 }

void ast_rtp_init void   ) 
 

Definition at line 1586 of file rtp.c.

References ast_rtp_reload().

Referenced by main().

01587 {
01588    ast_rtp_reload();
01589 }

int ast_rtp_lookup_code struct ast_rtp rtp,
int  isAstFormat,
int  code
 

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 }

char* ast_rtp_lookup_mime_subtype int  isAstFormat,
int  code
 

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 }

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

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 }

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

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 }

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

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 }

void ast_rtp_offered_from_local struct ast_rtp rtp,
int  local
 

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 }

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

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 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

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 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

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 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

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 }

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

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 }

void ast_rtp_reload void   ) 
 

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 }

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

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 }

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.

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 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 } 

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

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 }

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

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 } 

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 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 }

void ast_rtp_stop struct ast_rtp rtp  ) 
 

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 }

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame f
 

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 }


Generated on Sat Nov 25 19:10:24 2006 for Asterisk by  doxygen 1.4.2