summaryrefslogtreecommitdiff
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c62
1 files changed, 62 insertions, 0 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);