Skip to content

Commit

Permalink
Add AutoFilter=unique option for better ActionID tracking (Steve Davies)
Browse files Browse the repository at this point in the history
Add more_events option for users to get more "noise" (Steve Davies)
  • Loading branch information
davies147 committed Nov 19, 2008
1 parent 13ba1af commit 55ceea9
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
OSARCH=$(shell uname -s)
OSREV=$(shell uname -r)

VERSION := 1.22pre081111
VERSION := 1.22pre081119
DESTDIR ?=
CONFDIR:=/etc/asterisk
CONFDIR_REAL := $(DESTDIR)/etc/asterisk
Expand Down
42 changes: 36 additions & 6 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ OutputFormat: (standard|xml)
Sets the output format on a per-client basis

ProxyAction: SetAutoFilter
AutoFilter: (on|off)
AutoFilter: (on|off|unique)
Sets the AutoFilter property on a per-client basis
(See autofiltering section below)

Expand Down Expand Up @@ -167,10 +167,10 @@ AstManProxy Autofiltering Functionality

One of the most powerful features of AstManProxy is its ability to
automatically filter output on a per-client basis. It can do this
with its Autofilter capability, which can be set 'on' in the config
file or enabled via the ProxyAction: SetAutoFilter function.
with its Autofilter capability, which can be set 'on'/'unique' in
the config file or enabled via the ProxyAction: SetAutoFilter function.

With autofiltering enabled, each client only receives output containing
With autofiltering 'on', each client only receives output containing
the "ActionID" parameter it has set most recently. This is useful
for single atomic requests into asterisk from a client, such as
when creating a simple UI to inject a command.
Expand All @@ -193,6 +193,32 @@ how this same mechanism can be used to quickly query asterisk
box(es), initiate calls, etc, without your client having to worry
with filtering a lot of unrelated output.

A more advanced verion of this facility is to set autofiltering to
'unique'. This causes astmanproxy to alter the ActionID on the way
to Asterisk, and undo that change on the way back.

For example the exchange:

> Action: Ping
> ActionID: foo
>

< Response: Pong
< ActionID: foo
<

Might be seen by Asterisk as:

> Action: Ping
> ActionID: amp7-foo
>

< Response: Pong
< ActionID: amp7-foo
<

and the "amp7-" prefix is created uniquely for each client connection.

===================================================================
On the astmanproxy.users output filtering functionality

Expand All @@ -216,10 +242,14 @@ force the Account: header to be overwritten for all commands to/from
this client. If the Action is "Originate", then a missing Account:
header will be added.

Lastly, a "server" header will cause the proxy to behave as if the
A "server" option will cause the proxy to behave as if the
client has included a "Server:" header in each request packet.

user=secret,channel,out_context (to Asterisk),in_context (From Asterisk),accountcode,server
Any non-empty string provided in "more_events" will allow the passing
of non-filterable events to all clients. The default behaviour is to
block these packets if any form of filtering is requested.

user=secret,channel,out_context (to Asterisk),in_context (From Asterisk),accountcode,server,more_events

e.g.:
steve=steve,SIP/snom190,local,
Expand Down
6 changes: 5 additions & 1 deletion VERSIONS
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
1.22fork2 - Refresh of GIT fork by Steve Davies
1.22pre081119 - Refresh of GIT fork by Steve Davies
Add AutoFilter=unique option for better ActionID tracking (Steve Davies)
Add more_events option for users to get more "noise" (Steve Davies)

1.22pre081111 - Refresh of GIT fork by Steve Davies
Segfault amd SIGPIPE fixes (Steve Davies)
Several fixes to UniqueID header tracking (Steve Davies)
Ensure that Response: headers are not filtered out. Assumes ActionID is sent (Steve Davies)
Expand Down
4 changes: 2 additions & 2 deletions configs/astmanproxy.users
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
; sending commands. It must be an exact match to the hostname/ip address
; in the .conf configuration file.
;
; user=secret,[channel],[out_context (to Asterisk)],[in_context (From Asterisk)],[accountcode],[server]
; user=secret,[channel],[out_context (to Asterisk)],[in_context (From Asterisk)],[accountcode],[server],[more_events]
;
; steve=steve,SIP/snom190,local,
; dave=securepass,SIP/1002,,,davesaccount
; dave=securepass,SIP/1002,,,davesaccount,,y
; bill=pass
37 changes: 29 additions & 8 deletions src/astmanproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,26 +197,33 @@ int WriteClients(struct message *m) {
// If VALRET > 1, then we may want to send a retrospective NewChannel before
// writing out this event...
// Send the retrospective Newchannel from the cache (m->session->cache) to this client (c)...
if( (valret & ATS_SRCUNIQUE) && m->session ) {
if( (valret & ATS_SRCUNIQUE) && m->session ) {
struct message m_temp;
memset(&m_temp, 0, sizeof(struct message) );
uniqueid = astman_get_header(m, "SrcUniqueID");
ResendFromStack(uniqueid, m->session, &m_temp);
m_temp.session = m->session;
c->output->write(c, &m_temp);
}
if( (valret & ATS_DSTUNIQUE) && m->session ) {
}
if( (valret & ATS_DSTUNIQUE) && m->session ) {
struct message m_temp;
memset(&m_temp, 0, sizeof(struct message) );
uniqueid = astman_get_header(m, "DestUniqueID");
ResendFromStack(uniqueid, m->session, &m_temp);
m_temp.session = m->session;
c->output->write(c, &m_temp);
}
}
if (c->autofilter && c->actionid) {
actionid = astman_get_header(m, ACTION_ID);
if ( !strcmp(actionid, c->actionid) )
if ( c->autofilter == 1 && !strcmp(actionid, c->actionid) )
// Original AutoFilter
c->output->write(c, m);
else if ( c->autofilter == 2 && !strncmp(actionid, c->actionid, strlen(c->actionid)) ) {
// New AutoFilter, actionid like "ast123-XX"
memmove( actionid, actionid+strlen(c->actionid), strlen(actionid)+1-strlen(c->actionid));
c->output->write(c, m);
} else if (debug > 5)
debugmsg("ActionID Filtered a message to a client\n");
} else
c->output->write(c, m);

Expand All @@ -225,7 +232,8 @@ int WriteClients(struct message *m) {
c->outputcomplete = 1;
pthread_mutex_unlock(&c->lock);
}
}
} else if ( !c->server && m->hdrcount>1 && !valret && debug > 5)
debugmsg("Validate Filtered a message to a client");
c = c->next;
}
if( !strcasecmp( event, "Hangup" ) ) {
Expand Down Expand Up @@ -285,7 +293,12 @@ int WriteAsterisk(struct message *m) {
void *setactionid(char *actionid, struct message *m, struct mansession *s)
{
pthread_mutex_lock(&s->lock);
strncpy(s->actionid, actionid, MAX_LEN);
if( s->autofilter < 2 ) { // Either save ActionID
strncpy(s->actionid, actionid, MAX_LEN);
} else if( strlen(s->actionid) + strlen(actionid) < MAX_LEN ) { // Or modify it
memmove(actionid+strlen(s->actionid), actionid, strlen(actionid)+strlen(s->actionid));
strncpy(actionid, s->actionid, strlen(s->actionid));
}
pthread_mutex_unlock(&s->lock);

return 0;
Expand All @@ -300,12 +313,20 @@ void *session_do(struct mansession *s)

if (s->input->onconnect)
s->input->onconnect(s, &m);
if (s->autofilter == 2) {
pthread_mutex_lock(&s->lock);
snprintf(s->actionid, MAX_LEN - 20, "amp%d-", s->fd);
if (debug > 3)
debugmsg("Setting actionID root to %s for new connection", s->actionid);
pthread_mutex_unlock(&s->lock);
}

// Signal settings are not always inherited by threads, so ensure we ignore this one
// as it is handled through error returns
(void) signal(SIGPIPE, SIG_IGN);
for (;;) {
/* Get a complete message block from input handler */
memset(&m, 0, sizeof(struct message) );
memset( &m, 0, sizeof(struct message) );
if (debug > 3)
debugmsg("calling %s_read...", s->input->formatname);
res = s->input->read(s, &m);
Expand Down
11 changes: 8 additions & 3 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,14 @@ void *processline(char *s) {
strcpy(pc.proc_group, value);
else if (!strcmp(name,"logfile") )
strcpy(pc.logfile, value);
else if (!strcmp(name,"autofilter") )
pc.autofilter = strcmp(value,"on") ? 0 : 1;
else if (!strcmp(name,"outputformat") )
else if (!strcmp(name,"autofilter") ) {
if( ! strcmp(value,"on") )
pc.autofilter = 1;
else if( ! strcmp(value,"unique") )
pc.autofilter = 2;
else
pc.autofilter = 0;
} else if (!strcmp(name,"outputformat") )
strcpy(pc.outputformat, value);
else if (!strcmp(name,"inputformat") )
strcpy(pc.inputformat, value);
Expand Down
7 changes: 5 additions & 2 deletions src/config_perms.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ void *add_userperm(char* username, char *userspec, struct proxy_user **pu) {
case 5:
strncat(user->server, s, 1);
break;
case 6:
user->more_events[0] = 'y'; // Any non-null entry
break;
}
} while (*(s++));

Expand All @@ -91,9 +94,9 @@ void *processperm(char *s, struct proxy_user **pu) {
nvstate = 1;
continue;
}
if (!nvstate) {
if (!nvstate)
strncat(name, s, 1);
} else
else
strncat(value, s, 1);
} while (*(s++));

Expand Down
1 change: 1 addition & 0 deletions src/include/astmanproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct proxy_user {
char ocontext[80];
char account[80];
char server[80];
char more_events[2];
struct proxy_user *next;
};

Expand Down
56 changes: 42 additions & 14 deletions src/proxyfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,16 @@ void *ProxySetAutoFilter(struct mansession *s, struct message *m) {
value = astman_get_header(m, "AutoFilter");
if ( !strcasecmp(value, "on") )
i = 1;
else if ( !strcasecmp(value, "unique") )
i = 2;
else
i = 0;
pthread_mutex_lock(&s->lock);
s->autofilter = i;
if( i == 2 )
snprintf(s->actionid, MAX_LEN - 20, "amp%d-", s->fd);
else
s->actionid[0] = '\0';
pthread_mutex_unlock(&s->lock);

memset(&mo, 0, sizeof(struct message));
Expand Down Expand Up @@ -167,7 +173,7 @@ void *ProxyLogin(struct mansession *s, struct message *m) {
pthread_mutex_lock(&userslock);
pu = pc.userlist;
while( pu ) {
if ( !strcmp(user, pu->username) ) {
if ( !strcmp(user, pu->username) ) {
if (!AuthMD5(key, s->challenge, pu->secret) || !strcmp(secret, pu->secret) ) {
AddHeader(&mo, "Response: Success");
AddHeader(&mo, "Message: Authentication accepted");
Expand All @@ -179,6 +185,7 @@ void *ProxyLogin(struct mansession *s, struct message *m) {
strcpy(s->user.ocontext, pu->ocontext);
strcpy(s->user.account, pu->account);
strcpy(s->user.server, pu->server);
strcpy(s->user.more_events, pu->more_events);
pthread_mutex_unlock(&s->lock);
if( debug )
debugmsg("Login as: %s", user);
Expand Down Expand Up @@ -351,7 +358,7 @@ int proxyerror_do(struct mansession *s, char *err)
}

/* [do_]AddToStack - Stores an event in a stack for later repetition.
indexted on UniqueID.
indexed on UniqueID.
If SrcUniqueID / DestUniqueID are present, store against both.
If a record already exists, do nothing.
withbody = 1, saves a copy of whole message (server).
Expand Down Expand Up @@ -420,25 +427,37 @@ int do_AddToStack(char *uniqueid, struct message *m, struct mansession *s, int w
pthread_mutex_unlock(&s->lock);
return 1;
}

int AddToStack(struct message *m, struct mansession *s, int withbody)
{
char *uniqueid;
int ret;
int ret, absent;

ret=0;
absent=0;

uniqueid = astman_get_header(m, "Uniqueid");
if( uniqueid[0] != '\0' )
if( uniqueid[0] != '\0' ) {
if( do_AddToStack(uniqueid, m, s, withbody) )
ret |= ATS_UNIQUE;
} else
absent++;

uniqueid = astman_get_header(m, "SrcUniqueID");
if( uniqueid[0] != '\0' )
if( uniqueid[0] != '\0' ) {
if( do_AddToStack(uniqueid, m, s, withbody) )
ret |= ATS_SRCUNIQUE;
} else
absent++;

uniqueid = astman_get_header(m, "DestUniqueID");
if( uniqueid[0] != '\0' )
if( uniqueid[0] != '\0' ) {
if( do_AddToStack(uniqueid, m, s, withbody) )
ret |= ATS_DSTUNIQUE;
} else
absent++;

if( s->user.more_events[0] != '\0' && absent == 3 )
return 1; // Want more/anonymous events
return ret;
}

Expand Down Expand Up @@ -494,14 +513,14 @@ void FreeStack(struct mansession *s)
if( t->message )
free( t->message );
free( t );
s->depth--;
t = n;
s->depth--;
}
s->stack = NULL;
if( debug && s->depth > 0 )
debugmsg("ALERT! Stack may have leaked %d slots!!!", s->depth);
if( debug )
debugmsg("Freed entire stack.");
s->stack = NULL;
pthread_mutex_unlock(&s->lock);
}

Expand Down Expand Up @@ -535,6 +554,7 @@ void ResendFromStack(char* uniqueid, struct mansession *s, struct message *m)

if( !m )
return;

if( debug )
debugmsg("ResendFromStack: %s", uniqueid);

Expand Down Expand Up @@ -621,9 +641,12 @@ int ValidateAction(struct message *m, struct mansession *s, int inbound) {
// we will return a response if the ActionID matches our last known ActionID
response = astman_get_header(m, "Response");
actionid = astman_get_header(m, ACTION_ID);
if( response[0] != '\0' && actionid[0] != '\0' && !strcmp(actionid, s->actionid) )
return 1;

if( response[0] != '\0' && actionid[0] != '\0' && !strcmp(actionid, s->actionid) ) {
if (s->autofilter < 2 && !strcmp(actionid, s->actionid))
return 1;
else if ( !strncmp(actionid, s->actionid, strlen(s->actionid)) )
return 1;
}

if( uchannel[0] != '\0' ) {
channel = astman_get_header(m, "Channel");
Expand Down Expand Up @@ -683,8 +706,13 @@ int ValidateAction(struct message *m, struct mansession *s, int inbound) {
}
}

if( inbound )
return AddToStack(m, s, 0);
if( inbound ) {
int res;
res = AddToStack(m, s, 0);
if( debug > 5 )
debugmsg("AddToStack returned %d", res);
return res;
}
return 1;
}

Expand Down

0 comments on commit 55ceea9

Please sign in to comment.