Index: channels/iax2-parser.h =================================================================== --- channels/iax2-parser.h (revision 60397) +++ channels/iax2-parser.h (working copy) @@ -74,6 +74,8 @@ unsigned int rr_dropped; unsigned int rr_ooo; struct ast_variable *vars; + char* osptokenblock[IAX_MAX_OSPBLOCK_NUM]; + unsigned int ospblocklength[IAX_MAX_OSPBLOCK_NUM]; }; #define DIRECTION_INGRESS 1 Index: channels/chan_iax2.c =================================================================== --- channels/chan_iax2.c (revision 60397) +++ channels/chan_iax2.c (working copy) @@ -634,6 +634,9 @@ int frames_dropped; /*! received frame count: (just for stats) */ int frames_received; + + /*! received OSP token */ + char osptoken[IAX_MAX_OSPBUFF_SIZE]; }; static AST_LIST_HEAD_STATIC(queue, iax_frame); @@ -2890,6 +2893,11 @@ struct parsed_dial_string pds; struct create_addr_info cai; struct ast_var_t *var; + const char* osp_token_ptr; + unsigned int osp_token_length; + unsigned char osp_block_index; + unsigned int osp_block_length; + unsigned char osp_buffer[256]; if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "Channel is already in use (%s)?\n", c->name); @@ -3010,6 +3018,28 @@ iaxs[callno]->initid = ast_sched_add(sched, autokill * 2, auto_congest, CALLNO_TO_PTR(callno)); } + /* Check if there is an OSP token set by IAXCHANINFO function */ + osp_token_ptr = pbx_builtin_getvar_helper(c, "~IAX2~osptoken"); + if (!ast_strlen_zero(osp_token_ptr)) { + if ((osp_token_length = strlen(osp_token_ptr)) <= IAX_MAX_OSPTOKEN_SIZE) { + osp_block_index = 0; + while (osp_token_length > 0) { + osp_block_length = IAX_MAX_OSPBLOCK_SIZE < osp_token_length ? IAX_MAX_OSPBLOCK_SIZE : osp_token_length; + osp_buffer[0] = osp_block_index; + memcpy(osp_buffer + 1, osp_token_ptr, osp_block_length); + iax_ie_append_raw(&ied, IAX_IE_OSPTOKEN, osp_buffer, osp_block_length + 1); + osp_block_index++; + osp_token_ptr += osp_block_length; + osp_token_length -= osp_block_length; + } + } else { + ast_log(LOG_WARNING, "OSP token is too long\n"); + } + } else { + if (option_debug && iaxdebug) + ast_log(LOG_DEBUG, "OSP token is undefined\n"); + } + /* send the command using the appropriate socket for this peer */ iaxs[callno]->sockfd = cai.sockfd; @@ -6316,6 +6346,34 @@ iaxs[fr->callno]->remote_rr.ooo = ies->rr_ooo; } +static void save_osptoken(struct iax_frame *fr, struct iax_ies *ies) +{ + int i; + unsigned int length, offset = 0; + char* start = iaxs[fr->callno]->osptoken; + + for (i = 0; i < IAX_MAX_OSPBLOCK_NUM; i++) { + length = ies->ospblocklength[i]; + if (length != 0) { + if (length > IAX_MAX_OSPBLOCK_SIZE) { + /* OSP token block length wrong, clear buffer */ + offset = 0; + break; + } else { + memcpy(start + offset, ies->osptokenblock[i], length); + offset += length; + } + } else { + break; + } + } + *(start + offset) = '\0'; + if (strlen(start) != offset) { + /* OSP token length wrong, clear buffer */ + *start = '\0'; + } +} + static int socket_read(int *id, int fd, short events, void *cbdata) { struct iax2_thread *thread; @@ -6940,6 +6998,8 @@ ast_mutex_lock(&iaxsl[fr->callno]); } else exists = 0; + /* Get OSP token if it does exist */ + save_osptoken(fr, &ies); if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) { if (strcmp(iaxs[fr->callno]->exten, "TBD") && !exists) { memset(&ied0, 0, sizeof(ied0)); @@ -9824,7 +9884,70 @@ "\n" }; +/*! \brief ${IAXCHANINFO()} Dialplan function - reads iax channel data */ +static int function_iaxchaninfo_read(struct ast_channel *chan, const char *cmd, char *varname, char *buf, size_t len) +{ + unsigned short callno; + struct chan_iax2_pvt* pvt; + *buf = 0; + + if (!varname) { + ast_log(LOG_WARNING, "This function requires a parameter name.\n"); + return -1; + } + + ast_channel_lock(chan); + if (chan->tech != &iax2_tech) { + ast_log(LOG_WARNING, "This function can only be used on IAX channels.\n"); + ast_channel_unlock(chan); + return -1; + } + + callno = PTR_TO_CALLNO(chan->tech_pvt); + pvt = iaxs[callno]; + + if (!strcasecmp(varname, "osptoken")) { + ast_copy_string(buf, pvt->osptoken, len); + } else { + ast_channel_unlock(chan); + return -1; + } + ast_channel_unlock(chan); + + return 0; +} + +static int function_iaxchaninfo_write(struct ast_channel *chan, const char *cmd, char *varname, const char *value) +{ + char tmp[IAX_MAX_OSPBUFF_SIZE]; + + if (!varname) { + ast_log(LOG_WARNING, "This function requires a parameter name.\n"); + return -1; + } + + if (!strcasecmp(varname, "osptoken")) { + snprintf(tmp, sizeof(tmp), "_~IAX2~%s", varname); + pbx_builtin_setvar_helper(chan, tmp, value); + } else { + return -1; + } + + return 0; +} + +/*! \brief Structure to declare a dialplan function: IAXCHANINFO */ +static struct ast_custom_function iaxchaninfo_function = { + .name = "IAXCHANINFO", + .synopsis = "Get/set the specified IAX parameter for the current channel", + .syntax = "IAXCHANINFO(item)", + .read = function_iaxchaninfo_read, + .write = function_iaxchaninfo_write, + .desc = "Valid items are:\n" + "- osptoken The OSP token from the source or to the destination. Read and write.\n" +}; + /*! \brief Part of the device state notification system ---*/ static int iax2_devicestate(void *data) { @@ -10160,6 +10283,7 @@ static int unload_module(void) { + ast_custom_function_unregister(&iaxchaninfo_function); ast_custom_function_unregister(&iaxpeer_function); ast_custom_function_unregister(&iaxvar_function); return __unload_module(); @@ -10176,6 +10300,7 @@ ast_custom_function_register(&iaxpeer_function); ast_custom_function_register(&iaxvar_function); + ast_custom_function_register(&iaxchaninfo_function); iax_set_output(iax_debug_output); iax_set_error(iax_error_output); Index: channels/iax2.h =================================================================== --- channels/iax2.h (revision 60397) +++ channels/iax2.h (working copy) @@ -130,7 +130,13 @@ #define IAX_IE_RR_OOO 51 /* Frames received Out of Order u32 */ #define IAX_IE_VARIABLE 52 /* Remote variables */ +#define IAX_IE_OSPTOKEN 53 /* OSP token */ +#define IAX_MAX_OSPBLOCK_SIZE 254 /* Max OSP token block size, 255 bytes - 1 byte OSP token block index */ +#define IAX_MAX_OSPBLOCK_NUM 4 +#define IAX_MAX_OSPTOKEN_SIZE (IAX_MAX_OSPBLOCK_SIZE * IAX_MAX_OSPBLOCK_NUM) +#define IAX_MAX_OSPBUFF_SIZE (IAX_MAX_OSPTOKEN_SIZE + 16) + #define IAX_AUTH_PLAINTEXT (1 << 0) #define IAX_AUTH_MD5 (1 << 1) #define IAX_AUTH_RSA (1 << 2) Index: channels/iax2-parser.c =================================================================== --- channels/iax2-parser.c (revision 60397) +++ channels/iax2-parser.c (working copy) @@ -264,6 +264,7 @@ { IAX_IE_RR_DROPPED, "RR_DROPPED", dump_int }, { IAX_IE_RR_OOO, "RR_OUTOFORDER", dump_int }, { IAX_IE_VARIABLE, "VARIABLE", dump_string }, + { IAX_IE_OSPTOKEN, "OSPTOKEN" }, }; static struct iax2_ie prov_ies[] = { @@ -617,6 +618,7 @@ int ie; char tmp[256], *tmp2; struct ast_variable *var, *var2, *prev; + unsigned int count; memset(ies, 0, (int)sizeof(struct iax_ies)); ies->msgcount = -1; ies->firmwarever = -1; @@ -930,6 +932,15 @@ ies->vars = var; } break; + case IAX_IE_OSPTOKEN: + if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) { + ies->osptokenblock[count] = (char *)data + 2 + 1; + ies->ospblocklength[count] = len - 1; + } else { + snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %d\n", IAX_MAX_OSPBLOCK_NUM - 1, count); + errorf(tmp); + } + break; default: snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len); outputf(tmp);