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

Generated on Sun Apr 18 23:33:55 2004 for Asterisk by doxygen 1.3.6-20040222