Version 0.1.11 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@425 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 24 years ago
parent 4b75f411fc
commit f62f33ce93

@ -42,6 +42,15 @@
#include "iax.h"
/*
* Uncomment to try experimental IAX bridge optimization,
* designed to reduce latency when IAX calls cannot
* be trasnferred
*/
#define BRIDGE_OPTIMIZATION
#define DEFAULT_RETRY_TIME 1000
#define MEMORY_SIZE 100
#define DEFAULT_DROP 3
@ -161,7 +170,10 @@ struct iax_peer {
char inkeys[80]; /* Key(s) this peer can use to authenticate to us */
int hascallerid;
/* Suggested caller id if registering */
char callerid[AST_MAX_EXTENSION];
/* Whether or not to send ANI */
int sendani;
int expire; /* Schedule entry for expirey */
int expirey; /* How soon to expire */
int capability; /* Capability */
@ -268,8 +280,10 @@ struct chan_iax_pvt {
char context[80];
/* Caller ID if available */
char callerid[80];
/* Hidden Caller ID if appropriate */
char hidden_callerid[80];
/* Hidden Caller ID (i.e. ANI) if appropriate */
char ani[80];
/* Whether or not ani should be transmitted in addition to Caller*ID */
int sendani;
/* DNID */
char dnid[80];
/* Requested Extension */
@ -519,8 +533,12 @@ static unsigned int calc_timestamp(struct chan_iax_pvt *p, unsigned int ts);
static int send_ping(void *data)
{
int callno = (long)data;
/* Ping only if it's real, not if it's bridged */
if (iaxs[callno]) {
send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_PING, 0, NULL, 0, -1);
#ifdef BRIDGE_OPTIMIZATION
if (iaxs[callno]->bridgecallno < 0)
#endif
send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_PING, 0, NULL, 0, -1);
return 1;
} else
return 0;
@ -529,8 +547,12 @@ static int send_ping(void *data)
static int send_lagrq(void *data)
{
int callno = (long)data;
/* Ping only if it's real not if it's bridged */
if (iaxs[callno]) {
send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
#ifdef BRIDGE_OPTIMIZATION
if (iaxs[callno]->bridgecallno < 0)
#endif
send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
return 1;
} else
return 0;
@ -734,7 +756,7 @@ static int find_callno(short callno, short dcallno ,struct sockaddr_in *sin, int
if ((res < 0) && (new >= NEW_ALLOW)) {
/* Create a new one */
start = nextcallno;
for (x = nextcallno + 1; iaxs[x] && (x != start); x = (x + 1) % AST_IAX_MAX_CALLS)
for (x = (nextcallno + 1) % AST_IAX_MAX_CALLS; iaxs[x] && (x != start); x = (x + 1) % AST_IAX_MAX_CALLS)
if (x == start) {
ast_log(LOG_WARNING, "Unable to accept more calls\n");
return -1;
@ -1106,6 +1128,22 @@ static struct ast_cli_entry cli_show_cache =
static unsigned int calc_rxstamp(struct chan_iax_pvt *p);
#ifdef BRIDGE_OPTIMIZATION
static unsigned int calc_fakestamp(struct chan_iax_pvt *from, struct chan_iax_pvt *to, unsigned int ts);
static int forward_delivery(struct ast_iax_frame *fr)
{
struct chan_iax_pvt *p1, *p2;
p1 = iaxs[fr->callno];
p2 = iaxs[p1->bridgecallno];
/* Fix relative timestamp */
fr->ts = calc_fakestamp(p1, p2, fr->ts);
/* Now just send it send on the 2nd one
with adjusted timestamp */
return iax_send(p2, fr->f, fr->ts, -1, 0, 0, 0);
}
#endif
static int schedule_delivery(struct ast_iax_frame *fr, int reallydeliver)
{
int ms,x;
@ -1114,6 +1152,7 @@ static int schedule_delivery(struct ast_iax_frame *fr, int reallydeliver)
/* ms is a measure of the "lateness" of the packet relative to the first
packet we received, which always has a lateness of 1. */
ms = calc_rxstamp(iaxs[fr->callno]) - fr->ts;
if (ms > 32768) {
/* What likely happened here is that our counter has circled but we haven't
gotten the update from the main packet. We'll just pretend that we did, and
@ -1292,11 +1331,13 @@ static int iax_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan
return 0;
}
static int create_addr(struct sockaddr_in *sin, int *capability, char *peer)
static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, char *peer)
{
struct hostent *hp;
struct iax_peer *p;
int found=0;
if (sendani)
*sendani = 0;
sin->sin_family = AF_INET;
ast_pthread_mutex_lock(&peerl.lock);
p = peerl.peers;
@ -1306,6 +1347,8 @@ static int create_addr(struct sockaddr_in *sin, int *capability, char *peer)
if (capability)
*capability = p->capability;
if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) {
if (sendani)
*sendani = p->sendani;
if (p->addr.sin_addr.s_addr) {
sin->sin_addr = p->addr.sin_addr;
sin->sin_port = p->addr.sin_port;
@ -1376,7 +1419,7 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
strtok(hname, ":");
portno = strtok(hname, ":");
}
if (create_addr(&sin, NULL, hname)) {
if (create_addr(&sin, NULL, NULL, hname)) {
ast_log(LOG_WARNING, "No address associated with '%s'\n", hname);
return -1;
}
@ -1389,6 +1432,8 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
MYSNPRINTF "exten=%s;", rdest);
if (c->callerid)
MYSNPRINTF "callerid=%s;", c->callerid);
if (p->sendani && c->ani)
MYSNPRINTF "ani=%s;", c->ani);
if (c->language && strlen(c->language))
MYSNPRINTF "language=%s;", c->language);
if (c->dnid)
@ -1548,8 +1593,11 @@ static int iax_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
cs[1] = c1;
for (/* ever */;;) {
/* Check in case we got masqueraded into */
if ((c0->type != type) || (c1->type != type))
if ((c0->type != type) || (c1->type != type)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
return -2;
}
if (!transferstarted) {
/* Try the transfer */
if (iax_start_transfer(c0, c1))
@ -1708,8 +1756,8 @@ static struct ast_channel *ast_iax_new(struct chan_iax_pvt *i, int state, int ca
tmp->pvt->bridge = iax_bridge;
if (strlen(i->callerid))
tmp->callerid = strdup(i->callerid);
if (strlen(i->hidden_callerid))
tmp->hidden_callerid = strdup(i->hidden_callerid);
if (strlen(i->ani))
tmp->ani = strdup(i->ani);
if (strlen(i->language))
strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
if (strlen(i->dnid))
@ -1758,13 +1806,42 @@ static unsigned int calc_timestamp(struct chan_iax_pvt *p, unsigned int ts)
return ms;
}
#ifdef BRIDGE_OPTIMIZATION
static unsigned int calc_fakestamp(struct chan_iax_pvt *p1, struct chan_iax_pvt *p2, unsigned int fakets)
{
int ms;
/* Receive from p1, send to p2 */
/* Setup rxcore if necessary on outgoing channel */
if (!p1->rxcore.tv_sec && !p1->rxcore.tv_usec)
gettimeofday(&p1->rxcore, NULL);
/* Setup txcore if necessary on outgoing channel */
if (!p2->offset.tv_sec && !p2->offset.tv_usec)
gettimeofday(&p2->offset, NULL);
/* Now, ts is the timestamp of the original packet in the orignal context.
Adding rxcore to it gives us when we would want the packet to be delivered normally.
Subtracting txcore of the outgoing channel gives us what we'd expect */
ms = (p1->rxcore.tv_sec - p2->offset.tv_sec) * 1000 + (p1->rxcore.tv_usec - p1->offset.tv_usec) / 1000;
fakets += ms;
if (fakets <= p2->lastsent)
fakets = p2->lastsent + 1;
p2->lastsent = fakets;
return fakets;
}
#endif
static unsigned int calc_rxstamp(struct chan_iax_pvt *p)
{
/* Returns where in "receive time" we are */
struct timeval tv;
unsigned int ms;
/* Setup rxcore if necessary */
if (!p->rxcore.tv_sec && !p->rxcore.tv_usec)
gettimeofday(&p->rxcore, NULL);
gettimeofday(&tv, NULL);
ms = (tv.tv_sec - p->rxcore.tv_sec) * 1000 + (tv.tv_usec - p->rxcore.tv_usec) / 1000;
return ms;
@ -2099,6 +2176,13 @@ static int send_command(struct chan_iax_pvt *i, char type, int command, unsigned
return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
}
#ifdef BRIDGE_OPTIMIZATION
static int forward_command(struct chan_iax_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
{
return __send_command(iaxs[i->bridgecallno], type, command, ts, data, datalen, seqno, 0, 0, 0);
}
#endif
static int send_command_final(struct chan_iax_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
{
iax_predestroy(i);
@ -2183,6 +2267,8 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
strncpy(iaxs[callno]->exten, value, sizeof(iaxs[callno]->exten)-1);
else if (!strcmp(var, "callerid"))
strncpy(iaxs[callno]->callerid, value, sizeof(iaxs[callno]->callerid)-1);
else if (!strcmp(var, "ani"))
strncpy(iaxs[callno]->ani, value, sizeof(iaxs[callno]->ani) - 1);
else if (!strcmp(var, "dnid"))
strncpy(iaxs[callno]->dnid, value, sizeof(iaxs[callno]->dnid)-1);
else if (!strcmp(var, "context"))
@ -2239,11 +2325,11 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
strncpy(iaxs[callno]->inkeys, user->inkeys, sizeof(iaxs[callno]->inkeys));
/* And the permitted authentication methods */
strncpy(iaxs[callno]->methods, user->methods, sizeof(iaxs[callno]->methods)-1);
/* If they have callerid, override the given caller id. Always store the hidden */
/* If they have callerid, override the given caller id. Always store the ANI */
if (strlen(iaxs[callno]->callerid)) {
if (user->hascallerid)
strncpy(iaxs[callno]->callerid, user->callerid, sizeof(iaxs[callno]->callerid)-1);
strncpy(iaxs[callno]->hidden_callerid, user->callerid, sizeof(iaxs[callno]->hidden_callerid)-1);
strncpy(iaxs[callno]->ani, user->callerid, sizeof(iaxs[callno]->ani)-1);
}
if (strlen(user->accountcode))
strncpy(iaxs[callno]->accountcode, user->accountcode, sizeof(iaxs[callno]->accountcode)-1);
@ -2332,7 +2418,7 @@ static int authenticate_verify(struct chan_iax_pvt *p, char *orequest)
res = 0;
break;
} else if (!key)
ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n");
ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
keyn = strtok(NULL, ":");
}
} else if (strstr(p->methods, "md5")) {
@ -3364,24 +3450,53 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
ast_pthread_mutex_unlock(&dpcache_lock);
break;
case AST_IAX_COMMAND_PING:
#ifdef BRIDGE_OPTIMIZATION
if (iaxs[fr.callno]->bridgecallno > -1) {
/* If we're in a bridged call, just forward this */
forward_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PING, fr.ts, NULL, 0, -1);
} else {
/* Send back a pong packet with the original timestamp */
send_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PONG, fr.ts, NULL, 0, -1);
}
#else
/* Send back a pong packet with the original timestamp */
send_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PONG, fr.ts, NULL, 0, -1);
#endif
break;
case AST_IAX_COMMAND_PONG:
#ifdef BRIDGE_OPTIMIZATION
if (iaxs[fr.callno]->bridgecallno > -1) {
/* Forward to the other side of the bridge */
forward_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PONG, fr.ts, NULL, 0, -1);
} else {
/* Calculate ping time */
iaxs[fr.callno]->pingtime = calc_timestamp(iaxs[fr.callno], 0) - fr.ts;
}
#else
/* Calculate ping time */
iaxs[fr.callno]->pingtime = calc_timestamp(iaxs[fr.callno], 0) - fr.ts;
#endif
break;
case AST_IAX_COMMAND_LAGRQ:
case AST_IAX_COMMAND_LAGRP:
/* A little strange -- We have to actually go through the motions of
delivering the packet. In the very last step, it will be properly
handled by do_deliver */
snprintf(src, sizeof(src), "LAGRQ-IAX/%s/%d", inet_ntoa(sin.sin_addr),fr.callno);
f.src = src;
f.mallocd = 0;
f.offset = 0;
fr.f = &f;
f.timelen = 0;
schedule_delivery(iaxfrdup2(&fr, 0), 1);
#ifdef BRIDGE_OPTIMIZATION
if (iaxs[fr.callno]->bridgecallno > -1) {
forward_command(iaxs[fr.callno], AST_FRAME_IAX, f.subclass, fr.ts, NULL, 0, -1);
} else {
#endif
/* A little strange -- We have to actually go through the motions of
delivering the packet. In the very last step, it will be properly
handled by do_deliver */
snprintf(src, sizeof(src), "LAGRQ-IAX/%s/%d", inet_ntoa(sin.sin_addr),fr.callno);
f.src = src;
f.mallocd = 0;
f.offset = 0;
fr.f = &f;
f.timelen = 0;
schedule_delivery(iaxfrdup2(&fr, 0), 1);
#ifdef BRIDGE_OPTIMIZATION
}
#endif
break;
case AST_IAX_COMMAND_AUTHREQ:
if (iaxs[fr.callno]->state & (IAX_STATE_STARTED | IAX_STATE_TBD)) {
@ -3632,7 +3747,15 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
ast_log(LOG_DEBUG, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr.ts, iaxs[fr.callno]->last);
fr.outoforder = -1;
}
#ifdef BRIDGE_OPTIMIZATION
if (iaxs[fr.callno]->bridgecallno > -1) {
forward_delivery(&fr);
} else {
schedule_delivery(iaxfrdup2(&fr, 0), 1);
}
#else
schedule_delivery(iaxfrdup2(&fr, 0), 1);
#endif
/* Always run again */
ast_pthread_mutex_unlock(&iaxs_lock);
return 1;
@ -3690,6 +3813,7 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
{
int callno;
int res;
int sendani;
int fmt, native;
struct sockaddr_in sin;
char s[256];
@ -3703,7 +3827,7 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
if (!st)
st = s;
/* Populate our address from the given */
if (create_addr(&sin, &capability, st)) {
if (create_addr(&sin, &capability, &sendani, st)) {
return NULL;
}
ast_pthread_mutex_lock(&iaxs_lock);
@ -3712,6 +3836,8 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
ast_log(LOG_WARNING, "Unable to create call\n");
return NULL;
}
/* Keep track of sendani flag */
iaxs[callno]->sendani = sendani;
c = ast_iax_new(iaxs[callno], AST_STATE_DOWN, capability);
if (c) {
/* Choose a format we can live with */
@ -3963,6 +4089,8 @@ static struct iax_peer *build_peer(char *name, struct ast_variable *v)
} else if (!strcasecmp(v->name, "callerid")) {
strncpy(peer->callerid, v->value, sizeof(peer->callerid)-1);
peer->hascallerid=1;
} else if (!strcasecmp(v->name, "sendani")) {
peer->sendani = ast_true(v->value);
} else if (!strcasecmp(v->name, "inkeys")) {
strncpy(peer->inkeys, v->value, sizeof(peer->inkeys));
} else if (!strcasecmp(v->name, "outkey")) {
@ -4293,7 +4421,7 @@ static int cache_get_callno(char *data)
host = st;
}
/* Populate our address from the given */
if (create_addr(&sin, NULL, host)) {
if (create_addr(&sin, NULL, NULL, host)) {
return -1;
}
ast_log(LOG_DEBUG, "host: %s, user: %s, password: %s, context: %s\n", host, username, password, context);

@ -588,6 +588,8 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
tmp->fds[0] = i->fd;
/* XXX Switching formats silently causes kernel panics XXX */
tmp->nativeformats = prefformat;
tmp->pvt->rawreadformat = prefformat;
tmp->pvt->rawwriteformat = prefformat;
tmp->state = state;
if (state == AST_STATE_RING)
tmp->rings = 1;
@ -911,7 +913,7 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
} else {
if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS))
ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
}
ioctl(tmp->fd, PHONE_PLAY_STOP);
ioctl(tmp->fd, PHONE_REC_STOP);
@ -1088,7 +1090,7 @@ int load_module()
ast_pthread_mutex_unlock(&iflock);
/* Make sure we can register our Adtranphone channel type */
if (ast_channel_register(type, tdesc,
AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, phone_request)) {
AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, phone_request)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
ast_destroy(cfg);
unload_module();

Loading…
Cancel
Save