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

rtp.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Real-time Protocol Support
00005  * 
00006  * Copyright (C) 1999, Mark Spencer
00007  *
00008  * Mark Spencer <markster@linux-support.net>
00009  *
00010  * This program is free software, distributed under the terms of
00011  * the GNU General Public License
00012  */
00013 
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <pthread.h>
00017 #include <string.h>
00018 #include <sys/time.h>
00019 #include <signal.h>
00020 #include <errno.h>
00021 #include <unistd.h>
00022 #include <netinet/in.h>
00023 #include <sys/time.h>
00024 #include <sys/socket.h>
00025 #include <arpa/inet.h>
00026 #include <fcntl.h>
00027 
00028 #include <asterisk/rtp.h>
00029 #include <asterisk/frame.h>
00030 #include <asterisk/logger.h>
00031 #include <asterisk/options.h>
00032 #include <asterisk/channel.h>
00033 #include <asterisk/acl.h>
00034 #include <asterisk/channel.h>
00035 #include <asterisk/channel_pvt.h>
00036 #include <asterisk/config.h>
00037 
00038 #define RTP_MTU      1200
00039 
00040 #define TYPE_HIGH  0x0
00041 #define TYPE_LOW   0x1
00042 #define TYPE_SILENCE  0x2
00043 #define TYPE_DONTSEND    0x3
00044 #define TYPE_MASK  0x3
00045 
00046 static int dtmftimeout = 300; /* 300 samples */
00047 
00048 static int rtpstart = 0;
00049 static int rtpend = 0;
00050 
00051 // The value of each payload format mapping:
00052 struct rtpPayloadType {
00053   int isAstFormat; // whether the following code is an AST_FORMAT
00054   int code;
00055 };
00056 
00057 #define MAX_RTP_PT 256
00058 
00059 struct ast_rtp {
00060    int s;
00061    char resp;
00062    struct ast_frame f;
00063    unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
00064    unsigned int ssrc;
00065    unsigned int lastts;
00066    unsigned int lastrxts;
00067    unsigned int lastividtimestamp;
00068    unsigned int lastovidtimestamp;
00069    int lasttxformat;
00070    int lastrxformat;
00071    int dtmfcount;
00072    unsigned int dtmfduration;
00073    int nat;
00074    struct sockaddr_in us;
00075    struct sockaddr_in them;
00076    struct timeval rxcore;
00077    struct timeval txcore;
00078    struct ast_smoother *smoother;
00079    int *ioid;
00080    unsigned short seqno;
00081    struct sched_context *sched;
00082    struct io_context *io;
00083    void *data;
00084    ast_rtp_callback callback;
00085     struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
00086     // a cache for the result of rtp_lookup_code():
00087     int rtp_lookup_code_cache_isAstFormat;
00088     int rtp_lookup_code_cache_code;
00089     int rtp_lookup_code_cache_result;
00090    struct ast_rtcp *rtcp;
00091 };
00092 
00093 struct ast_rtcp {
00094    int s;      /* Socket */
00095    struct sockaddr_in us;
00096    struct sockaddr_in them;
00097 };
00098 
00099 static struct ast_rtp_protocol *protos = NULL;
00100 
00101 int ast_rtp_fd(struct ast_rtp *rtp)
00102 {
00103    return rtp->s;
00104 }
00105 
00106 int ast_rtcp_fd(struct ast_rtp *rtp)
00107 {
00108    if (rtp->rtcp)
00109       return rtp->rtcp->s;
00110    return -1;
00111 }
00112 
00113 static int g723_len(unsigned char buf)
00114 {
00115    switch(buf & TYPE_MASK) {
00116    case TYPE_DONTSEND:
00117       return 0;
00118       break;
00119    case TYPE_SILENCE:
00120       return 4;
00121       break;
00122    case TYPE_HIGH:
00123       return 24;
00124       break;
00125    case TYPE_LOW:
00126       return 20;
00127       break;
00128    default:
00129       ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
00130    }
00131    return -1;
00132 }
00133 
00134 static int g723_samples(unsigned char *buf, int maxlen)
00135 {
00136    int pos = 0;
00137    int samples = 0;
00138    int res;
00139    while(pos < maxlen) {
00140       res = g723_len(buf[pos]);
00141       if (res <= 0)
00142          break;
00143       samples += 240;
00144       pos += res;
00145    }
00146    return samples;
00147 }
00148 
00149 void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
00150 {
00151    rtp->data = data;
00152 }
00153 
00154 void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
00155 {
00156    rtp->callback = callback;
00157 }
00158 
00159 void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
00160 {
00161    rtp->nat = nat;
00162 }
00163 
00164 static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
00165 {
00166    ast_log(LOG_DEBUG, "Sending dtmf: %d (%c)\n", rtp->resp, rtp->resp);
00167    rtp->f.frametype = AST_FRAME_DTMF;
00168    rtp->f.subclass = rtp->resp;
00169    rtp->f.datalen = 0;
00170    rtp->f.samples = 0;
00171    rtp->f.mallocd = 0;
00172    rtp->f.src = "RTP";
00173    rtp->resp = 0;
00174    rtp->dtmfduration = 0;
00175    return &rtp->f;
00176    
00177 }
00178 
00179 static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
00180 {
00181    unsigned int event;
00182    char resp = 0;
00183    struct ast_frame *f = NULL;
00184    event = ntohl(*((unsigned int *)(data)));
00185    event &= 0x001F;
00186 #if 0
00187    printf("Cisco Digit: %08x (len = %d)\n", event, len);
00188 #endif   
00189    if (event < 10) {
00190       resp = '0' + event;
00191    } else if (event < 11) {
00192       resp = '*';
00193    } else if (event < 12) {
00194       resp = '#';
00195    } else if (event < 16) {
00196       resp = 'A' + (event - 12);
00197    }
00198    if (rtp->resp && (rtp->resp != resp)) {
00199       f = send_dtmf(rtp);
00200    }
00201    rtp->resp = resp;
00202    rtp->dtmfcount = dtmftimeout;
00203    return f;
00204 }
00205 
00206 static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len)
00207 {
00208    unsigned int event;
00209    unsigned int event_end;
00210    unsigned int duration;
00211    char resp = 0;
00212    struct ast_frame *f = NULL;
00213    event = ntohl(*((unsigned int *)(data)));
00214    event >>= 24;
00215    event_end = ntohl(*((unsigned int *)(data)));
00216    event_end <<= 8;
00217    event_end >>= 24;
00218    duration = ntohl(*((unsigned int *)(data)));
00219    duration &= 0xFFFF;
00220 #if 0
00221    printf("Event: %08x (len = %d)\n", event, len);
00222 #endif   
00223    if (event < 10) {
00224       resp = '0' + event;
00225    } else if (event < 11) {
00226       resp = '*';
00227    } else if (event < 12) {
00228       resp = '#';
00229    } else if (event < 16) {
00230       resp = 'A' + (event - 12);
00231    }
00232    if (rtp->resp && (rtp->resp != resp)) {
00233       f = send_dtmf(rtp);
00234    }
00235    else if(event_end & 0x80)
00236    {
00237       if (rtp->resp) {
00238          f = send_dtmf(rtp);
00239          rtp->resp = 0;
00240       }
00241       resp = 0;
00242       duration = 0;
00243    }
00244    else if(rtp->dtmfduration && (duration < rtp->dtmfduration))
00245    {
00246       f = send_dtmf(rtp);
00247    }
00248    if (!(event_end & 0x80))
00249       rtp->resp = resp;
00250    rtp->dtmfcount = dtmftimeout;
00251    rtp->dtmfduration = duration;
00252    return f;
00253 }
00254 
00255 static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *data, int len)
00256 {
00257    struct ast_frame *f = NULL;
00258    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
00259       totally help us out becuase we don't have an engine to keep it going and we are not
00260       guaranteed to have it every 20ms or anything */
00261 #if 0
00262    printf("RFC3389: %d bytes, format is %d\n", len, rtp->lastrxformat);
00263 #endif   
00264    ast_log(LOG_NOTICE, "RFC3389 support incomplete.  Turn off on client if possible\n");
00265    if (!rtp->lastrxformat)
00266       return   NULL;
00267    switch(rtp->lastrxformat) {
00268    case AST_FORMAT_ULAW:
00269       rtp->f.frametype = AST_FRAME_VOICE;
00270       rtp->f.subclass = AST_FORMAT_ULAW;
00271       rtp->f.datalen = 160;
00272       rtp->f.samples = 160;
00273       memset(rtp->f.data, 0x7f, rtp->f.datalen);
00274       f = &rtp->f;
00275       break;
00276    case AST_FORMAT_ALAW:
00277       rtp->f.frametype = AST_FRAME_VOICE;
00278       rtp->f.subclass = AST_FORMAT_ALAW;
00279       rtp->f.datalen = 160;
00280       rtp->f.samples = 160;
00281       memset(rtp->f.data, 0x7e, rtp->f.datalen); /* XXX Is this right? XXX */
00282       f = &rtp->f;
00283       break;
00284    case AST_FORMAT_SLINEAR:
00285       rtp->f.frametype = AST_FRAME_VOICE;
00286       rtp->f.subclass = AST_FORMAT_SLINEAR;
00287       rtp->f.datalen = 320;
00288       rtp->f.samples = 160;
00289       memset(rtp->f.data, 0x00, rtp->f.datalen);
00290       f = &rtp->f;
00291       break;
00292    default:
00293       ast_log(LOG_NOTICE, "Don't know how to handle RFC3389 for receive codec %d\n", rtp->lastrxformat);
00294    }
00295    return f;
00296 }
00297 
00298 static int rtpread(int *id, int fd, short events, void *cbdata)
00299 {
00300    struct ast_rtp *rtp = cbdata;
00301    struct ast_frame *f;
00302    f = ast_rtp_read(rtp);
00303    if (f) {
00304       if (rtp->callback)
00305          rtp->callback(rtp, f, rtp->data);
00306    }
00307    return 1;
00308 }
00309 
00310 struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
00311 {
00312    static struct ast_frame null_frame = { AST_FRAME_NULL, };
00313    int len;
00314    int hdrlen = 8;
00315    int res;
00316    struct sockaddr_in sin;
00317    unsigned int rtcpdata[1024];
00318    
00319    if (!rtp->rtcp)
00320       return &null_frame;
00321 
00322    len = sizeof(sin);
00323    
00324    res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
00325                0, (struct sockaddr *)&sin, &len);
00326    
00327    if (res < 0) {
00328       ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00329       if (errno == EBADF)
00330          CRASH;
00331       return &null_frame;
00332    }
00333 
00334    if (res < hdrlen) {
00335       ast_log(LOG_WARNING, "RTP Read too short\n");
00336       return &null_frame;
00337    }
00338 
00339    if (rtp->nat) {
00340       /* Send to whoever sent to us */
00341       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00342           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00343          memcpy(&rtp->them, &sin, sizeof(rtp->them));
00344          ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00345       }
00346    }
00347    if (option_debug)
00348       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00349    return &null_frame;
00350 }
00351 
00352 struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
00353 {
00354    int res;
00355    struct sockaddr_in sin;
00356    int len;
00357    unsigned int seqno;
00358    int payloadtype;
00359    int hdrlen = 12;
00360    int mark;
00361    unsigned int timestamp;
00362    unsigned int *rtpheader;
00363    static struct ast_frame *f, null_frame = { AST_FRAME_NULL, };
00364    struct rtpPayloadType rtpPT;
00365    
00366    len = sizeof(sin);
00367    
00368    /* Cache where the header will go */
00369    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
00370                0, (struct sockaddr *)&sin, &len);
00371 
00372 
00373    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
00374    if (res < 0) {
00375       ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00376       if (errno == EBADF)
00377          CRASH;
00378       return &null_frame;
00379    }
00380    if (res < hdrlen) {
00381       ast_log(LOG_WARNING, "RTP Read too short\n");
00382       return &null_frame;
00383    }
00384    if (rtp->nat) {
00385       /* Send to whoever sent to us */
00386       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00387           (rtp->them.sin_port != sin.sin_port)) {
00388          memcpy(&rtp->them, &sin, sizeof(rtp->them));
00389          ast_log(LOG_DEBUG, "RTP NAT: Using address %s:%d\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
00390       }
00391    }
00392    /* Get fields */
00393    seqno = ntohl(rtpheader[0]);
00394    payloadtype = (seqno & 0x7f0000) >> 16;
00395    mark = seqno & (1 << 23);
00396    seqno &= 0xffff;
00397    timestamp = ntohl(rtpheader[1]);
00398 
00399 #if 0
00400    printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
00401 #endif   
00402    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
00403    if (!rtpPT.isAstFormat) {
00404      // This is special in-band data that's not one of our codecs
00405      if (rtpPT.code == AST_RTP_DTMF) {
00406        /* It's special -- rfc2833 process it */
00407        f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00408        if (f) return f; else return &null_frame;
00409      } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
00410        /* It's really special -- process it the Cisco way */
00411        f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00412        if (f) return f; else return &null_frame;
00413      } else if (rtpPT.code == AST_RTP_CN) {
00414        /* Comfort Noise */
00415        f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00416        if (f) return f; else return &null_frame;
00417      } else {
00418        ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
00419        return &null_frame;
00420      }
00421    }
00422    rtp->f.subclass = rtpPT.code;
00423    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
00424       rtp->f.frametype = AST_FRAME_VOICE;
00425    else
00426       rtp->f.frametype = AST_FRAME_VIDEO;
00427    rtp->lastrxformat = rtp->f.subclass;
00428 
00429    if (!rtp->lastrxts)
00430       rtp->lastrxts = timestamp;
00431 
00432    if (rtp->dtmfcount) {
00433 #if 0
00434       printf("dtmfcount was %d\n", rtp->dtmfcount);
00435 #endif      
00436       rtp->dtmfcount -= (timestamp - rtp->lastrxts);
00437       if (rtp->dtmfcount < 0)
00438          rtp->dtmfcount = 0;
00439 #if 0
00440       if (dtmftimeout != rtp->dtmfcount)
00441          printf("dtmfcount is %d\n", rtp->dtmfcount);
00442 #endif
00443    }
00444    rtp->lastrxts = timestamp;
00445 
00446    /* Send any pending DTMF */
00447    if (rtp->resp && !rtp->dtmfcount) {
00448       ast_log(LOG_DEBUG, "Sending pending DTMF\n");
00449       return send_dtmf(rtp);
00450    }
00451    rtp->f.mallocd = 0;
00452    rtp->f.datalen = res - hdrlen;
00453    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
00454    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
00455    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
00456       switch(rtp->f.subclass) {
00457       case AST_FORMAT_ULAW:
00458       case AST_FORMAT_ALAW:
00459          rtp->f.samples = rtp->f.datalen;
00460          break;
00461       case AST_FORMAT_SLINEAR:
00462          rtp->f.samples = rtp->f.datalen / 2;
00463          break;
00464       case AST_FORMAT_GSM:
00465          rtp->f.samples = 160 * (rtp->f.datalen / 33);
00466          break;
00467       case AST_FORMAT_ILBC:
00468          rtp->f.samples = 240 * (rtp->f.datalen / 50);
00469          break;
00470       case AST_FORMAT_ADPCM:
00471          rtp->f.samples = rtp->f.datalen * 2;
00472          break;
00473       case AST_FORMAT_G729A:
00474          rtp->f.samples = rtp->f.datalen * 8;
00475          break;
00476       case AST_FORMAT_G723_1:
00477          rtp->f.samples = g723_samples(rtp->f.data, rtp->f.datalen);
00478          break;
00479       case AST_FORMAT_SPEEX:
00480               rtp->f.samples = 160;
00481          // assumes that the RTP packet contained one Speex frame
00482          break;
00483       default:
00484          ast_log(LOG_NOTICE, "Unable to calculate samples for format %s\n", ast_getformatname(rtp->f.subclass));
00485          break;
00486       }
00487    } else {
00488       /* Video -- samples is # of samples vs. 90000 */
00489       if (!rtp->lastividtimestamp)
00490          rtp->lastividtimestamp = timestamp;
00491       rtp->f.samples = timestamp - rtp->lastividtimestamp;
00492       rtp->lastividtimestamp = timestamp;
00493       if (mark)
00494          rtp->f.subclass |= 0x1;
00495       
00496    }
00497    rtp->f.src = "RTP";
00498    return &rtp->f;
00499 }
00500 
00501 // The following array defines the MIME type (and subtype) for each
00502 // of our codecs, or RTP-specific data type.
00503 static struct {
00504   struct rtpPayloadType payloadType;
00505   char* type;
00506   char* subtype;
00507 } mimeTypes[] = {
00508   {{1, AST_FORMAT_G723_1}, "audio", "G723"},
00509   {{1, AST_FORMAT_GSM}, "audio", "GSM"},
00510   {{1, AST_FORMAT_ULAW}, "audio", "PCMU"},
00511   {{1, AST_FORMAT_ALAW}, "audio", "PCMA"},
00512   {{1, AST_FORMAT_G726}, "audio", "G726-32"},
00513   {{1, AST_FORMAT_ADPCM}, "audio", "DVI4"},
00514   {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
00515   {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
00516   {{1, AST_FORMAT_G729A}, "audio", "G729"},
00517   {{1, AST_FORMAT_SPEEX}, "audio", "SPEEX"},
00518   {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
00519   {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
00520   {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
00521   {{0, AST_RTP_CN}, "audio", "CN"},
00522   {{1, AST_FORMAT_JPEG}, "video", "JPEG"},
00523   {{1, AST_FORMAT_PNG}, "video", "PNG"},
00524   {{1, AST_FORMAT_H261}, "video", "H261"},
00525   {{1, AST_FORMAT_H263}, "video", "H263"},
00526 };
00527 
00528 /* Static (i.e., well-known) RTP payload types for our "AST_FORMAT..."s:
00529    also, our own choices for dynamic payload types.  This is our master
00530    table for transmission */
00531 static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
00532   [0] = {1, AST_FORMAT_ULAW},
00533   [2] = {1, AST_FORMAT_G726}, // Technically this is G.721, but if Cisco can do it, so can we...
00534   [3] = {1, AST_FORMAT_GSM},
00535   [4] = {1, AST_FORMAT_G723_1},
00536   [5] = {1, AST_FORMAT_ADPCM}, // 8 kHz
00537   [6] = {1, AST_FORMAT_ADPCM}, // 16 kHz
00538   [7] = {1, AST_FORMAT_LPC10},
00539   [8] = {1, AST_FORMAT_ALAW},
00540   [10] = {1, AST_FORMAT_SLINEAR}, // 2 channels
00541   [11] = {1, AST_FORMAT_SLINEAR}, // 1 channel
00542   [13] = {0, AST_RTP_CN},
00543   [16] = {1, AST_FORMAT_ADPCM}, // 11.025 kHz
00544   [17] = {1, AST_FORMAT_ADPCM}, // 22.050 kHz
00545   [18] = {1, AST_FORMAT_G729A},
00546   [26] = {1, AST_FORMAT_JPEG},
00547   [31] = {1, AST_FORMAT_H261},
00548   [34] = {1, AST_FORMAT_H263},
00549   [97] = {1, AST_FORMAT_ILBC},
00550   [101] = {0, AST_RTP_DTMF},
00551   [110] = {1, AST_FORMAT_SPEEX},
00552   [121] = {0, AST_RTP_CISCO_DTMF}, // Must be type 121
00553 };
00554 
00555 void ast_rtp_pt_clear(struct ast_rtp* rtp) 
00556 {
00557   int i;
00558 
00559   for (i = 0; i < MAX_RTP_PT; ++i) {
00560     rtp->current_RTP_PT[i].isAstFormat = 0;
00561     rtp->current_RTP_PT[i].code = 0;
00562   }
00563 
00564   rtp->rtp_lookup_code_cache_isAstFormat = 0;
00565   rtp->rtp_lookup_code_cache_code = 0;
00566   rtp->rtp_lookup_code_cache_result = 0;
00567 }
00568 
00569 void ast_rtp_pt_default(struct ast_rtp* rtp) 
00570 {
00571   int i;
00572   /* Initialize to default payload types */
00573   for (i = 0; i < MAX_RTP_PT; ++i) {
00574     rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00575     rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00576   }
00577 
00578   rtp->rtp_lookup_code_cache_isAstFormat = 0;
00579   rtp->rtp_lookup_code_cache_code = 0;
00580   rtp->rtp_lookup_code_cache_result = 0;
00581 }
00582 
00583 // Make a note of a RTP payload type that was seen in a SDP "m=" line.
00584 // By default, use the well-known value for this type (although it may
00585 // still be set to a different value by a subsequent "a=rtpmap:" line):
00586 void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt) {
00587   if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type
00588 
00589   if (static_RTP_PT[pt].code != 0) {
00590     rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00591   }
00592 } 
00593 
00594 // Make a note of a RTP payload type (with MIME type) that was seen in
00595 // a SDP "a=rtpmap:" line.
00596 void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
00597           char* mimeType, char* mimeSubtype) {
00598   int i;
00599 
00600   if (pt < 0 || pt > MAX_RTP_PT) return; // bogus payload type
00601 
00602   for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00603     if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00604    strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00605       rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00606       return;
00607     }
00608   }
00609 } 
00610 
00611 // Return the union of all of the codecs that were set by rtp_set...() calls
00612 // They're returned as two distinct sets: AST_FORMATs, and AST_RTPs
00613 void ast_rtp_get_current_formats(struct ast_rtp* rtp,
00614               int* astFormats, int* nonAstFormats) {
00615   int pt;
00616 
00617   *astFormats = *nonAstFormats = 0;
00618   for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00619     if (rtp->current_RTP_PT[pt].isAstFormat) {
00620       *astFormats |= rtp->current_RTP_PT[pt].code;
00621     } else {
00622       *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00623     }
00624   }
00625 }
00626 
00627 struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt) {
00628   if (pt < 0 || pt > MAX_RTP_PT) {
00629     struct rtpPayloadType result;
00630     result.isAstFormat = result.code = 0;
00631     return result; // bogus payload type
00632   }
00633   /* Gotta use our static one, since that's what we sent against */
00634   return static_RTP_PT[pt];
00635 }
00636 
00637 int ast_rtp_lookup_code(struct ast_rtp* rtp, int isAstFormat, int code) {
00638   int pt;
00639 
00640   /* Looks up an RTP code out of our *static* outbound list */
00641 
00642   if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00643       code == rtp->rtp_lookup_code_cache_code) {
00644     // Use our cached mapping, to avoid the overhead of the loop below
00645     return rtp->rtp_lookup_code_cache_result;
00646   }
00647 
00648   for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00649     if (static_RTP_PT[pt].code == code &&
00650       static_RTP_PT[pt].isAstFormat == isAstFormat) {
00651       rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00652       rtp->rtp_lookup_code_cache_code = code;
00653       rtp->rtp_lookup_code_cache_result = pt;
00654       return pt;
00655     }
00656   }
00657   return -1;
00658 }
00659 
00660 char* ast_rtp_lookup_mime_subtype(int isAstFormat, int code) {
00661   int i;
00662 
00663   for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00664     if (mimeTypes[i].payloadType.code == code &&
00665    mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00666       return mimeTypes[i].subtype;
00667     }
00668   }
00669   return "";
00670 }
00671 
00672 static struct ast_rtcp *ast_rtcp_new(void)
00673 {
00674    struct ast_rtcp *rtcp;
00675    long flags;
00676    rtcp = malloc(sizeof(struct ast_rtcp));
00677    if (!rtcp)
00678       return NULL;
00679    memset(rtcp, 0, sizeof(struct ast_rtcp));
00680    rtcp->s = socket(AF_INET, SOCK_DGRAM, 0);
00681    rtcp->us.sin_family = AF_INET;
00682    if (rtcp->s < 0) {
00683       free(rtcp);
00684       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00685       return NULL;
00686    }
00687    flags = fcntl(rtcp->s, F_GETFL);
00688    fcntl(rtcp->s, F_SETFL, flags | O_NONBLOCK);
00689    return rtcp;
00690 }
00691 
00692 struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
00693 {
00694    struct ast_rtp *rtp;
00695    int x;
00696    int flags;
00697    int startplace;
00698    rtp = malloc(sizeof(struct ast_rtp));
00699    if (!rtp)
00700       return NULL;
00701    memset(rtp, 0, sizeof(struct ast_rtp));
00702    rtp->them.sin_family = AF_INET;
00703    rtp->us.sin_family = AF_INET;
00704    rtp->s = socket(AF_INET, SOCK_DGRAM, 0);
00705    rtp->ssrc = rand();
00706    rtp->seqno = rand() & 0xffff;
00707    if (rtp->s < 0) {
00708       free(rtp);
00709       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00710       return NULL;
00711    }
00712    if (sched && rtcpenable) {
00713       rtp->sched = sched;
00714       rtp->rtcp = ast_rtcp_new();
00715    }
00716    flags = fcntl(rtp->s, F_GETFL);
00717    fcntl(rtp->s, F_SETFL, flags | O_NONBLOCK);
00718    /* Find us a place */
00719    x = (rand() % (rtpend-rtpstart)) + rtpstart;
00720    x = x & ~1;
00721    startplace = x;
00722    for (;;) {
00723       /* Must be an even port number by RTP spec */
00724       rtp->us.sin_port = htons(x);
00725       if (rtp->rtcp)
00726          rtp->rtcp->us.sin_port = htons(x + 1);
00727       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us)) &&
00728          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
00729          break;
00730       if (errno != EADDRINUSE) {
00731          ast_log(LOG_WARNING, "Unexpected bind error: %s\n", strerror(errno));
00732          close(rtp->s);
00733          if (rtp->rtcp) {
00734             close(rtp->rtcp->s);
00735             free(rtp->rtcp);
00736          }
00737          free(rtp);
00738          return NULL;
00739       }
00740       x += 2;
00741       if (x > rtpend)
00742          x = (rtpstart + 1) & ~1;
00743       if (x == startplace) {
00744          ast_log(LOG_WARNING, "No RTP ports remaining\n");
00745          close(rtp->s);
00746          if (rtp->rtcp) {
00747             close(rtp->rtcp->s);
00748             free(rtp->rtcp);
00749          }
00750          free(rtp);
00751          return NULL;
00752       }
00753    }
00754    if (io && sched && callbackmode) {
00755       /* Operate this one in a callback mode */
00756       rtp->sched = sched;
00757       rtp->io = io;
00758       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
00759    }
00760    ast_rtp_pt_default(rtp);
00761    return rtp;
00762 }
00763 
00764 int ast_rtp_settos(struct ast_rtp *rtp, int tos)
00765 {
00766    int res;
00767    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
00768       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
00769    return res;
00770 }
00771 
00772 void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
00773 {
00774    rtp->them.sin_port = them->sin_port;
00775    rtp->them.sin_addr = them->sin_addr;
00776    if (rtp->rtcp) {
00777       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
00778       rtp->rtcp->them.sin_addr = them->sin_addr;
00779    }
00780 }
00781 
00782 void ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
00783 {
00784    them->sin_family = AF_INET;
00785    them->sin_port = rtp->them.sin_port;
00786    them->sin_addr = rtp->them.sin_addr;
00787 }
00788 
00789 void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
00790 {
00791    memcpy(us, &rtp->us, sizeof(rtp->us));
00792 }
00793 
00794 void ast_rtp_stop(struct ast_rtp *rtp)
00795 {
00796    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00797    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00798    if (rtp->rtcp) {
00799       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
00800       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
00801    }
00802 }
00803 
00804 void ast_rtp_destroy(struct ast_rtp *rtp)
00805 {
00806    if (rtp->smoother)
00807       ast_smoother_free(rtp->smoother);
00808    if (rtp->ioid)
00809       ast_io_remove(rtp->io, rtp->ioid);
00810    if (rtp->s > -1)
00811       close(rtp->s);
00812    if (rtp->rtcp) {
00813       close(rtp->rtcp->s);
00814       free(rtp->rtcp);
00815    }
00816    free(rtp);
00817 }
00818 
00819 static unsigned int calc_txstamp(struct ast_rtp *rtp)
00820 {
00821    struct timeval now;
00822    unsigned int ms;
00823    if (!rtp->txcore.tv_sec && !rtp->txcore.tv_usec) {
00824       gettimeofday(&rtp->txcore, NULL);
00825    }
00826    gettimeofday(&now, NULL);
00827    ms = (now.tv_sec - rtp->txcore.tv_sec) * 1000;
00828    ms += (now.tv_usec - rtp->txcore.tv_usec) / 1000;
00829    /* Use what we just got for next time */
00830    rtp->txcore.tv_sec = now.tv_sec;
00831    rtp->txcore.tv_usec = now.tv_usec;
00832    return ms;
00833 }
00834 
00835 int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
00836 {
00837    unsigned int *rtpheader;
00838    int hdrlen = 12;
00839    int res;
00840    int ms;
00841    int pred;
00842    int x;
00843    char data[256];
00844 
00845    if ((digit <= '9') && (digit >= '0'))
00846       digit -= '0';
00847    else if (digit == '*')
00848       digit = 10;
00849    else if (digit == '#')
00850       digit = 11;
00851    else if ((digit >= 'A') && (digit <= 'D')) 
00852       digit = digit - 'A' + 12;
00853    else if ((digit >= 'a') && (digit <= 'd')) 
00854       digit = digit - 'a' + 12;
00855    else {
00856       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00857       return -1;
00858    }
00859    
00860 
00861    /* If we have no peer, return immediately */ 
00862    if (!rtp->them.sin_addr.s_addr)
00863       return 0;
00864 
00865    ms = calc_txstamp(rtp);
00866    /* Default prediction */
00867    pred = rtp->lastts + ms * 8;
00868    
00869    /* Get a pointer to the header */
00870    rtpheader = (unsigned int *)data;
00871    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (101 << 16) | (rtp->seqno++));
00872    rtpheader[1] = htonl(rtp->lastts);
00873    rtpheader[2] = htonl(rtp->ssrc); 
00874    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
00875    for (x=0;x<4;x++) {
00876       if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
00877          res = sendto(rtp->s, (void *)rtpheader, hdrlen + 4, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
00878          if (res <0) 
00879             ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
00880    #if 0
00881       printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
00882    #endif      
00883       }
00884       if (x ==0) {
00885          /* Clear marker bit and increment seqno */
00886          rtpheader[0] = htonl((2 << 30)  | (101 << 16) | (rtp->seqno++));
00887          /* Make duration 240 */
00888          rtpheader[3] |= htonl((240));
00889          /* Set the End bit for the last 3 */
00890          rtpheader[3] |= htonl((1 << 23));
00891       }
00892    }
00893    return 0;
00894 }
00895 
00896 static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec)
00897 {
00898    unsigned int *rtpheader;
00899    int hdrlen = 12;
00900    int res;
00901    int ms;
00902    int pred;
00903    int mark = 0;
00904 
00905    ms = calc_txstamp(rtp);
00906    /* Default prediction */
00907    if (f->subclass < AST_FORMAT_MAX_AUDIO) {
00908       pred = rtp->lastts + ms * 8;
00909       
00910       switch(f->subclass) {
00911       case AST_FORMAT_ULAW:
00912       case AST_FORMAT_ALAW:
00913          /* If we're within +/- 20ms from when where we
00914             predict we should be, use that */
00915          pred = rtp->lastts + f->datalen;
00916          break;
00917       case AST_FORMAT_G729A:
00918          pred = rtp->lastts + f->datalen * 8;
00919          break;
00920       case AST_FORMAT_GSM:
00921          pred = rtp->lastts + (f->datalen * 160 / 33);
00922          break;
00923       case AST_FORMAT_ILBC:
00924          pred = rtp->lastts + (f->datalen * 240 / 50);
00925          break;
00926       case AST_FORMAT_G723_1:
00927          pred = rtp->lastts + g723_samples(f->data, f->datalen);
00928          break;
00929       case AST_FORMAT_SPEEX:
00930               pred = rtp->lastts + 160;
00931          // assumes that the RTP packet contains one Speex frame
00932          break;
00933       default:
00934          ast_log(LOG_WARNING, "Not sure about timestamp format for codec format %s\n", ast_getformatname(f->subclass));
00935       }
00936 
00937       /* Re-calculate last TS */
00938       rtp->lastts = rtp->lastts + ms * 8;
00939       /* If it's close to our prediction, go for it */
00940       if (abs(rtp->lastts - pred) < 640)
00941          rtp->lastts = pred;
00942       else
00943          ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
00944    } else {
00945       mark = f->subclass & 0x1;
00946       pred = rtp->lastovidtimestamp + f->samples;
00947       /* Re-calculate last TS */
00948       rtp->lastts = rtp->lastts + ms * 90;
00949       /* If it's close to our prediction, go for it */
00950       if (abs(rtp->lastts - pred) < 7200) {
00951          rtp->lastts = pred;
00952          rtp->lastovidtimestamp += f->samples;
00953       } else {
00954          ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
00955          rtp->lastovidtimestamp = rtp->lastts;
00956       }
00957    }
00958    /* Get a pointer to the header */
00959    rtpheader = (unsigned int *)(f->data - hdrlen);
00960    rtpheader[0] = htonl((2 << 30) | (codec << 16) | (rtp->seqno++) | (mark << 23));
00961    rtpheader[1] = htonl(rtp->lastts);
00962    rtpheader[2] = htonl(rtp->ssrc); 
00963    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
00964       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
00965       if (res <0) 
00966          ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
00967 #if 0
00968       printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
00969 #endif      
00970    }
00971    return 0;
00972 }
00973 
00974 int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
00975 {
00976    struct ast_frame *f;
00977    int codec;
00978    int hdrlen = 12;
00979    int subclass;
00980    
00981 
00982    /* If we have no peer, return immediately */ 
00983    if (!rtp->them.sin_addr.s_addr)
00984       return 0;
00985 
00986    /* If there is no data length, return immediately */
00987    if (!_f->datalen) 
00988       return 0;
00989    
00990    /* Make sure we have enough space for RTP header */
00991    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
00992       ast_log(LOG_WARNING, "RTP can only send voice\n");
00993       return -1;
00994    }
00995 
00996    subclass = _f->subclass;
00997    if (_f->frametype == AST_FRAME_VIDEO)
00998       subclass &= ~0x1;
00999 
01000    codec = ast_rtp_lookup_code(rtp, 1, subclass);
01001    if (codec < 0) {
01002       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
01003       return -1;
01004    }
01005 
01006    if (rtp->lasttxformat != subclass) {
01007       /* New format, reset the smoother */
01008       ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01009       rtp->lasttxformat = subclass;
01010       if (rtp->smoother)
01011          ast_smoother_free(rtp->smoother);
01012       rtp->smoother = NULL;
01013    }
01014 
01015 
01016    switch(subclass) {
01017    case AST_FORMAT_ULAW:
01018    case AST_FORMAT_ALAW:
01019       if (!rtp->smoother) {
01020          rtp->smoother = ast_smoother_new(160);
01021       }
01022       if (!rtp->smoother) {
01023          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01024          return -1;
01025       }
01026       ast_smoother_feed(rtp->smoother, _f);
01027       
01028       while((f = ast_smoother_read(rtp->smoother)))
01029          ast_rtp_raw_write(rtp, f, codec);
01030       break;
01031    case AST_FORMAT_G729A:
01032       if (!rtp->smoother) {
01033          rtp->smoother = ast_smoother_new(20);
01034       }
01035       if (!rtp->smoother) {
01036          ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
01037          return -1;
01038       }
01039       ast_smoother_feed(rtp->smoother, _f);
01040       
01041       while((f = ast_smoother_read(rtp->smoother)))
01042          ast_rtp_raw_write(rtp, f, codec);
01043       break;
01044    case AST_FORMAT_GSM:
01045       if (!rtp->smoother) {
01046          rtp->smoother = ast_smoother_new(33);
01047       }
01048       if (!rtp->smoother) {
01049          ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
01050          return -1;
01051       }
01052       ast_smoother_feed(rtp->smoother, _f);
01053       while((f = ast_smoother_read(rtp->smoother)))
01054          ast_rtp_raw_write(rtp, f, codec);
01055       break;
01056    case AST_FORMAT_ILBC:
01057       if (!rtp->smoother) {
01058          rtp->smoother = ast_smoother_new(50);
01059       }
01060       if (!rtp->smoother) {
01061          ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
01062          return -1;
01063       }
01064       ast_smoother_feed(rtp->smoother, _f);
01065       while((f = ast_smoother_read(rtp->smoother)))
01066          ast_rtp_raw_write(rtp, f, codec);
01067       break;
01068    default: 
01069       ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
01070       // fall through to...
01071    case AST_FORMAT_H261:
01072    case AST_FORMAT_H263:
01073    case AST_FORMAT_G723_1:
01074    case AST_FORMAT_SPEEX:
01075            // Don't buffer outgoing frames; send them one-per-packet:
01076       if (_f->offset < hdrlen) {
01077          f = ast_frdup(_f);
01078       } else {
01079          f = _f;
01080       }
01081       ast_rtp_raw_write(rtp, f, codec);
01082    }
01083       
01084    return 0;
01085 }
01086 
01087 void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto)
01088 {
01089    struct ast_rtp_protocol *cur, *prev;
01090    cur = protos;
01091    prev = NULL;
01092    while(cur) {
01093       if (cur == proto) {
01094          if (prev)
01095             prev->next = proto->next;
01096          else
01097             protos = proto->next;
01098          return;
01099       }
01100       prev = cur;
01101       cur = cur->next;
01102    }
01103 }
01104 
01105 int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
01106 {
01107    struct ast_rtp_protocol *cur;
01108    cur = protos;
01109    while(cur) {
01110       if (cur->type == proto->type) {
01111          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01112          return -1;
01113       }
01114       cur = cur->next;
01115    }
01116    proto->next = protos;
01117    protos = proto;
01118    return 0;
01119 }
01120 
01121 static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
01122 {
01123    struct ast_rtp_protocol *cur;
01124    cur = protos;
01125    while(cur) {
01126       if (cur->type == chan->type) {
01127          return cur;
01128       }
01129       cur = cur->next;
01130    }
01131    return NULL;
01132 }
01133 
01134 int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
01135 {
01136    struct ast_frame *f;
01137    struct ast_channel *who, *cs[3];
01138    struct ast_rtp *p0, *p1;
01139    struct ast_rtp *vp0, *vp1;
01140    struct ast_rtp_protocol *pr0, *pr1;
01141    struct sockaddr_in ac0, ac1;
01142    struct sockaddr_in vac0, vac1;
01143    struct sockaddr_in t0, t1;
01144    struct sockaddr_in vt0, vt1;
01145    
01146    void *pvt0, *pvt1;
01147    int to;
01148    memset(&vt0, 0, sizeof(vt0));
01149    memset(&vt1, 0, sizeof(vt1));
01150    memset(&vac0, 0, sizeof(vac0));
01151    memset(&vac1, 0, sizeof(vac1));
01152 
01153    /* XXX Wait a half a second for things to settle up 
01154          this really should be fixed XXX */
01155    ast_autoservice_start(c0);
01156    ast_autoservice_start(c1);
01157    usleep(500000);
01158    ast_autoservice_stop(c0);
01159    ast_autoservice_stop(c1);
01160 
01161    /* if need DTMF, cant native bridge */
01162    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
01163       return -2;
01164    ast_mutex_lock(&c0->lock);
01165    ast_mutex_lock(&c1->lock);
01166    pr0 = get_proto(c0);
01167    pr1 = get_proto(c1);
01168    if (!pr0) {
01169       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01170       ast_mutex_unlock(&c0->lock);
01171       ast_mutex_unlock(&c1->lock);
01172       return -1;
01173    }
01174    if (!pr1) {
01175       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01176       ast_mutex_unlock(&c0->lock);
01177       ast_mutex_unlock(&c1->lock);
01178       return -1;
01179    }
01180    pvt0 = c0->pvt->pvt;
01181    pvt1 = c1->pvt->pvt;
01182    p0 = pr0->get_rtp_info(c0);
01183    if (pr0->get_vrtp_info)
01184       vp0 = pr0->get_vrtp_info(c0);
01185    else
01186       vp0 = NULL;
01187    p1 = pr1->get_rtp_info(c1);
01188    if (pr1->get_vrtp_info)
01189       vp1 = pr1->get_vrtp_info(c1);
01190    else
01191       vp1 = NULL;
01192    if (!p0 || !p1) {
01193       /* Somebody doesn't want to play... */
01194       ast_mutex_unlock(&c0->lock);
01195       ast_mutex_unlock(&c1->lock);
01196       return -2;
01197    }
01198    if (pr0->get_codec && pr1->get_codec) {
01199       int codec0,codec1;
01200       codec0 = pr0->get_codec(c0);
01201       codec1 = pr1->get_codec(c1);
01202       /* Hey, we can't do reinvite if both parties speak diffrent codecs */
01203       if (codec0 != codec1) {
01204          ast_log(LOG_WARNING, "codec0 = %d is not codec1 = %d, cannot native bridge.\n",codec0,codec1);
01205          ast_mutex_unlock(&c0->lock);
01206          ast_mutex_unlock(&c1->lock);
01207          return -2;
01208       }
01209    }
01210    if (pr0->set_rtp_peer(c0, p1, vp1)) 
01211       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01212    else {
01213       /* Store RTP peer */
01214       ast_rtp_get_peer(p1, &ac1);
01215       if (vp1)
01216          ast_rtp_get_peer(p1, &vac1);
01217    }
01218    if (pr1->set_rtp_peer(c1, p0, vp0))
01219       ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01220    else {
01221       /* Store RTP peer */
01222       ast_rtp_get_peer(p0, &ac0);
01223       if (vp0)
01224          ast_rtp_get_peer(p0, &vac0);
01225    }
01226    ast_mutex_unlock(&c0->lock);
01227    ast_mutex_unlock(&c1->lock);
01228    cs[0] = c0;
01229    cs[1] = c1;
01230    cs[2] = NULL;
01231    for (;;) {
01232       if ((c0->pvt->pvt != pvt0)  ||
01233          (c1->pvt->pvt != pvt1) ||
01234          (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01235             ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
01236             if (c0->pvt->pvt == pvt0) {
01237                if (pr0->set_rtp_peer(c0, NULL, NULL)) 
01238                   ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01239             }
01240             if (c1->pvt->pvt == pvt1) {
01241                if (pr1->set_rtp_peer(c1, NULL, NULL)) 
01242                   ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01243             }
01244             /* Tell it to try again later */
01245             return -3;
01246       }
01247       to = -1;
01248       ast_rtp_get_peer(p1, &t1);
01249       ast_rtp_get_peer(p0, &t0);
01250       if (vp1)
01251          ast_rtp_get_peer(vp1, &vt1);
01252       if (vp0)
01253          ast_rtp_get_peer(vp0, &vt0);
01254       if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1))) {
01255          ast_log(LOG_DEBUG, "Oooh, '%s' changed end address\n", c1->name);
01256          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL)) 
01257             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
01258          memcpy(&ac1, &t1, sizeof(ac1));
01259          memcpy(&vac1, &vt1, sizeof(vac1));
01260       }
01261       if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
01262          ast_log(LOG_DEBUG, "Oooh, '%s' changed end address\n", c0->name);
01263          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL))
01264             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
01265          memcpy(&ac0, &t0, sizeof(ac0));
01266          memcpy(&vac0, &vt0, sizeof(vac0));
01267       }
01268       who = ast_waitfor_n(cs, 2, &to);
01269       if (!who) {
01270          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
01271          /* check for hagnup / whentohangup */
01272          if (ast_check_hangup(c0) || ast_check_hangup(c1))
01273             break;
01274          continue;
01275       }
01276       f = ast_read(who);
01277       if (!f || ((f->frametype == AST_FRAME_DTMF) &&
01278                (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 
01279                 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
01280          *fo = f;
01281          *rc = who;
01282          ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
01283          if ((c0->pvt->pvt == pvt0) && (!c0->_softhangup)) {
01284             if (pr0->set_rtp_peer(c0, NULL, NULL)) 
01285                ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);
01286          }
01287          if ((c1->pvt->pvt == pvt1) && (!c1->_softhangup)) {
01288             if (pr1->set_rtp_peer(c1, NULL, NULL)) 
01289                ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);
01290          }
01291          /* That's all we needed */
01292          return 0;
01293       } else {
01294          if ((f->frametype == AST_FRAME_DTMF) || 
01295             (f->frametype == AST_FRAME_VOICE) || 
01296             (f->frametype == AST_FRAME_VIDEO)) {
01297             /* Forward voice or DTMF frames if they happen upon us */
01298             if (who == c0) {
01299                ast_write(c1, f);
01300             } else if (who == c1) {
01301                ast_write(c0, f);
01302             }
01303          }
01304          ast_frfree(f);
01305       }
01306       /* Swap priority not that it's a big deal at this point */
01307       cs[2] = cs[0];
01308       cs[0] = cs[1];
01309       cs[1] = cs[2];
01310       
01311    }
01312    return -1;
01313 }
01314 
01315 void ast_rtp_reload(void)
01316 {
01317    struct ast_config *cfg;
01318    char *s;
01319    rtpstart = 5000;
01320    rtpend = 31000;
01321    cfg = ast_load("rtp.conf");
01322    if (cfg) {
01323       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01324          rtpstart = atoi(s);
01325          if (rtpstart < 1024)
01326             rtpstart = 1024;
01327          if (rtpstart > 65535)
01328             rtpstart = 65535;
01329       }
01330       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01331          rtpend = atoi(s);
01332          if (rtpend < 1024)
01333             rtpend = 1024;
01334          if (rtpend > 65535)
01335             rtpend = 65535;
01336       }
01337       ast_destroy(cfg);
01338    }
01339    if (rtpstart >= rtpend) {
01340       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end\n");
01341       rtpstart = 5000;
01342       rtpend = 31000;
01343    }
01344    if (option_verbose > 1)
01345       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01346 }
01347 
01348 void ast_rtp_init(void)
01349 {
01350    ast_rtp_reload();
01351 }

Generated on Fri Feb 27 12:19:44 2004 for Asterisk by doxygen 1.3.5