From 3d91c0a0c01474336aba0342a3d10c301f19d93f Mon Sep 17 00:00:00 2001 From: Tilghman Lesher Date: Tue, 16 Jan 2007 08:38:59 +0000 Subject: IAX2 remote variables - Bug 7619 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@51123 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ channels/iax2-parser.c | 34 ++++++++++++++++++++++++++- channels/iax2-parser.h | 1 + channels/iax2.h | 1 + 4 files changed, 97 insertions(+), 1 deletion(-) 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()", + .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) -- cgit v1.2.3