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

Generated on Fri Oct 31 07:05:08 2003 for Asterisk by doxygen 1.3.4