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