Newer
Older
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Real-time Protocol Support
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <asterisk/rtp.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
James Golovich
committed
#include <asterisk/lock.h>
#define RTP_MTU 1200
#define TYPE_SILENCE 0x2
#define TYPE_DONTSEND 0x3
static int dtmftimeout = 3000; /* 3000 samples */
static int rtpstart = 0;
static int rtpend = 0;
// The value of each payload format mapping:
struct rtpPayloadType {
int isAstFormat; // whether the following code is an AST_FORMAT
int code;
};
#define MAX_RTP_PT 256
struct ast_rtp {
int s;
char resp;
struct ast_frame f;
unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
unsigned int ssrc;
unsigned int lastts;
unsigned int lastrxts;
unsigned int lastividtimestamp;
unsigned int lastovidtimestamp;
struct sockaddr_in us;
struct sockaddr_in them;
struct timeval rxcore;
struct timeval txcore;
int *ioid;
unsigned short seqno;
struct sched_context *sched;
struct io_context *io;
void *data;
ast_rtp_callback callback;
Mark Spencer
committed
struct rtpPayloadType current_RTP_PT[MAX_RTP_PT];
// a cache for the result of rtp_lookup_code():
int rtp_lookup_code_cache_isAstFormat;
int rtp_lookup_code_cache_code;
int rtp_lookup_code_cache_result;
struct ast_rtcp *rtcp;
};
struct ast_rtcp {
int s; /* Socket */
struct sockaddr_in us;
struct sockaddr_in them;
static struct ast_rtp_protocol *protos = NULL;
int ast_rtp_fd(struct ast_rtp *rtp)
{
return rtp->s;
}
int ast_rtcp_fd(struct ast_rtp *rtp)
{
if (rtp->rtcp)
return rtp->rtcp->s;
return -1;
}
static int g723_len(unsigned char buf)
{
switch(buf & TYPE_MASK) {
case TYPE_SILENCE:
return 4;
break;
case TYPE_HIGH:
return 24;
break;
case TYPE_LOW:
return 20;
break;
default:
ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
}
return -1;
}
static int g723_samples(unsigned char *buf, int maxlen)
{
int pos = 0;
int samples = 0;
int res;
while(pos < maxlen) {
res = g723_len(buf[pos]);
break;
samples += 240;
pos += res;
}
return samples;
}
void ast_rtp_set_data(struct ast_rtp *rtp, void *data)
{
rtp->data = data;
}
void ast_rtp_set_callback(struct ast_rtp *rtp, ast_rtp_callback callback)
{
rtp->callback = callback;
}
void ast_rtp_setnat(struct ast_rtp *rtp, int nat)
{
rtp->nat = nat;
}
static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
struct timeval tv;
static struct ast_frame null_frame = { AST_FRAME_NULL, };
gettimeofday(&tv, NULL);
if ((tv.tv_sec < rtp->dtmfmute.tv_sec) ||
((tv.tv_sec == rtp->dtmfmute.tv_sec) && (tv.tv_usec < rtp->dtmfmute.tv_usec))) {
ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", inet_ntoa(rtp->them.sin_addr));
rtp->resp = 0;
rtp->dtmfduration = 0;
return &null_frame;
}
ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, inet_ntoa(rtp->them.sin_addr));
rtp->f.frametype = AST_FRAME_DTMF;
rtp->f.subclass = rtp->resp;
rtp->f.datalen = 0;
rtp->f.mallocd = 0;
rtp->f.src = "RTP";
rtp->resp = 0;
static struct ast_frame *process_cisco_dtmf(struct ast_rtp *rtp, unsigned char *data, int len)
{
unsigned int event;
char resp = 0;
struct ast_frame *f = NULL;
event = ntohl(*((unsigned int *)(data)));
event &= 0x001F;
Loading
Loading full blame...