[asterisk-bugs] [JIRA] (ASTERISK-29486) Hint-like extension value lookup function without device state

N A (JIRA) noreply at issues.asterisk.org
Tue Aug 3 14:51:34 CDT 2021


    [ https://issues.asterisk.org/jira/browse/ASTERISK-29486?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=255768#comment-255768 ] 

N A commented on ASTERISK-29486:
--------------------------------

That email was a bit of an early concept and the idea has morphed a bit since then.
The goal is not really set variables, it's to retrieve values, only - the same with DB gets a value from the DB, and you could save that in a variable. Generally, I don't save these in variables, since they're things I'll just look up once and I don't need again, so it can just be passed directly into the application - similar idea to DoSomething(${DB(something/something)}).

GoSub, in contrast, requires that variables are explicitly set, if you are using it to do more than one thing. This is because you can't just do all the lookups in the application itself, to get the value that you need. You need to call them one at a time, then save them temporarily while you do other lookups, then pass them all in at once. That's what the email example demonstrates.

The real point though, is that this function isn't another way of doing what Gosub does - Gosub by itself doesn't have any mechanism to retrieve the values this function does. It could be wrapped up in a Gosub, but the point is that it's able to return a value from the dialplan - similar to what HINT does, but without the device state overhead. Additionally, the value is variable-substituted, allowing for certain logic to be nested nicely. Here's an example:

Say that I want to get the extension length for dialing digits at some sort of prompt. Say in order to do that, I need to first get the customer group that the user belongs to. Perhaps that might look something like this:

[customer-groups]
exten => _55XXXXX,1,1
exten => _6[23]3NXXX,1,17
exten => _652[6-9]XXX,1,${EXTEN:-4:1}

[extension-lengths]
exten => _[12],1,5
exten => 3,1,3

[audio]
exten => _555XXXX,1,custom/default ; not user-changeable - static value for this range
exten => _4XXNXXX,1,${DB(usersettings/audio/${EXTEN})} ; we can call any function in a lookup, to return as a value, depending on the extension
exten => _63[14]XXXX,1,custom/companies/${EXTEN:-7:3}_main ; some variable manipulation
exten => _800XXXX,1,${LOOKUP(${EXTEN:-7:3}@nxx-greetings)} ; notice that this lookup calls another lookup, for this pattern match. This means one lookup could call another one, in dialplan execution, it "comes for free" because it's all evaluated at once for a single application call.

Now I can do:
same => n,Read(myvar,${LOOKUP(${CALLERID(num)}@audio)},${LOOKUP(${LOOKUP(${CALLERID(num)}@customer-groups)}@extension-lengths)})

In this example, we don't need to save the number of digits into a variable, we're just using it once, so we don't need to first save it and then use it. If this were a Gosub, it might look more like this:
same => n,Gosub(customer-groups,${CALLERID(num)},1)
same => n,Gosub(extension-lengths,${GOSUB_RETVAL},1)
same => n,Set(tmpvar=${GOSUB_RETVAL})
same => n,Gosub(audio,${CALLERID(num)},1)
same => n,Read(myvar,${GOSUB_RETVAL},${tmpvar})

This is a simple example with 3 *values* (not variables, per se). As the number of values increases, so does the complexity of trying to hijack Gosub for this purpose. You could write a subroutine to read digits with this data. That's not the goal of the function, which is to do a single thing and do it well, the value of which can be used for any purpose. I could make these same LOOKUP calls in 10 different places for different purposes. I don't need to write ten different subroutines to look up the same information. I just get what I need directly and provide it directly as an argument to whatever it is I'm invoking.
Additionally, Gosub can't return a dialplan value. It can Return(123), or Return(${DB(something/something)}), but it can't actually return the application value of an extension, which is kind of the main idea. For instance:

exten => 5,1,Progress(${DB_DELETE(something/${EXTEN})})
  same => n,Answer(${EXTEN})

Suppose that this was some kind of auto-generated dialplan, and you wanted to retrieve what was at that location - easy:
same => n,NoOp(${LOOKUP(default,5,1)} ${LOOKUP(default,5,2)})

== NoOp(Progress(87564375) Answer(5))

Currently, you can retrieve dialplan values using AMI. There is no way to do this from the dialplan itself though - apart from HINT, which sort of works, but has limitations. So this naturally compliments the DIALPLAN_EXISTS function, hence why DIALPLAN_VALUE could be an equivalently suitable name for this function.

The XML documentation might change. Right now, it's currently extension at context, but I may change that to extension at context,priority or context,extension,priority, so that the priority can be specified in a more elegant way. Initially, I didn't anticipate specifying the priority, but that would likely be something's that needed. I am open to changing the argument format around.

TL;DR -
- LOOKUP allows for retrieving extension values. There is no way to do this currently in the dialplan.
- LOOKUP naturally allows for convenient and compactly providing data to applications. This could be from DB, ODBC_FUNC, a static value, or any function. In such cases, extensions contain the desired dialplan functions and the variable parser takes care of everything. In your application, you don't need to care how the underlying data was retrieved - a single interface (the LOOKUP function) abstracts that away.

As an example of the latter, say that depending on the called number, I use a different API to get the caller ID information:

[caller-id]
exten => _212NXXXXXX,1,${CURL(https://new-york-city-cheap-caller-id.com/api/v1/${EXTEN})}
exten => _555NXXXXXX,1,${DB(cnam/${EXTEN:-5})} ; internal, check AstDB for these
exten => _NNXXXXXXX,1,${CURL(http://bulkcnam.com/${EXTEN})} ; use bulk CNAM for everything else
exten => 2124561414,1,WHITE HOUSE
exten => _NXX8675309,1,JENNY

This example makes it clear that LOOKUP is not replacing any of the other functions, e.g. DB. Rather, it complements them.

Now, all this logic is compactly in one place. You can thus do things like this:
same => n,Set(CALLERID(name)=${LOOKUP(${CALLERID(num)}@caller-id)})
or...
same => n,SayAlpha(${LOOKUP(${CALLERID(num)}@caller-id)})
or...
same => n,Dial(${LOOKUP(${EXTEN}@something)},${LOOKUP(${EXTEN}@ring-times)},m(${LOOKUP(${EXTEN}@music-on-hold-class)}f(${LOOKUP(${EXTEN}@ocd)})

Possibilities really are endless. There are many different directions this could be taken, all depending on what one does with it. LOOKUP itself is designed to be intentionally flexible for this.

> Hint-like extension value lookup function without device state
> --------------------------------------------------------------
>
>                 Key: ASTERISK-29486
>                 URL: https://issues.asterisk.org/jira/browse/ASTERISK-29486
>             Project: Asterisk
>          Issue Type: New Feature
>      Security Level: None
>          Components: Functions/NewFeature
>    Affects Versions: 18.4.0
>            Reporter: N A
>            Assignee: N A
>
> This is a new function that works like the HINT function, only a separate priority is used so that device state overhead is not added. This can provide a mechanism for a fast, efficient, and clean extension value lookup in the dialplan using native core extension pattern matching capabilities to retrieve extension values, including substituting variables.



--
This message was sent by Atlassian JIRA
(v6.2#6252)



More information about the asterisk-bugs mailing list