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