00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/time.h>
00030 #include <signal.h>
00031 #include <errno.h>
00032 #include <unistd.h>
00033 #include <netinet/in.h>
00034 #include <sys/time.h>
00035 #include <sys/socket.h>
00036 #include <arpa/inet.h>
00037 #include <fcntl.h>
00038
00039 #include "asterisk.h"
00040
00041 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 13095 $")
00042
00043 #include "asterisk/rtp.h"
00044 #include "asterisk/frame.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/options.h"
00047 #include "asterisk/channel.h"
00048 #include "asterisk/acl.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/config.h"
00051 #include "asterisk/lock.h"
00052 #include "asterisk/utils.h"
00053 #include "asterisk/cli.h"
00054 #include "asterisk/unaligned.h"
00055 #include "asterisk/utils.h"
00056
00057 #define MAX_TIMESTAMP_SKEW 640
00058
00059 #define RTP_MTU 1200
00060
00061 #define DEFAULT_DTMF_TIMEOUT 3000
00062
00063 static int dtmftimeout = DEFAULT_DTMF_TIMEOUT;
00064
00065 static int rtpstart = 0;
00066 static int rtpend = 0;
00067 static int rtpdebug = 0;
00068 static struct sockaddr_in rtpdebugaddr;
00069 #ifdef SO_NO_CHECK
00070 static int nochecksums = 0;
00071 #endif
00072
00073
00074 struct rtpPayloadType {
00075 int isAstFormat;
00076 int code;
00077 };
00078
00079 #define MAX_RTP_PT 256
00080
00081 #define FLAG_3389_WARNING (1 << 0)
00082 #define FLAG_NAT_ACTIVE (3 << 1)
00083 #define FLAG_NAT_INACTIVE (0 << 1)
00084 #define FLAG_NAT_INACTIVE_NOWARN (1 << 1)
00085
00086 struct ast_rtp {
00087 int s;
00088 char resp;
00089 struct ast_frame f;
00090 unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
00091
00092 unsigned int ssrc;
00093 unsigned int lastts;
00094 unsigned int lastdigitts;
00095 unsigned int lastrxts;
00096 unsigned int lastividtimestamp;
00097 unsigned int lastovidtimestamp;
00098 unsigned int lasteventseqn;
00099 unsigned int lasteventendseqn;
00100 int lasttxformat;
00101 int lastrxformat;
00102 int dtmfcount;
00103 unsigned int dtmfduration;
00104 int nat;
00105 unsigned int flags;
00106
00107 struct sockaddr_in us;
00108
00109 struct sockaddr_in them;
00110 struct timeval rxcore;
00111 struct timeval txcore;
00112 struct timeval dtmfmute;
00113 struct ast_smoother *smoother;
00114 int *ioid;
00115
00116 unsigned short seqno;
00117 unsigned short rxseqno;
00118 struct sched_context *sched;
00119 struct io_context *io;
00120 void *data;
00121 ast_rtp_callback callback;
00122 struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
00123
00124 int rtp_lookup_code_cache_isAstFormat;
00125 int rtp_lookup_code_cache_code;
00126 int rtp_lookup_code_cache_result;
00127 int rtp_offered_from_local;
00128 struct ast_rtcp *rtcp;
00129 };
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 struct ast_rtcp {
00142
00143 int s;
00144
00145 struct sockaddr_in us;
00146
00147 struct sockaddr_in them;
00148 };
00149
00150 static struct ast_rtp_protocol *protos = NULL;
00151
00152 int ast_rtp_fd(struct ast_rtp *rtp)
00153 {
00154 return rtp->s;
00155 }
00156
00157 int ast_rtcp_fd(struct ast_rtp *rtp)
00158 {
00159 if (rtp->rtcp)
00160 return rtp->rtcp->s;
00161 return -1;
00162 }
00163
00164 void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
00165 {
00166 rtp->data = data;
00167 }
00168
00169 void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
00170 {
00171 rtp->callback = callback;
00172 }
00173
00174 void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
00175 {
00176 rtp->nat = nat;
00177 }
00178
00179 static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
00180 {
00181 static struct ast_frame null_frame = { AST_FRAME_NULL, };
00182 char iabuf[INET_ADDRSTRLEN];
00183
00184 if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
00185 if (option_debug)
00186 ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
00187 rtp->resp = 0;
00188 rtp->dtmfduration = 0;
00189 return &null_frame;
00190 }
00191 if (option_debug)
00192 ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
00193 if (rtp->resp == 'X') {
00194 rtp->f.frametype = AST_FRAME_CONTROL;
00195 rtp->f.subclass = AST_CONTROL_FLASH;
00196 } else {
00197 rtp->f.frametype = AST_FRAME_DTMF;
00198 rtp->f.subclass = rtp->resp;
00199 }
00200 rtp->f.datalen = 0;
00201 rtp->f.samples = 0;
00202 rtp->f.mallocd = 0;
00203 rtp->f.src = "RTP";
00204 rtp->resp = 0;
00205 rtp->dtmfduration = 0;
00206 return &rtp->f;
00207
00208 }
00209
00210 static inline int rtp_debug_test_addr(struct sockaddr_in *addr)
00211 {
00212 if (rtpdebug == 0)
00213 return 0;
00214 if (rtpdebugaddr.sin_addr.s_addr) {
00215 if (((ntohs(rtpdebugaddr.sin_port) != 0)
00216 && (rtpdebugaddr.sin_port != addr->sin_port))
00217 || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00218 return 0;
00219 }
00220 return 1;
00221 }
00222
00223 static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
00224 {
00225 unsigned int event;
00226 char resp = 0;
00227 struct ast_frame *f = NULL;
00228 event = ntohl(*((unsigned int *)(data)));
00229 event &= 0x001F;
00230 #if 0
00231 printf("Cisco Digit: %08x (len = %d)\n", event, len);
00232 #endif
00233 if (event < 10) {
00234 resp = '0' + event;
00235 } else if (event < 11) {
00236 resp = '*';
00237 } else if (event < 12) {
00238 resp = '#';
00239 } else if (event < 16) {
00240 resp = 'A' + (event - 12);
00241 } else if (event < 17) {
00242 resp = 'X';
00243 }
00244 if (rtp->resp && (rtp->resp != resp)) {
00245 f = send_dtmf(rtp);
00246 }
00247 rtp->resp = resp;
00248 rtp->dtmfcount = dtmftimeout;
00249 return f;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 static struct ast_frame *process_rfc2833(struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno)
00264 {
00265 unsigned int event;
00266 unsigned int event_end;
00267 unsigned int duration;
00268 char resp = 0;
00269 struct ast_frame *f = NULL;
00270 event = ntohl(*((unsigned int *)(data)));
00271 event >>= 24;
00272 event_end = ntohl(*((unsigned int *)(data)));
00273 event_end <<= 8;
00274 event_end >>= 24;
00275 duration = ntohl(*((unsigned int *)(data)));
00276 duration &= 0xFFFF;
00277 if (rtpdebug)
00278 ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
00279 if (event < 10) {
00280 resp = '0' + event;
00281 } else if (event < 11) {
00282 resp = '*';
00283 } else if (event < 12) {
00284 resp = '#';
00285 } else if (event < 16) {
00286 resp = 'A' + (event - 12);
00287 } else if (event < 17) {
00288 resp = 'X';
00289 }
00290 if (rtp->resp && (rtp->resp != resp)) {
00291 f = send_dtmf(rtp);
00292 } else if(event_end & 0x80) {
00293 if (rtp->resp) {
00294 if(rtp->lasteventendseqn != seqno) {
00295 f = send_dtmf(rtp);
00296 rtp->lasteventendseqn = seqno;
00297 }
00298 rtp->resp = 0;
00299 }
00300 resp = 0;
00301 duration = 0;
00302 } else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) {
00303 f = send_dtmf(rtp);
00304 }
00305 if (!(event_end & 0x80))
00306 rtp->resp = resp;
00307 rtp->dtmfcount = dtmftimeout;
00308 rtp->dtmfduration = duration;
00309 return f;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 static struct ast_frame *process_rfc3389(struct ast_rtp *rtp, unsigned char *data, int len)
00319 {
00320 struct ast_frame *f = NULL;
00321
00322
00323
00324 if (rtpdebug)
00325 ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
00326
00327 if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
00328 char iabuf[INET_ADDRSTRLEN];
00329
00330 ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
00331 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
00332 ast_set_flag(rtp, FLAG_3389_WARNING);
00333 }
00334
00335
00336 if (!len)
00337 return NULL;
00338 if (len < 24) {
00339 rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
00340 rtp->f.datalen = len - 1;
00341 rtp->f.offset = AST_FRIENDLY_OFFSET;
00342 memcpy(rtp->f.data, data + 1, len - 1);
00343 } else {
00344 rtp->f.data = NULL;
00345 rtp->f.offset = 0;
00346 rtp->f.datalen = 0;
00347 }
00348 rtp->f.frametype = AST_FRAME_CNG;
00349 rtp->f.subclass = data[0] & 0x7f;
00350 rtp->f.datalen = len - 1;
00351 rtp->f.samples = 0;
00352 rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
00353 f = &rtp->f;
00354 return f;
00355 }
00356
00357 static int rtpread(int *id, int fd, short events, void *cbdata)
00358 {
00359 struct ast_rtp *rtp = cbdata;
00360 struct ast_frame *f;
00361 f = ast_rtp_read(rtp);
00362 if (f) {
00363 if (rtp->callback)
00364 rtp->callback(rtp, f, rtp->data);
00365 }
00366 return 1;
00367 }
00368
00369 struct ast_frame *ast_rtcp_read(struct ast_rtp *rtp)
00370 {
00371 static struct ast_frame null_frame = { AST_FRAME_NULL, };
00372 socklen_t len;
00373 int hdrlen = 8;
00374 int res;
00375 struct sockaddr_in sin;
00376 unsigned int rtcpdata[1024];
00377 char iabuf[INET_ADDRSTRLEN];
00378
00379 if (!rtp || !rtp->rtcp)
00380 return &null_frame;
00381
00382 len = sizeof(sin);
00383
00384 res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
00385 0, (struct sockaddr *)&sin, &len);
00386
00387 if (res < 0) {
00388 if (errno != EAGAIN)
00389 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00390 if (errno == EBADF)
00391 CRASH;
00392 return &null_frame;
00393 }
00394
00395 if (res < hdrlen) {
00396 ast_log(LOG_WARNING, "RTP Read too short\n");
00397 return &null_frame;
00398 }
00399
00400 if (rtp->nat) {
00401
00402 if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00403 (rtp->rtcp->them.sin_port != sin.sin_port)) {
00404 memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00405 if (option_debug || rtpdebug)
00406 ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00407 }
00408 }
00409 if (option_debug)
00410 ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00411 return &null_frame;
00412 }
00413
00414 static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
00415 {
00416 struct timeval ts = ast_samp2tv( timestamp, 8000);
00417 if (ast_tvzero(rtp->rxcore) || mark) {
00418 rtp->rxcore = ast_tvsub(ast_tvnow(), ts);
00419
00420 rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 20000;
00421 }
00422 *tv = ast_tvadd(rtp->rxcore, ts);
00423 }
00424
00425 struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
00426 {
00427 int res;
00428 struct sockaddr_in sin;
00429 socklen_t len;
00430 unsigned int seqno;
00431 int version;
00432 int payloadtype;
00433 int hdrlen = 12;
00434 int padding;
00435 int mark;
00436 int ext;
00437 int x;
00438 char iabuf[INET_ADDRSTRLEN];
00439 unsigned int timestamp;
00440 unsigned int *rtpheader;
00441 static struct ast_frame *f, null_frame = { AST_FRAME_NULL, };
00442 struct rtpPayloadType rtpPT;
00443
00444 len = sizeof(sin);
00445
00446
00447 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
00448 0, (struct sockaddr *)&sin, &len);
00449
00450
00451 rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
00452 if (res < 0) {
00453 if (errno != EAGAIN)
00454 ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00455 if (errno == EBADF)
00456 CRASH;
00457 return &null_frame;
00458 }
00459 if (res < hdrlen) {
00460 ast_log(LOG_WARNING, "RTP Read too short\n");
00461 return &null_frame;
00462 }
00463
00464
00465
00466 if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
00467 return &null_frame;
00468
00469 if (rtp->nat) {
00470
00471 if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00472 (rtp->them.sin_port != sin.sin_port)) {
00473 memcpy(&rtp->them, &sin, sizeof(rtp->them));
00474 rtp->rxseqno = 0;
00475 ast_set_flag(rtp, FLAG_NAT_ACTIVE);
00476 if (option_debug || rtpdebug)
00477 ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
00478 }
00479 }
00480
00481
00482 seqno = ntohl(rtpheader[0]);
00483
00484
00485 version = (seqno & 0xC0000000) >> 30;
00486 if (version != 2)
00487 return &null_frame;
00488
00489 payloadtype = (seqno & 0x7f0000) >> 16;
00490 padding = seqno & (1 << 29);
00491 mark = seqno & (1 << 23);
00492 ext = seqno & (1 << 28);
00493 seqno &= 0xffff;
00494 timestamp = ntohl(rtpheader[1]);
00495
00496 if (padding) {
00497
00498 res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
00499 }
00500
00501 if (ext) {
00502
00503 hdrlen += 4;
00504 hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2;
00505 }
00506
00507 if (res < hdrlen) {
00508 ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
00509 return &null_frame;
00510 }
00511
00512 if(rtp_debug_test_addr(&sin))
00513 ast_verbose("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len %d)\n"
00514 , ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
00515
00516 rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
00517 if (!rtpPT.isAstFormat) {
00518
00519 if (rtpPT.code == AST_RTP_DTMF) {
00520
00521 if(rtp_debug_test_addr(&sin)) {
00522 unsigned char *data;
00523 unsigned int event;
00524 unsigned int event_end;
00525 unsigned int duration;
00526 data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
00527 event = ntohl(*((unsigned int *)(data)));
00528 event >>= 24;
00529 event_end = ntohl(*((unsigned int *)(data)));
00530 event_end <<= 8;
00531 event_end >>= 24;
00532 duration = ntohl(*((unsigned int *)(data)));
00533 duration &= 0xFFFF;
00534 ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
00535 }
00536 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00537 f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
00538 rtp->lasteventseqn = seqno;
00539 } else
00540 f = NULL;
00541 if (f)
00542 return f;
00543 else
00544 return &null_frame;
00545 } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
00546
00547 if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
00548 f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00549 rtp->lasteventseqn = seqno;
00550 } else
00551 f = NULL;
00552 if (f)
00553 return f;
00554 else
00555 return &null_frame;
00556 } else if (rtpPT.code == AST_RTP_CN) {
00557
00558 f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
00559 if (f)
00560 return f;
00561 else
00562 return &null_frame;
00563 } else {
00564 ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
00565 return &null_frame;
00566 }
00567 }
00568 rtp->f.subclass = rtpPT.code;
00569 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
00570 rtp->f.frametype = AST_FRAME_VOICE;
00571 else
00572 rtp->f.frametype = AST_FRAME_VIDEO;
00573 rtp->lastrxformat = rtp->f.subclass;
00574
00575 if (!rtp->lastrxts)
00576 rtp->lastrxts = timestamp;
00577
00578 if (rtp->rxseqno) {
00579 for (x=rtp->rxseqno + 1; x < seqno; x++) {
00580
00581 rtp->f.mallocd = 0;
00582 rtp->f.datalen = 0;
00583 rtp->f.data = NULL;
00584 rtp->f.offset = 0;
00585 rtp->f.samples = 0;
00586 rtp->f.src = "RTPMissedFrame";
00587 }
00588 }
00589 rtp->rxseqno = seqno;
00590
00591 if (rtp->dtmfcount) {
00592 #if 0
00593 printf("dtmfcount was %d\n", rtp->dtmfcount);
00594 #endif
00595 rtp->dtmfcount -= (timestamp - rtp->lastrxts);
00596 if (rtp->dtmfcount < 0)
00597 rtp->dtmfcount = 0;
00598 #if 0
00599 if (dtmftimeout != rtp->dtmfcount)
00600 printf("dtmfcount is %d\n", rtp->dtmfcount);
00601 #endif
00602 }
00603 rtp->lastrxts = timestamp;
00604
00605
00606 if (rtp->resp && !rtp->dtmfcount) {
00607 if (option_debug)
00608 ast_log(LOG_DEBUG, "Sending pending DTMF\n");
00609 return send_dtmf(rtp);
00610 }
00611 rtp->f.mallocd = 0;
00612 rtp->f.datalen = res - hdrlen;
00613 rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
00614 rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
00615 if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
00616 rtp->f.samples = ast_codec_get_samples(&rtp->f);
00617 if (rtp->f.subclass == AST_FORMAT_SLINEAR)
00618 ast_frame_byteswap_be(&rtp->f);
00619 calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
00620 } else {
00621
00622 if (!rtp->lastividtimestamp)
00623 rtp->lastividtimestamp = timestamp;
00624 rtp->f.samples = timestamp - rtp->lastividtimestamp;
00625 rtp->lastividtimestamp = timestamp;
00626 rtp->f.delivery.tv_sec = 0;
00627 rtp->f.delivery.tv_usec = 0;
00628 if (mark)
00629 rtp->f.subclass |= 0x1;
00630
00631 }
00632 rtp->f.src = "RTP";
00633 return &rtp->f;
00634 }
00635
00636
00637
00638 static struct {
00639 struct rtpPayloadType payloadType;
00640 char* type;
00641 char* subtype;
00642 } mimeTypes[] = {
00643 {{1, AST_FORMAT_G723_1}, "audio", "G723"},
00644 {{1, AST_FORMAT_GSM}, "audio", "GSM"},
00645 {{1, AST_FORMAT_ULAW}, "audio", "PCMU"},
00646 {{1, AST_FORMAT_ALAW}, "audio", "PCMA"},
00647 {{1, AST_FORMAT_G726}, "audio", "G726-32"},
00648 {{1, AST_FORMAT_ADPCM}, "audio", "DVI4"},
00649 {{1, AST_FORMAT_SLINEAR}, "audio", "L16"},
00650 {{1, AST_FORMAT_LPC10}, "audio", "LPC"},
00651 {{1, AST_FORMAT_G729A}, "audio", "G729"},
00652 {{1, AST_FORMAT_SPEEX}, "audio", "speex"},
00653 {{1, AST_FORMAT_ILBC}, "audio", "iLBC"},
00654 {{0, AST_RTP_DTMF}, "audio", "telephone-event"},
00655 {{0, AST_RTP_CISCO_DTMF}, "audio", "cisco-telephone-event"},
00656 {{0, AST_RTP_CN}, "audio", "CN"},
00657 {{1, AST_FORMAT_JPEG}, "video", "JPEG"},
00658 {{1, AST_FORMAT_PNG}, "video", "PNG"},
00659 {{1, AST_FORMAT_H261}, "video", "H261"},
00660 {{1, AST_FORMAT_H263}, "video", "H263"},
00661 {{1, AST_FORMAT_H263_PLUS}, "video", "h263-1998"},
00662 };
00663
00664
00665
00666
00667 static struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] = {
00668 [0] = {1, AST_FORMAT_ULAW},
00669 #ifdef USE_DEPRECATED_G726
00670 [2] = {1, AST_FORMAT_G726},
00671 #endif
00672 [3] = {1, AST_FORMAT_GSM},
00673 [4] = {1, AST_FORMAT_G723_1},
00674 [5] = {1, AST_FORMAT_ADPCM},
00675 [6] = {1, AST_FORMAT_ADPCM},
00676 [7] = {1, AST_FORMAT_LPC10},
00677 [8] = {1, AST_FORMAT_ALAW},
00678 [10] = {1, AST_FORMAT_SLINEAR},
00679 [11] = {1, AST_FORMAT_SLINEAR},
00680 [13] = {0, AST_RTP_CN},
00681 [16] = {1, AST_FORMAT_ADPCM},
00682 [17] = {1, AST_FORMAT_ADPCM},
00683 [18] = {1, AST_FORMAT_G729A},
00684 [19] = {0, AST_RTP_CN},
00685 [26] = {1, AST_FORMAT_JPEG},
00686 [31] = {1, AST_FORMAT_H261},
00687 [34] = {1, AST_FORMAT_H263},
00688 [103] = {1, AST_FORMAT_H263_PLUS},
00689 [97] = {1, AST_FORMAT_ILBC},
00690 [101] = {0, AST_RTP_DTMF},
00691 [110] = {1, AST_FORMAT_SPEEX},
00692 [111] = {1, AST_FORMAT_G726},
00693 [121] = {0, AST_RTP_CISCO_DTMF},
00694 };
00695
00696 void ast_rtp_pt_clear(struct ast_rtp* rtp)
00697 {
00698 int i;
00699 if (!rtp)
00700 return;
00701
00702 for (i = 0; i < MAX_RTP_PT; ++i) {
00703 rtp->current_RTP_PT[i].isAstFormat = 0;
00704 rtp->current_RTP_PT[i].code = 0;
00705 }
00706
00707 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00708 rtp->rtp_lookup_code_cache_code = 0;
00709 rtp->rtp_lookup_code_cache_result = 0;
00710 }
00711
00712 void ast_rtp_pt_default(struct ast_rtp* rtp)
00713 {
00714 int i;
00715
00716
00717 for (i = 0; i < MAX_RTP_PT; ++i) {
00718 rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00719 rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00720 }
00721
00722 rtp->rtp_lookup_code_cache_isAstFormat = 0;
00723 rtp->rtp_lookup_code_cache_code = 0;
00724 rtp->rtp_lookup_code_cache_result = 0;
00725 }
00726
00727
00728
00729
00730 void ast_rtp_set_m_type(struct ast_rtp* rtp, int pt) {
00731 if (pt < 0 || pt > MAX_RTP_PT)
00732 return;
00733
00734 if (static_RTP_PT[pt].code != 0) {
00735 rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00736 }
00737 }
00738
00739
00740
00741 void ast_rtp_set_rtpmap_type(struct ast_rtp* rtp, int pt,
00742 char* mimeType, char* mimeSubtype) {
00743 int i;
00744
00745 if (pt < 0 || pt > MAX_RTP_PT)
00746 return;
00747
00748 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00749 if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00750 strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00751 rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00752 return;
00753 }
00754 }
00755 }
00756
00757
00758
00759 void ast_rtp_get_current_formats(struct ast_rtp* rtp,
00760 int* astFormats, int* nonAstFormats) {
00761 int pt;
00762
00763 *astFormats = *nonAstFormats = 0;
00764 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00765 if (rtp->current_RTP_PT[pt].isAstFormat) {
00766 *astFormats |= rtp->current_RTP_PT[pt].code;
00767 } else {
00768 *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00769 }
00770 }
00771 }
00772
00773 void ast_rtp_offered_from_local(struct ast_rtp* rtp, int local) {
00774 if (rtp)
00775 rtp->rtp_offered_from_local = local;
00776 else
00777 ast_log(LOG_WARNING, "rtp structure is null\n");
00778 }
00779
00780 struct rtpPayloadType ast_rtp_lookup_pt(struct ast_rtp* rtp, int pt)
00781 {
00782 struct rtpPayloadType result;
00783
00784 result.isAstFormat = result.code = 0;
00785 if (pt < 0 || pt > MAX_RTP_PT)
00786 return result;
00787
00788
00789 if (!rtp->rtp_offered_from_local)
00790 result = rtp->current_RTP_PT[pt];
00791
00792
00793 if (!result.code)
00794 result = static_RTP_PT[pt];
00795 return result;
00796 }
00797
00798
00799 int ast_rtp_lookup_code(struct ast_rtp* rtp, const int isAstFormat, const int code) {
00800
00801 int pt;
00802
00803 if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00804 code == rtp->rtp_lookup_code_cache_code) {
00805
00806
00807 return rtp->rtp_lookup_code_cache_result;
00808 }
00809
00810
00811 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00812 if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00813 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00814 rtp->rtp_lookup_code_cache_code = code;
00815 rtp->rtp_lookup_code_cache_result = pt;
00816 return pt;
00817 }
00818 }
00819
00820
00821 for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00822 if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
00823 rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00824 rtp->rtp_lookup_code_cache_code = code;
00825 rtp->rtp_lookup_code_cache_result = pt;
00826 return pt;
00827 }
00828 }
00829 return -1;
00830 }
00831
00832 char* ast_rtp_lookup_mime_subtype(const int isAstFormat, const int code) {
00833
00834 int i;
00835
00836 for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00837 if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00838 return mimeTypes[i].subtype;
00839 }
00840 }
00841 return "";
00842 }
00843
00844 char *ast_rtp_lookup_mime_multiple(char *buf, int size, const int capability, const int isAstFormat)
00845 {
00846 int format;
00847 unsigned len;
00848 char *end = buf;
00849 char *start = buf;
00850
00851 if (!buf || !size)
00852 return NULL;
00853
00854 snprintf(end, size, "0x%x (", capability);
00855
00856 len = strlen(end);
00857 end += len;
00858 size -= len;
00859 start = end;
00860
00861 for (format = 1; format < AST_RTP_MAX; format <<= 1) {
00862 if (capability & format) {
00863 const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
00864 snprintf(end, size, "%s|", name);
00865 len = strlen(end);
00866 end += len;
00867 size -= len;
00868 }
00869 }
00870
00871 if (start == end)
00872 snprintf(start, size, "nothing)");
00873 else if (size > 1)
00874 *(end -1) = ')';
00875
00876 return buf;
00877 }
00878
00879 static int rtp_socket(void)
00880 {
00881 int s;
00882 long flags;
00883 s = socket(AF_INET, SOCK_DGRAM, 0);
00884 if (s > -1) {
00885 flags = fcntl(s, F_GETFL);
00886 fcntl(s, F_SETFL, flags | O_NONBLOCK);
00887 #ifdef SO_NO_CHECK
00888 if (nochecksums)
00889 setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00890 #endif
00891 }
00892 return s;
00893 }
00894
00895
00896
00897
00898
00899
00900 static struct ast_rtcp *ast_rtcp_new(void)
00901 {
00902 struct ast_rtcp *rtcp;
00903 rtcp = malloc(sizeof(struct ast_rtcp));
00904 if (!rtcp)
00905 return NULL;
00906 memset(rtcp, 0, sizeof(struct ast_rtcp));
00907 rtcp->s = rtp_socket();
00908 rtcp->us.sin_family = AF_INET;
00909 if (rtcp->s < 0) {
00910 free(rtcp);
00911 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00912 return NULL;
00913 }
00914 return rtcp;
00915 }
00916
00917 struct ast_rtp *ast_rtp_new_with_bindaddr(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
00918 {
00919 struct ast_rtp *rtp;
00920 int x;
00921 int first;
00922 int startplace;
00923 rtp = malloc(sizeof(struct ast_rtp));
00924 if (!rtp)
00925 return NULL;
00926 memset(rtp, 0, sizeof(struct ast_rtp));
00927 rtp->them.sin_family = AF_INET;
00928 rtp->us.sin_family = AF_INET;
00929 rtp->s = rtp_socket();
00930 rtp->ssrc = rand();
00931 rtp->seqno = rand() & 0xffff;
00932 if (rtp->s < 0) {
00933 free(rtp);
00934 ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
00935 return NULL;
00936 }
00937 if (sched && rtcpenable) {
00938 rtp->sched = sched;
00939 rtp->rtcp = ast_rtcp_new();
00940 }
00941
00942
00943 x = (rand() % (rtpend-rtpstart)) + rtpstart;
00944 x = x & ~1;
00945
00946 startplace = x;
00947
00948 for (;;) {
00949
00950 rtp->us.sin_port = htons(x);
00951 rtp->us.sin_addr = addr;
00952
00953 if (rtp->rtcp)
00954 rtp->rtcp->us.sin_port = htons(x + 1);
00955
00956 if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
00957 (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
00958 break;
00959 if (!first) {
00960
00961 close(rtp->s);
00962 rtp->s = rtp_socket();
00963 }
00964 if (errno != EADDRINUSE) {
00965
00966 ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
00967 close(rtp->s);
00968 if (rtp->rtcp) {
00969 close(rtp->rtcp->s);
00970 free(rtp->rtcp);
00971 }
00972 free(rtp);
00973 return NULL;
00974 }
00975
00976 x += 2;
00977
00978 if (x > rtpend)
00979
00980 x = (rtpstart + 1) & ~1;
00981
00982 if (x == startplace) {
00983
00984 ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
00985 close(rtp->s);
00986 if (rtp->rtcp) {
00987 close(rtp->rtcp->s);
00988 free(rtp->rtcp);
00989 }
00990 free(rtp);
00991 return NULL;
00992 }
00993 }
00994 if (io && sched && callbackmode) {
00995
00996 rtp->sched = sched;
00997 rtp->io = io;
00998 rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
00999 }
01000 ast_rtp_pt_default(rtp);
01001 return rtp;
01002 }
01003
01004 struct ast_rtp *ast_rtp_new(struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
01005 {
01006 struct in_addr ia;
01007
01008 memset(&ia, 0, sizeof(ia));
01009 return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01010 }
01011
01012 int ast_rtp_settos(struct ast_rtp *rtp, int tos)
01013 {
01014 int res;
01015
01016 if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
01017 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01018 return res;
01019 }
01020
01021 void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
01022 {
01023 rtp->them.sin_port = them->sin_port;
01024 rtp->them.sin_addr = them->sin_addr;
01025 if (rtp->rtcp) {
01026 rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01027 rtp->rtcp->them.sin_addr = them->sin_addr;
01028 }
01029 rtp->rxseqno = 0;
01030 }
01031
01032 void ast_rtp_get_peer(struct ast_rtp *rtp, struct sockaddr_in *them)
01033 {
01034 them->sin_family = AF_INET;
01035 them->sin_port = rtp->them.sin_port;
01036 them->sin_addr = rtp->them.sin_addr;
01037 }
01038
01039 void ast_rtp_get_us(struct ast_rtp *rtp, struct sockaddr_in *us)
01040 {
01041 memcpy(us, &rtp->us, sizeof(rtp->us));
01042 }
01043
01044 void ast_rtp_stop(struct ast_rtp *rtp)
01045 {
01046 memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01047 memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01048 if (rtp->rtcp) {
01049 memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01050 memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01051 }
01052 }
01053
01054 void ast_rtp_reset(struct ast_rtp *rtp)
01055 {
01056 memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
01057 memset(&rtp->txcore, 0, sizeof(rtp->txcore));
01058 memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
01059 rtp->lastts = 0;
01060 rtp->lastdigitts = 0;
01061 rtp->lastrxts = 0;
01062 rtp->lastividtimestamp = 0;
01063 rtp->lastovidtimestamp = 0;
01064 rtp->lasteventseqn = 0;
01065 rtp->lasteventendseqn = 0;
01066 rtp->lasttxformat = 0;
01067 rtp->lastrxformat = 0;
01068 rtp->dtmfcount = 0;
01069 rtp->dtmfduration = 0;
01070 rtp->seqno = 0;
01071 rtp->rxseqno = 0;
01072 }
01073
01074 void ast_rtp_destroy(struct ast_rtp *rtp)
01075 {
01076 if (rtp->smoother)
01077 ast_smoother_free(rtp->smoother);
01078 if (rtp->ioid)
01079 ast_io_remove(rtp->io, rtp->ioid);
01080 if (rtp->s > -1)
01081 close(rtp->s);
01082 if (rtp->rtcp) {
01083 close(rtp->rtcp->s);
01084 free(rtp->rtcp);
01085 }
01086 free(rtp);
01087 }
01088
01089 static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
01090 {
01091 struct timeval t;
01092 long ms;
01093 if (ast_tvzero(rtp->txcore)) {
01094 rtp->txcore = ast_tvnow();
01095
01096 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
01097 }
01098
01099 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
01100 ms = ast_tvdiff_ms(t, rtp->txcore);
01101 if (ms < 0)
01102 ms = 0;
01103
01104 rtp->txcore = t;
01105 return (unsigned int) ms;
01106 }
01107
01108 int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
01109 {
01110 unsigned int *rtpheader;
01111 int hdrlen = 12;
01112 int res;
01113 int x;
01114 int payload;
01115 char data[256];
01116 char iabuf[INET_ADDRSTRLEN];
01117
01118 if ((digit <= '9') && (digit >= '0'))
01119 digit -= '0';
01120 else if (digit == '*')
01121 digit = 10;
01122 else if (digit == '#')
01123 digit = 11;
01124 else if ((digit >= 'A') && (digit <= 'D'))
01125 digit = digit - 'A' + 12;
01126 else if ((digit >= 'a') && (digit <= 'd'))
01127 digit = digit - 'a' + 12;
01128 else {
01129 ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
01130 return -1;
01131 }
01132 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
01133
01134
01135 if (!rtp->them.sin_addr.s_addr)
01136 return 0;
01137
01138 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
01139
01140
01141 rtpheader = (unsigned int *)data;
01142 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
01143 rtpheader[1] = htonl(rtp->lastdigitts);
01144 rtpheader[2] = htonl(rtp->ssrc);
01145 rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
01146 for (x = 0; x < 6; x++) {
01147 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01148 res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
01149 if (res < 0)
01150 ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
01151 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
01152 ntohs(rtp->them.sin_port), strerror(errno));
01153 if (rtp_debug_test_addr(&rtp->them))
01154 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n",
01155 ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
01156 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
01157 }
01158
01159 if (x < 3)
01160 rtp->seqno++;
01161
01162 rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
01163
01164 if (x == 2) {
01165 #if 0
01166
01167
01168 rtp->lastdigitts++;
01169 rtpheader[1] = htonl(rtp->lastdigitts);
01170 #endif
01171
01172 rtpheader[3] |= htonl((800));
01173
01174 rtpheader[3] |= htonl((1 << 23));
01175 }
01176 }
01177
01178
01179
01180
01181
01182 rtp->lastdigitts += 960;
01183
01184
01185
01186 rtp->seqno++;
01187 return 0;
01188 }
01189
01190 int ast_rtp_sendcng(struct ast_rtp *rtp, int level)
01191 {
01192 unsigned int *rtpheader;
01193 int hdrlen = 12;
01194 int res;
01195 int payload;
01196 char data[256];
01197 char iabuf[INET_ADDRSTRLEN];
01198 level = 127 - (level & 0x7f);
01199 payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
01200
01201
01202 if (!rtp->them.sin_addr.s_addr)
01203 return 0;
01204
01205 rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
01206
01207
01208 rtpheader = (unsigned int *)data;
01209 rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
01210 rtpheader[1] = htonl(rtp->lastts);
01211 rtpheader[2] = htonl(rtp->ssrc);
01212 data[12] = level;
01213 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01214 res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01215 if (res <0)
01216 ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
01217 if(rtp_debug_test_addr(&rtp->them))
01218 ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n"
01219 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
01220
01221 }
01222 return 0;
01223 }
01224
01225 static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec)
01226 {
01227 unsigned char *rtpheader;
01228 char iabuf[INET_ADDRSTRLEN];
01229 int hdrlen = 12;
01230 int res;
01231 unsigned int ms;
01232 int pred;
01233 int mark = 0;
01234
01235 ms = calc_txstamp(rtp, &f->delivery);
01236
01237 if (f->subclass < AST_FORMAT_MAX_AUDIO) {
01238 pred = rtp->lastts + f->samples;
01239
01240
01241 rtp->lastts = rtp->lastts + ms * 8;
01242 if (ast_tvzero(f->delivery)) {
01243
01244
01245 if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
01246 rtp->lastts = pred;
01247 else {
01248 if (option_debug > 2)
01249 ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
01250 mark = 1;
01251 }
01252 }
01253 } else {
01254 mark = f->subclass & 0x1;
01255 pred = rtp->lastovidtimestamp + f->samples;
01256
01257 rtp->lastts = rtp->lastts + ms * 90;
01258
01259 if (ast_tvzero(f->delivery)) {
01260 if (abs(rtp->lastts - pred) < 7200) {
01261 rtp->lastts = pred;
01262 rtp->lastovidtimestamp += f->samples;
01263 } else {
01264 if (option_debug > 2)
01265 ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
01266 rtp->lastovidtimestamp = rtp->lastts;
01267 }
01268 }
01269 }
01270
01271
01272
01273 if (rtp->lastts > rtp->lastdigitts)
01274 rtp->lastdigitts = rtp->lastts;
01275
01276
01277 rtpheader = (unsigned char *)(f->data - hdrlen);
01278
01279 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
01280 put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
01281 put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
01282
01283 if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01284 res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01285 if (res <0) {
01286 if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01287 ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
01288 } else if ((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) {
01289
01290 if (option_debug || rtpdebug)
01291 ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
01292 ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
01293 }
01294 }
01295
01296 if(rtp_debug_test_addr(&rtp->them))
01297 ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n"
01298 , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
01299 }
01300
01301 rtp->seqno++;
01302
01303 return 0;
01304 }
01305
01306 int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
01307 {
01308 struct ast_frame *f;
01309 int codec;
01310 int hdrlen = 12;
01311 int subclass;
01312
01313
01314
01315 if (!rtp->them.sin_addr.s_addr)
01316 return 0;
01317
01318
01319 if (!_f->datalen)
01320 return 0;
01321
01322
01323 if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
01324 ast_log(LOG_WARNING, "RTP can only send voice\n");
01325 return -1;
01326 }
01327
01328 subclass = _f->subclass;
01329 if (_f->frametype == AST_FRAME_VIDEO)
01330 subclass &= ~0x1;
01331
01332 codec = ast_rtp_lookup_code(rtp, 1, subclass);
01333 if (codec < 0) {
01334 ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
01335 return -1;
01336 }
01337
01338 if (rtp->lasttxformat != subclass) {
01339
01340 if (option_debug)
01341 ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01342 rtp->lasttxformat = subclass;
01343 if (rtp->smoother)
01344 ast_smoother_free(rtp->smoother);
01345 rtp->smoother = NULL;
01346 }
01347
01348
01349 switch(subclass) {
01350 case AST_FORMAT_SLINEAR:
01351 if (!rtp->smoother) {
01352 rtp->smoother = ast_smoother_new(320);
01353 }
01354 if (!rtp->smoother) {
01355 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01356 return -1;
01357 }
01358 ast_smoother_feed_be(rtp->smoother, _f);
01359
01360 while((f = ast_smoother_read(rtp->smoother)))
01361 ast_rtp_raw_write(rtp, f, codec);
01362 break;
01363 case AST_FORMAT_ULAW:
01364 case AST_FORMAT_ALAW:
01365 if (!rtp->smoother) {
01366 rtp->smoother = ast_smoother_new(160);
01367 }
01368 if (!rtp->smoother) {
01369 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01370 return -1;
01371 }
01372 ast_smoother_feed(rtp->smoother, _f);
01373
01374 while((f = ast_smoother_read(rtp->smoother)))
01375 ast_rtp_raw_write(rtp, f, codec);
01376 break;
01377 case AST_FORMAT_ADPCM:
01378 case AST_FORMAT_G726:
01379 if (!rtp->smoother) {
01380 rtp->smoother = ast_smoother_new(80);
01381 }
01382 if (!rtp->smoother) {
01383 ast_log(LOG_WARNING, "Unable to create smoother :(\n");
01384 return -1;
01385 }
01386 ast_smoother_feed(rtp->smoother, _f);
01387
01388 while((f = ast_smoother_read(rtp->smoother)))
01389 ast_rtp_raw_write(rtp, f, codec);
01390 break;
01391 case AST_FORMAT_G729A:
01392 if (!rtp->smoother) {
01393 rtp->smoother = ast_smoother_new(20);
01394 if (rtp->smoother)
01395 ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
01396 }
01397 if (!rtp->smoother) {
01398 ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
01399 return -1;
01400 }
01401 ast_smoother_feed(rtp->smoother, _f);
01402
01403 while((f = ast_smoother_read(rtp->smoother)))
01404 ast_rtp_raw_write(rtp, f, codec);
01405 break;
01406 case AST_FORMAT_GSM:
01407 if (!rtp->smoother) {
01408 rtp->smoother = ast_smoother_new(33);
01409 }
01410 if (!rtp->smoother) {
01411 ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
01412 return -1;
01413 }
01414 ast_smoother_feed(rtp->smoother, _f);
01415 while((f = ast_smoother_read(rtp->smoother)))
01416 ast_rtp_raw_write(rtp, f, codec);
01417 break;
01418 case AST_FORMAT_ILBC:
01419 if (!rtp->smoother) {
01420 rtp->smoother = ast_smoother_new(50);
01421 }
01422 if (!rtp->smoother) {
01423 ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
01424 return -1;
01425 }
01426 ast_smoother_feed(rtp->smoother, _f);
01427 while((f = ast_smoother_read(rtp->smoother)))
01428 ast_rtp_raw_write(rtp, f, codec);
01429 break;
01430 default:
01431 ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
01432
01433 case AST_FORMAT_H261:
01434 case AST_FORMAT_H263:
01435 case AST_FORMAT_H263_PLUS:
01436 case AST_FORMAT_G723_1:
01437 case AST_FORMAT_LPC10:
01438 case AST_FORMAT_SPEEX:
01439
01440 if (_f->offset < hdrlen) {
01441 f = ast_frdup(_f);
01442 } else {
01443 f = _f;
01444 }
01445 ast_rtp_raw_write(rtp, f, codec);
01446 }
01447
01448 return 0;
01449 }
01450
01451
01452 void ast_rtp_proto_unregister(struct ast_rtp_protocol *proto)
01453 {
01454 struct ast_rtp_protocol *cur, *prev;
01455
01456 cur = protos;
01457 prev = NULL;
01458 while(cur) {
01459 if (cur == proto) {
01460 if (prev)
01461 prev->next = proto->next;
01462 else
01463 protos = proto->next;
01464 return;
01465 }
01466 prev = cur;
01467 cur = cur->next;
01468 }
01469 }
01470
01471
01472 int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
01473 {
01474 struct ast_rtp_protocol *cur;
01475 cur = protos;
01476 while(cur) {
01477 if (cur->type == proto->type) {
01478 ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01479 return -1;
01480 }
01481 cur = cur->next;
01482 }
01483 proto->next = protos;
01484 protos = proto;
01485 return 0;
01486 }
01487
01488
01489 static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
01490 {
01491 struct ast_rtp_protocol *cur;
01492
01493 cur = protos;
01494 while(cur) {
01495 if (cur->type == chan->type) {
01496 return cur;
01497 }
01498 cur = cur->next;
01499 }
01500 return NULL;
01501 }
01502
01503
01504
01505
01506 enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
01507 {
01508 struct ast_frame *f;
01509 struct ast_channel *who, *cs[3];
01510 struct ast_rtp *p0, *p1;
01511 struct ast_rtp *vp0, *vp1;
01512 struct ast_rtp_protocol *pr0, *pr1;
01513 struct sockaddr_in ac0, ac1;
01514 struct sockaddr_in vac0, vac1;
01515 struct sockaddr_in t0, t1;
01516 struct sockaddr_in vt0, vt1;
01517 char iabuf[INET_ADDRSTRLEN];
01518
01519 void *pvt0, *pvt1;
01520 int codec0,codec1, oldcodec0, oldcodec1;
01521
01522 memset(&vt0, 0, sizeof(vt0));
01523 memset(&vt1, 0, sizeof(vt1));
01524 memset(&vac0, 0, sizeof(vac0));
01525 memset(&vac1, 0, sizeof(vac1));
01526
01527
01528 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
01529 return AST_BRIDGE_FAILED_NOWARN;
01530
01531
01532 ast_mutex_lock(&c0->lock);
01533 while(ast_mutex_trylock(&c1->lock)) {
01534 ast_mutex_unlock(&c0->lock);
01535 usleep(1);
01536 ast_mutex_lock(&c0->lock);
01537 }
01538
01539
01540 pr0 = get_proto(c0);
01541 pr1 = get_proto(c1);
01542 if (!pr0) {
01543 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
01544 ast_mutex_unlock(&c0->lock);
01545 ast_mutex_unlock(&c1->lock);
01546 return AST_BRIDGE_FAILED;
01547 }
01548 if (!pr1) {
01549 ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
01550 ast_mutex_unlock(&c0->lock);
01551 ast_mutex_unlock(&c1->lock);
01552 return AST_BRIDGE_FAILED;
01553 }
01554
01555
01556 pvt0 = c0->tech_pvt;
01557 pvt1 = c1->tech_pvt;
01558
01559
01560 p0 = pr0->get_rtp_info(c0);
01561 if (pr0->get_vrtp_info)
01562 vp0 = pr0->get_vrtp_info(c0);
01563 else
01564 vp0 = NULL;
01565 p1 = pr1->get_rtp_info(c1);
01566 if (pr1->get_vrtp_info)
01567 vp1 = pr1->get_vrtp_info(c1);
01568 else
01569 vp1 = NULL;
01570
01571
01572 if (!p0 || !p1) {
01573
01574 ast_mutex_unlock(&c0->lock);
01575 ast_mutex_unlock(&c1->lock);
01576 return AST_BRIDGE_FAILED_NOWARN;
01577 }
01578
01579 if (pr0->get_codec)
01580 codec0 = pr0->get_codec(c0);
01581 else
01582 codec0 = 0;
01583 if (pr1->get_codec)
01584 codec1 = pr1->get_codec(c1);
01585 else
01586 codec1 = 0;
01587 if (pr0->get_codec && pr1->get_codec) {
01588
01589 if (!(codec0 & codec1)) {
01590 if (option_debug)
01591 ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
01592 ast_mutex_unlock(&c0->lock);
01593 ast_mutex_unlock(&c1->lock);
01594 return AST_BRIDGE_FAILED_NOWARN;
01595 }
01596 }
01597
01598
01599 if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
01600 ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
01601 else {
01602
01603 ast_rtp_get_peer(p1, &ac1);
01604 if (vp1)
01605 ast_rtp_get_peer(vp1, &vac1);
01606 }
01607
01608 if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
01609 ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
01610 else {
01611
01612 ast_rtp_get_peer(p0, &ac0);
01613 if (vp0)
01614 ast_rtp_get_peer(vp0, &vac0);
01615 }
01616 ast_mutex_unlock(&c0->lock);
01617 ast_mutex_unlock(&c1->lock);
01618
01619
01620 cs[0] = c0;
01621 cs[1] = c1;
01622 cs[2] = NULL;
01623 oldcodec0 = codec0;
01624 oldcodec1 = codec1;
01625 for (;;) {
01626
01627 if ((c0->tech_pvt != pvt0) ||
01628 (c1->tech_pvt != pvt1) ||
01629 (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
01630 ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
01631 if (c0->tech_pvt == pvt0) {
01632 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
01633 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
01634 }
01635 if (c1->tech_pvt == pvt1) {
01636 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
01637 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
01638 }
01639 return AST_BRIDGE_RETRY;
01640 }
01641
01642 ast_rtp_get_peer(p1, &t1);
01643 ast_rtp_get_peer(p0, &t0);
01644 if (pr0->get_codec)
01645 codec0 = pr0->get_codec(c0);
01646 if (pr1->get_codec)
01647 codec1 = pr1->get_codec(c1);
01648 if (vp1)
01649 ast_rtp_get_peer(vp1, &vt1);
01650 if (vp0)
01651 ast_rtp_get_peer(vp0, &vt0);
01652 if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
01653 if (option_debug > 1) {
01654 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01655 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
01656 ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
01657 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
01658 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01659 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
01660 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01661 c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
01662 }
01663 if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
01664 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
01665 memcpy(&ac1, &t1, sizeof(ac1));
01666 memcpy(&vac1, &vt1, sizeof(vac1));
01667 oldcodec1 = codec1;
01668 }
01669 if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
01670 if (option_debug) {
01671 ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
01672 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
01673 ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
01674 c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
01675 }
01676 if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
01677 ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
01678 memcpy(&ac0, &t0, sizeof(ac0));
01679 memcpy(&vac0, &vt0, sizeof(vac0));
01680 oldcodec0 = codec0;
01681 }
01682 who = ast_waitfor_n(cs, 2, &timeoutms);
01683 if (!who) {
01684 if (!timeoutms)
01685 return AST_BRIDGE_RETRY;
01686 if (option_debug)
01687 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
01688
01689 if (ast_check_hangup(c0) || ast_check_hangup(c1))
01690 break;
01691 continue;
01692 }
01693 f = ast_read(who);
01694 if (!f || ((f->frametype == AST_FRAME_DTMF) &&
01695 (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
01696 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
01697 *fo = f;
01698 *rc = who;
01699 if (option_debug)
01700 ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
01701 if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
01702 if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
01703 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
01704 }
01705 if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
01706 if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
01707 ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
01708 }
01709 return AST_BRIDGE_COMPLETE;
01710 } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
01711 if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) ||
01712 (f->subclass == AST_CONTROL_VIDUPDATE)) {
01713 ast_indicate(who == c0 ? c1 : c0, f->subclass);
01714 ast_frfree(f);
01715 } else {
01716 *fo = f;
01717 *rc = who;
01718 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
01719 return AST_BRIDGE_COMPLETE;
01720 }
01721 } else {
01722 if ((f->frametype == AST_FRAME_DTMF) ||
01723 (f->frametype == AST_FRAME_VOICE) ||
01724 (f->frametype == AST_FRAME_VIDEO)) {
01725
01726 if (who == c0) {
01727 ast_write(c1, f);
01728 } else if (who == c1) {
01729 ast_write(c0, f);
01730 }
01731 }
01732 ast_frfree(f);
01733 }
01734
01735 cs[2] = cs[0];
01736 cs[0] = cs[1];
01737 cs[1] = cs[2];
01738
01739 }
01740 return AST_BRIDGE_FAILED;
01741 }
01742
01743 static int rtp_do_debug_ip(int fd, int argc, char *argv[])
01744 {
01745 struct hostent *hp;
01746 struct ast_hostent ahp;
01747 char iabuf[INET_ADDRSTRLEN];
01748 int port = 0;
01749 char *p, *arg;
01750
01751 if (argc != 4)
01752 return RESULT_SHOWUSAGE;
01753 arg = argv[3];
01754 p = strstr(arg, ":");
01755 if (p) {
01756 *p = '\0';
01757 p++;
01758 port = atoi(p);
01759 }
01760 hp = ast_gethostbyname(arg, &ahp);
01761 if (hp == NULL)
01762 return RESULT_SHOWUSAGE;
01763 rtpdebugaddr.sin_family = AF_INET;
01764 memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
01765 rtpdebugaddr.sin_port = htons(port);
01766 if (port == 0)
01767 ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr));
01768 else
01769 ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr), port);
01770 rtpdebug = 1;
01771 return RESULT_SUCCESS;
01772 }
01773
01774 static int rtp_do_debug(int fd, int argc, char *argv[])
01775 {
01776 if(argc != 2) {
01777 if(argc != 4)
01778 return RESULT_SHOWUSAGE;
01779 return rtp_do_debug_ip(fd, argc, argv);
01780 }
01781 rtpdebug = 1;
01782 memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
01783 ast_cli(fd, "RTP Debugging Enabled\n");
01784 return RESULT_SUCCESS;
01785 }
01786
01787 static int rtp_no_debug(int fd, int argc, char *argv[])
01788 {
01789 if(argc !=3)
01790 return RESULT_SHOWUSAGE;
01791 rtpdebug = 0;
01792 ast_cli(fd,"RTP Debugging Disabled\n");
01793 return RESULT_SUCCESS;
01794 }
01795
01796 static char debug_usage[] =
01797 "Usage: rtp debug [ip host[:port]]\n"
01798 " Enable dumping of all RTP packets to and from host.\n";
01799
01800 static char no_debug_usage[] =
01801 "Usage: rtp no debug\n"
01802 " Disable all RTP debugging\n";
01803
01804 static struct ast_cli_entry cli_debug_ip =
01805 {{ "rtp", "debug", "ip", NULL } , rtp_do_debug, "Enable RTP debugging on IP", debug_usage };
01806
01807 static struct ast_cli_entry cli_debug =
01808 {{ "rtp", "debug", NULL } , rtp_do_debug, "Enable RTP debugging", debug_usage };
01809
01810 static struct ast_cli_entry cli_no_debug =
01811 {{ "rtp", "no", "debug", NULL } , rtp_no_debug, "Disable RTP debugging", no_debug_usage };
01812
01813 void ast_rtp_reload(void)
01814 {
01815 struct ast_config *cfg;
01816 char *s;
01817
01818 rtpstart = 5000;
01819 rtpend = 31000;
01820 dtmftimeout = DEFAULT_DTMF_TIMEOUT;
01821 cfg = ast_config_load("rtp.conf");
01822 if (cfg) {
01823 if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01824 rtpstart = atoi(s);
01825 if (rtpstart < 1024)
01826 rtpstart = 1024;
01827 if (rtpstart > 65535)
01828 rtpstart = 65535;
01829 }
01830 if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01831 rtpend = atoi(s);
01832 if (rtpend < 1024)
01833 rtpend = 1024;
01834 if (rtpend > 65535)
01835 rtpend = 65535;
01836 }
01837 if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
01838 #ifdef SO_NO_CHECK
01839 if (ast_false(s))
01840 nochecksums = 1;
01841 else
01842 nochecksums = 0;
01843 #else
01844 if (ast_false(s))
01845 ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
01846 #endif
01847 }
01848 if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
01849 dtmftimeout = atoi(s);
01850 if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
01851 ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
01852 dtmftimeout, DEFAULT_DTMF_TIMEOUT);
01853 dtmftimeout = DEFAULT_DTMF_TIMEOUT;
01854 };
01855 }
01856 ast_config_destroy(cfg);
01857 }
01858 if (rtpstart >= rtpend) {
01859 ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
01860 rtpstart = 5000;
01861 rtpend = 31000;
01862 }
01863 if (option_verbose > 1)
01864 ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01865
01866 }
01867
01868
01869 void ast_rtp_init(void)
01870 {
01871 ast_cli_register(&cli_debug);
01872 ast_cli_register(&cli_debug_ip);
01873 ast_cli_register(&cli_no_debug);
01874 ast_rtp_reload();
01875 }