aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2007-01-16 08:38:59 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2007-01-16 08:38:59 +0000
commit4373b2af1324baceb226714e35640af07eedc5b9 (patch)
treed59470d07f7dce94e52073d498c2569145c29fa8
parent7106c73282ff24a165af4076b81401abb2bb46a7 (diff)
IAX2 remote variables - Bug 7619
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@51123 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_iax2.c62
-rw-r--r--channels/iax2-parser.c34
-rw-r--r--channels/iax2-parser.h1
-rw-r--r--channels/iax2.h1
4 files changed, 97 insertions, 1 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 2026f92e8..aa5c791b1 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -2884,6 +2884,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
struct parsed_dial_string pds;
struct create_addr_info cai;
+ struct ast_var_t *var;
if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name);
@@ -3007,6 +3008,19 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
/* send the command using the appropriate socket for this peer */
iaxs[callno]->sockfd = cai.sockfd;
+ /* Add remote vars */
+ AST_LIST_TRAVERSE(&c->varshead, var, entries) {
+ if (!strncmp(ast_var_name(var), "~IAX2~", strlen("~IAX2~"))) {
+ char tmp[256];
+ int i;
+ /* Automatically divide the value up into sized chunks */
+ for (i = 0; i < strlen(ast_var_value(var)); i += 255 - (strlen(ast_var_name(var)) - strlen("~IAX2~") + 1)) {
+ snprintf(tmp, sizeof(tmp), "%s=%s", ast_var_name(var) + strlen("~IAX2~"), ast_var_value(var) + i);
+ iax_ie_append_str(&ied, IAX_IE_VARIABLE, tmp);
+ }
+ }
+ }
+
/* Transmit the string in a "NEW" request */
send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
@@ -6447,6 +6461,33 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
return 1;
}
+static int acf_iaxvar_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+ const char *value;
+ char tmp[256];
+ snprintf(tmp, sizeof(tmp), "~IAX2~%s", data);
+ value = pbx_builtin_getvar_helper(chan, tmp);
+ ast_copy_string(buf, value ? value : "", len);
+ return 0;
+}
+
+static int acf_iaxvar_write(struct ast_channel *chan, const char *cmd, char *varname, const char *value)
+{
+ char tmp[256];
+ /* Inherit forever */
+ snprintf(tmp, sizeof(tmp), "__~IAX2~%s", varname);
+ pbx_builtin_setvar_helper(chan, tmp, value);
+ return 0;
+}
+
+static struct ast_custom_function iaxvar_function = {
+ .name = "IAXVAR",
+ .synopsis = "Sets or retrieves a remote variable",
+ .syntax = "IAXVAR(<varname>)",
+ .read = acf_iaxvar_read,
+ .write = acf_iaxvar_write,
+};
+
static int socket_process(struct iax2_thread *thread)
{
struct sockaddr_in sin;
@@ -6753,6 +6794,9 @@ retryowner:
} else {
if (option_debug)
ast_log(LOG_DEBUG, "Neat, somebody took away the channel at a magical time but i found it!\n");
+ /* Free remote variables (if any) */
+ if (ies.vars)
+ ast_variables_destroy(ies.vars);
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
@@ -6996,6 +7040,18 @@ retryowner:
if(!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format)))
iax2_destroy(fr->callno);
+ else if (ies.vars) {
+ struct ast_variable *var, *prev = NULL;
+ char tmp[256];
+ for (var = ies.vars; var; var = var->next) {
+ if (prev)
+ free(prev);
+ prev = var;
+ snprintf(tmp, sizeof(tmp), "__~IAX2~%s", var->name);
+ pbx_builtin_setvar_helper(c, tmp, var->value);
+ }
+ ies.vars = NULL;
+ }
} else {
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
/* If this is a TBD call, we're ready but now what... */
@@ -7586,6 +7642,10 @@ retryowner2:
iax_ie_append_byte(&ied0, IAX_IE_IAX_UNKNOWN, f.subclass);
send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_UNSUPPORT, 0, ied0.buf, ied0.pos, -1);
}
+ /* Free remote variables (if any) */
+ if (ies.vars)
+ ast_variables_destroy(ies.vars);
+
/* Don't actually pass these frames along */
if ((f.subclass != IAX_COMMAND_ACK) &&
(f.subclass != IAX_COMMAND_TXCNT) &&
@@ -10025,6 +10085,7 @@ static int __unload_module(void)
static int unload_module(void)
{
ast_custom_function_unregister(&iaxpeer_function);
+ ast_custom_function_unregister(&iaxvar_function);
return __unload_module();
}
@@ -10038,6 +10099,7 @@ static int load_module(void)
struct iax2_peer *peer = NULL;
ast_custom_function_register(&iaxpeer_function);
+ ast_custom_function_register(&iaxvar_function);
iax_set_output(iax_debug_output);
iax_set_error(iax_error_output);
diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c
index 1a5f4d9f8..5e76dd850 100644
--- a/channels/iax2-parser.c
+++ b/channels/iax2-parser.c
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/frame.h"
#include "asterisk/utils.h"
#include "asterisk/unaligned.h"
+#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/threadstorage.h"
@@ -262,6 +263,7 @@ static struct iax2_ie {
{ IAX_IE_RR_DELAY, "RR_DELAY", dump_short },
{ IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int },
{ IAX_IE_RR_OOO, "RR_OUTOFORDER", dump_int },
+ { IAX_IE_VARIABLE, "VARIABLE", dump_string },
};
static struct iax2_ie prov_ies[] = {
@@ -613,7 +615,8 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
/* Parse data into information elements */
int len;
int ie;
- char tmp[256];
+ char tmp[256], *tmp2;
+ struct ast_variable *var, *var2, *prev;
memset(ies, 0, (int)sizeof(struct iax_ies));
ies->msgcount = -1;
ies->firmwarever = -1;
@@ -898,6 +901,35 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
}
break;
+ case IAX_IE_VARIABLE:
+ ast_copy_string(tmp, (char *)data + 2, len + 1);
+ tmp2 = strchr(tmp, '=');
+ if (tmp2)
+ *tmp2++ = '\0';
+ else
+ tmp2 = "";
+ /* Existing variable or new variable? */
+ for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
+ if (strcmp(tmp, var2->name) == 0) {
+ int len = strlen(var2->value) + strlen(tmp2) + 1;
+ char *tmp3 = alloca(len);
+ snprintf(tmp3, len, "%s%s", var2->value, tmp2);
+ var = ast_variable_new(tmp, tmp3);
+ var->next = var2->next;
+ if (prev)
+ prev->next = var;
+ else
+ ies->vars = var;
+ free(var2);
+ break;
+ }
+ }
+ if (!var2) {
+ var = ast_variable_new(tmp, tmp2);
+ var->next = ies->vars;
+ ies->vars = var;
+ }
+ break;
default:
snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
outputf(tmp);
diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h
index 1b95d099f..35f8c69bd 100644
--- a/channels/iax2-parser.h
+++ b/channels/iax2-parser.h
@@ -73,6 +73,7 @@ struct iax_ies {
unsigned short rr_delay;
unsigned int rr_dropped;
unsigned int rr_ooo;
+ struct ast_variable *vars;
};
#define DIRECTION_INGRESS 1
diff --git a/channels/iax2.h b/channels/iax2.h
index 2b0c8bb99..084c4f201 100644
--- a/channels/iax2.h
+++ b/channels/iax2.h
@@ -128,6 +128,7 @@
#define IAX_IE_RR_DELAY 49 /* Max playout delay for received frames (in ms) u16 */
#define IAX_IE_RR_DROPPED 50 /* Dropped frames (presumably by jitterbuf) u32 */
#define IAX_IE_RR_OOO 51 /* Frames received Out of Order u32 */
+#define IAX_IE_VARIABLE 52 /* Remote variables */
#define IAX_AUTH_PLAINTEXT (1 << 0)