diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-04-20 21:12:53 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-04-20 21:12:53 +0000 |
commit | 8d14d2255818deacb493ff997938be8fa9786de6 (patch) | |
tree | d9a976f0c1e49c15f520493fa94cdd56b6ae937c /channels | |
parent | 59c77fe14b1b7a0a89147f7f82b58ab0265098f5 (diff) |
Merge changes from team/russell/iax2_osp
This set of changes adds OSP support to chan_iax2. However, I have modified
the patch a bit from what was submitted. You now use the CHANNEL() function
to get and set the OSP token for IAX2.
(issue #8531, reported by and original patch by homesick, patch updated by me)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@61702 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_iax2.c | 118 | ||||
-rw-r--r-- | channels/iax2-parser.c | 11 | ||||
-rw-r--r-- | channels/iax2-parser.h | 2 | ||||
-rw-r--r-- | channels/iax2.h | 5 |
4 files changed, 136 insertions, 0 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 88e1ae58a..d03aeb3e0 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -577,6 +577,8 @@ struct chan_iax2_pvt { AST_STRING_FIELD(accountcode); AST_STRING_FIELD(mohinterpret); AST_STRING_FIELD(mohsuggest); + /*! received OSP token */ + AST_STRING_FIELD(osptoken); ); /*! permitted authentication methods */ @@ -851,6 +853,9 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, static void destroy_user(struct iax2_user *user); static void prune_peers(void); +static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen); +static int acf_channel_write(struct ast_channel *chan, const char *function, char *data, const char *value); + static const struct ast_channel_tech iax2_tech = { .type = "IAX2", .description = tdesc, @@ -874,6 +879,8 @@ static const struct ast_channel_tech iax2_tech = { .bridge = iax2_bridge, .transfer = iax2_transfer, .fixup = iax2_fixup, + .func_channel_read = acf_channel_read, + .func_channel_write = acf_channel_write, }; static void insert_idle_thread(struct iax2_thread *thread) @@ -2890,6 +2897,11 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout) 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 +3022,25 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout) 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 = iaxs[callno]->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 +6347,36 @@ static void save_rr(struct iax_frame *fr, struct iax_ies *ies) 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 full_osptoken[IAX_MAX_OSPBUFF_SIZE]; + + 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(full_osptoken + offset, ies->osptokenblock[i], length); + offset += length; + } + } else { + break; + } + } + *(full_osptoken + offset) = '\0'; + if (strlen(full_osptoken) != offset) { + /* OSP token length wrong, clear buffer */ + *full_osptoken = '\0'; + } + + ast_string_field_set(iaxs[fr->callno], osptoken, full_osptoken); +} + static int socket_read(int *id, int fd, short events, void *cbdata) { struct iax2_thread *thread; @@ -6940,6 +7001,8 @@ retryowner: 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,6 +9887,61 @@ struct ast_custom_function iaxpeer_function = { "\n" }; +static int acf_channel_write(struct ast_channel *chan, const char *function, char *args, const char *value) +{ + struct chan_iax2_pvt *pvt; + unsigned int callno; + int res = 0; + + if (!chan || chan->tech != &iax2_tech) { + ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); + return -1; + } + + callno = PTR_TO_CALLNO(chan->tech_pvt); + ast_mutex_lock(&iaxsl[callno]); + if (!(pvt = iaxs[callno])) { + ast_mutex_unlock(&iaxsl[callno]); + return -1; + } + + if (!strcasecmp(args, "osptoken")) + ast_string_field_set(pvt, osptoken, value); + else + res = -1; + + ast_mutex_unlock(&iaxsl[callno]); + + return res; +} + +static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen) +{ + struct chan_iax2_pvt *pvt; + unsigned int callno; + int res = 0; + + if (!chan || chan->tech != &iax2_tech) { + ast_log(LOG_ERROR, "This function requires a valid IAX2 channel\n"); + return -1; + } + + callno = PTR_TO_CALLNO(chan->tech_pvt); + ast_mutex_lock(&iaxsl[callno]); + if (!(pvt = iaxs[callno])) { + ast_mutex_unlock(&iaxsl[callno]); + return -1; + } + + if (!strcasecmp(args, "osptoken")) + ast_copy_string(buf, pvt->osptoken, buflen); + else + res = -1; + + ast_mutex_unlock(&iaxsl[callno]); + + return res; +} /*! \brief Part of the device state notification system ---*/ static int iax2_devicestate(void *data) diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index c491f7a02..28bb07230 100644 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -264,6 +264,7 @@ static struct iax2_ie { { 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 iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) 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 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) 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); diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h index 35f8c69bd..076f7ca85 100644 --- a/channels/iax2-parser.h +++ b/channels/iax2-parser.h @@ -74,6 +74,8 @@ struct iax_ies { 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 diff --git a/channels/iax2.h b/channels/iax2.h index 084c4f201..4f6a19ea5 100644 --- a/channels/iax2.h +++ b/channels/iax2.h @@ -129,7 +129,12 @@ #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_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) |