Hello,
I'm occasionally running into issues with inconsistent string interpolation in the kamailio.cfg.
Here's the latest example. Take this line:
$var(x) = "sip:+$var(abc)-$var(def)-$si@$Ri:$Rp";
Here, the values of the variables will NOT be interpolated into the string. Instead, I have to use this:
$var(x) = "sip:+" + $var(abc) + "-" + $var(def) + "-" + $si + "@" + $Ri + ":" + $Rp;
However, when I have an instruction such as:
append_hf("P-Asserted-Identity: $var(x)\r\n");
Then string interpolation takes place (i.e. the value of $var(x) is put into the string.
This is very confusing and error prone. Is it something that can be fixed? The behaviour should be consistent.
-Sven
Hello,
there are different actions, one is assignment of an expression and the other is a function call. Functions can evaluate they parameters as they need/want by having the appropriate C code inside.
For assignments, that is the general interpreter which considers strings as being the tokens in between quotes. Trying to interpret variables inside the strings automatically won't work, because that will mean to do it for cases when it should not happen (e.g., modparams or function parameters that specify just name of variables). Of course, with some extra coding to keep states of where that string is used might be possible, but I think will make the interpreter too complex. I might be wrong, so a patch is welcome to prove the otherwise :-)
Some functions can evaluate the parameter content, some don't. And in some cases, even there is a variable inside a parameter for a function, it is not evaluated, but it is set. That's again based on the purpose of the function.
Instead of concatenation expression, you can use few other options:
- $_s(...) -- iirc, like:
$var(x) = $_s("sip:+$var(abc)-$var(def)-$si@$Ri:$Rp");
- pv_printf($var(x), ...)
Cheers, Daniel On 01/10/15 11:56, Sven Neuhaus wrote:
Hello,
I'm occasionally running into issues with inconsistent string interpolation in the kamailio.cfg.
Here's the latest example. Take this line:
$var(x) = "sip:+$var(abc)-$var(def)-$si@$Ri:$Rp";
Here, the values of the variables will NOT be interpolated into the string. Instead, I have to use this:
$var(x) = "sip:+" + $var(abc) + "-" + $var(def) + "-" + $si + "@" + $Ri
- ":" + $Rp;
However, when I have an instruction such as:
append_hf("P-Asserted-Identity: $var(x)\r\n");
Then string interpolation takes place (i.e. the value of $var(x) is put into the string.
This is very confusing and error prone. Is it something that can be fixed? The behaviour should be consistent.
-Sven
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list sr-users@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
Am 01.10.2015 um 12:53 schrieb Daniel-Constantin Mierla:
there are different actions, one is assignment of an expression and the other is a function call. Functions can evaluate they parameters as they need/want by having the appropriate C code inside.
After I noticed the problem and tried to understand what was going on, that's what I came up with. That doesn't make it less error prone, however.
For assignments, that is the general interpreter which considers strings as being the tokens in between quotes. Trying to interpret variables inside the strings automatically won't work, because that will mean to do it for cases when it should not happen (e.g., modparams or function parameters that specify just name of variables). Of course, with some extra coding to keep states of where that string is used might be possible, but I think will make the interpreter too complex. I might be wrong, so a patch is welcome to prove the otherwise :-)
Ideally, all variables in double quoted strings should be interpolated and single quoted strings should not (the same way it is done in bash, Perl, PHP, Groove, Ruby and elsewhere).
Some functions can evaluate the parameter content, some don't. And in some cases, even there is a variable inside a parameter for a function, it is not evaluated, but it is set. That's again based on the purpose of the function.
That's frightening!
Instead of concatenation expression, you can use few other options:
- $_s(...) -- iirc, like:
That $_() is a useful thing to know.
$var(x) = $_s("sip:+$var(abc)-$var(def)-$si@$Ri:$Rp");
- pv_printf($var(x), ...)
I looked up the documentation for pv_printf() in the KEx module and was baffled to see the variable name being passed as a string in the example ... "pv_printf("$ru", "sip:$rU@$fd");" :-*
Cheers, -Sven
On 01/10/15 14:34, Sven Neuhaus wrote:
Am 01.10.2015 um 12:53 schrieb Daniel-Constantin Mierla:
there are different actions, one is assignment of an expression and the other is a function call. Functions can evaluate they parameters as they need/want by having the appropriate C code inside.
After I noticed the problem and tried to understand what was going on, that's what I came up with. That doesn't make it less error prone, however.
For assignments, that is the general interpreter which considers strings as being the tokens in between quotes. Trying to interpret variables inside the strings automatically won't work, because that will mean to do it for cases when it should not happen (e.g., modparams or function parameters that specify just name of variables). Of course, with some extra coding to keep states of where that string is used might be possible, but I think will make the interpreter too complex. I might be wrong, so a patch is welcome to prove the otherwise :-)
Ideally, all variables in double quoted strings should be interpolated and single quoted strings should not (the same way it is done in bash, Perl, PHP, Groove, Ruby and elsewhere).
In C is not :-) .
Some functions can evaluate the parameter content, some don't. And in some cases, even there is a variable inside a parameter for a function, it is not evaluated, but it is set. That's again based on the purpose of the function.
That's frightening!
Why? Do you know the purpose of parameters for C libc functions without fist looking at the manual? One needs to retrieve values, so instead of evaluating the value, is about setting the value.
Instead of concatenation expression, you can use few other options:
- $_s(...) -- iirc, like:
That $_() is a useful thing to know.
$var(x) = $_s("sip:+$var(abc)-$var(def)-$si@$Ri:$Rp");
- pv_printf($var(x), ...)
I looked up the documentation for pv_printf() in the KEx module and was baffled to see the variable name being passed as a string in the example ... "pv_printf("$ru", "sip:$rU@$fd");" :-*
That's pretty much from day 0 of sip express router back in 2001 -- the parameters of functions from modules had to be enclosed in double quotes, not matter what they are. There was no support for expressions as parameters for functions. Later there were some changes and some parameters can be without double quotes, but that is not the general rule -- if in double quotes, it should work always (for module functions).
Cheers, Daniel
Am 02.10.2015 um 08:38 schrieb Daniel-Constantin Mierla:
On 01/10/15 14:34, Sven Neuhaus wrote:
Am 01.10.2015 um 12:53 schrieb Daniel-Constantin Mierla:
For assignments, that is the general interpreter which considers strings as being the tokens in between quotes. Trying to interpret variables inside the strings automatically won't work, because that will mean to do it for cases when it should not happen (e.g., modparams or function parameters that specify just name of variables).
In those cases there should be a different syntax, such as single quoted strings or escaping the $ sign with a backslash or - if you prefer it the "C" way, the & "address of" operator - to make it clear a reference to a variable is passed and not its content.
Of course, with some extra coding to keep states of where that string is used might be possible, but I think will make the interpreter too complex. I might be wrong, so a patch is welcome to prove the otherwise :-)
Ideally, all variables in double quoted strings should be interpolated and single quoted strings should not (the same way it is done in bash, Perl, PHP, Groove, Ruby and elsewhere).
In C is not :-) .
But then again, in C the string interpolation is consistent. Removing it altogether and making $_() mandatory for string interpolation would avoid confusion.
Some functions can evaluate the parameter content, some don't. And in some cases, even there is a variable inside a parameter for a function, it is not evaluated, but it is set. That's again based on the purpose of the function.
That's frightening!
Why? Do you know the purpose of parameters for C libc functions without fist looking at the manual? One needs to retrieve values, so instead of evaluating the value, is about setting the value.
For starters, it would need to be in the documentation of every function, which it is not currently.
It's one thing to know what a function does and what its parameters are. It adds a whole level of complexity and source of errors having to look up which one of those parameters will be interpolated. That's why noone else is doing it that way.
- pv_printf($var(x), ...)
I looked up the documentation for pv_printf() in the KEx module and was baffled to see the variable name being passed as a string in the example ... "pv_printf("$ru", "sip:$rU@$fd");" :-*
That's pretty much from day 0 of sip express router back in 2001 -- the parameters of functions from modules had to be enclosed in double quotes, not matter what they are. There was no support for expressions as parameters for functions. Later there were some changes and some parameters can be without double quotes, but that is not the general rule -- if in double quotes, it should work always (for module functions).
Again, here we have the situation that there is a parameter to a function call where the first parameter is not interpolated and the second one is. That is not a good idea!
By the way: With the modparam() function the behaviour differs depending on the module that is being configured.
I think it would make Kamailio easier and less error prone to configure if the string interpolation behaviour were identical in all places.
Cheers, -Sven
On 02/10/15 11:00, Sven Neuhaus wrote:
Am 02.10.2015 um 08:38 schrieb Daniel-Constantin Mierla:
On 01/10/15 14:34, Sven Neuhaus wrote:
Am 01.10.2015 um 12:53 schrieb Daniel-Constantin Mierla:
For assignments, that is the general interpreter which considers strings as being the tokens in between quotes. Trying to interpret variables inside the strings automatically won't work, because that will mean to do it for cases when it should not happen (e.g., modparams or function parameters that specify just name of variables).
In those cases there should be a different syntax, such as single quoted strings or escaping the $ sign with a backslash or - if you prefer it the "C" way, the & "address of" operator - to make it clear a reference to a variable is passed and not its content.
Of course, with some extra coding to keep states of where that string is used might be possible, but I think will make the interpreter too complex. I might be wrong, so a patch is welcome to prove the otherwise :-)
Ideally, all variables in double quoted strings should be interpolated and single quoted strings should not (the same way it is done in bash, Perl, PHP, Groove, Ruby and elsewhere).
In C is not :-) .
But then again, in C the string interpolation is consistent. Removing it altogether and making $_() mandatory for string interpolation would avoid confusion.
What I wanted to say is that in C is up to me to interpret as function developer, for example:
int i = 0; void myprint(char *v) {
if(strcpy(v, "i")==0) { printf("%d", i); } else { # error - unknown global variable } }
or:
void myprint(char *v) { printf("%s", v); }
Then use: myprint("i");
Now, would you like the ccompiler to expand i inside the parameter?
All PVs in kamailio are global variables. Now it is up to myprint() developer to do what he needs with that parameter.
Some functions can evaluate the parameter content, some don't. And in some cases, even there is a variable inside a parameter for a function, it is not evaluated, but it is set. That's again based on the purpose of the function.
That's frightening!
Why? Do you know the purpose of parameters for C libc functions without fist looking at the manual? One needs to retrieve values, so instead of evaluating the value, is about setting the value.
For starters, it would need to be in the documentation of every function, which it is not currently.
All functions for modules are documented in the readme of the module, if you find one which is not, then it is considered a bug and should be fixed quickly. You can see all those functions indexed by name at:
http://www.kamailio.org/wiki/alphaindexes/4.3.x/modfunctions
It's one thing to know what a function does and what its parameters are. It adds a whole level of complexity and source of errors having to look up which one of those parameters will be interpolated. That's why noone else is doing it that way.
Well, in C a parameter can be pointer and can be used for input (read) of output (write).
The & (reference) and * (pointer) operators in C are not for saying it is a parameter for write or read. Practically behind each PV is a pointer in the C code, because we cannot any longer declare a non-pointer variable from kamailio.cfg back to c code (which is already compiled at the time kamailio.cfg is loaded).
- pv_printf($var(x), ...)
I looked up the documentation for pv_printf() in the KEx module and was baffled to see the variable name being passed as a string in the example ... "pv_printf("$ru", "sip:$rU@$fd");" :-*
That's pretty much from day 0 of sip express router back in 2001 -- the parameters of functions from modules had to be enclosed in double quotes, not matter what they are. There was no support for expressions as parameters for functions. Later there were some changes and some parameters can be without double quotes, but that is not the general rule -- if in double quotes, it should work always (for module functions).
Again, here we have the situation that there is a parameter to a function call where the first parameter is not interpolated and the second one is. That is not a good idea!
By the way: With the modparam() function the behaviour differs depending on the module that is being configured.
I think it would make Kamailio easier and less error prone to configure if the string interpolation behaviour were identical in all places.
I am open to discuss and even help evolving the interpreter to be more friendly. But for this specific case I don't really see your point.
And documentation for all those functions is there, prove a missing one and will be fixed as said above. Even if there would be '&' or '*', you have to read the docs to see what that function does, how many parameters and what those parameters should be.
Start a wiki page on kamailio.org/wiki/ in the development section collecting what you would like to have, then email to sr-dev to get input from other developers interested in the topic.
Cheers, Daniel
Am 02.10.2015 um 11:51 schrieb Daniel-Constantin Mierla:
On 02/10/15 11:00, Sven Neuhaus wrote:
Am 02.10.2015 um 08:38 schrieb Daniel-Constantin Mierla:
On 01/10/15 14:34, Sven Neuhaus wrote:
Ideally, all variables in double quoted strings should be interpolated and single quoted strings should not (the same way it is done in bash, Perl, PHP, Groove, Ruby and elsewhere).
In C is not :-) .
But then again, in C the string interpolation is consistent. Removing it altogether and making $_() mandatory for string interpolation would avoid confusion.
What I wanted to say is that in C is up to me to interpret as function developer, for example:
int i = 0; void myprint(char *v) {
if(strcpy(v, "i")==0) { printf("%d", i); } else { # error - unknown global variable } }
or:
void myprint(char *v) { printf("%s", v); }
Then use: myprint("i");
Now, would you like the ccompiler to expand i inside the parameter?
All PVs in kamailio are global variables. Now it is up to myprint() developer to do what he needs with that parameter.
There is no way (that I know of) to access a variable by its name in C, i.e. converting a string that contains a variable name back into a reference to the actual variable. Your example has a hard-coded variable name "i" to make it work. There are some script languages that will allow you to get access to a variable if you only know its name (some do it with tricks such as eval() or reflection in Java). I consider passing a reference to a variable by using a string with its name to be ambiguous and error-prone.
Some functions can evaluate the parameter content, some don't. And in some cases, even there is a variable inside a parameter for a function, it is not evaluated, but it is set. That's again based on the purpose of the function.
That's frightening!
Why? Do you know the purpose of parameters for C libc functions without first looking at the manual? One needs to retrieve values, so instead of evaluating the value, is about setting the value.
For starters, it would need to be in the documentation of every function, which it is not currently.
All functions for modules are documented in the readme of the module, if you find one which is not, then it is considered a bug and should be fixed quickly. You can see all those functions indexed by name at:
http://www.kamailio.org/wiki/alphaindexes/4.3.x/modfunctions
The functions are documented of course, however it isn't clearly stated how its strings are interpreted. Sometimes it can be guessed but it's open to interpretation.
A random example is the function ds_list_exist(groupid) from the dispatcher module. If I pass a variable in a string to this function, will it retrieve the value of the variable or will it try to interpret the variable name as a groupid? I have no idea. If I pass a variable without quotes, I hope it will get interpolated.
It's one thing to know what a function does and what its parameters are. It adds a whole level of complexity and source of errors having to look up which one of those parameters will be interpolated. That's why no-one else is doing it that way.
Well, in C a parameter can be pointer and can be used for input (read) of output (write).
The & (reference) and * (pointer) operators in C are not for saying it is a parameter for write or read. Practically behind each PV is a pointer in the C code, because we cannot any longer declare a non-pointer variable from kamailio.cfg back to c code (which is already compiled at the time kamailio.cfg is loaded).
I'm not sure I fully understand what you are getting at here.
- pv_printf($var(x), ...)
I looked up the documentation for pv_printf() in the KEx module and was baffled to see the variable name being passed as a string in the example ... "pv_printf("$ru", "sip:$rU@$fd");" :-*
That's pretty much from day 0 of sip express router back in 2001 -- the parameters of functions from modules had to be enclosed in double quotes, not matter what they are. There was no support for expressions as parameters for functions. Later there were some changes and some parameters can be without double quotes, but that is not the general rule -- if in double quotes, it should work always (for module functions).
Again, here we have the situation that there is a parameter to a function call where the first parameter is not interpolated and the second one is. That is not a good idea!
By the way: With the modparam() function the behaviour differs depending on the module that is being configured.
I think it would make Kamailio easier and less error prone to configure if the string interpolation behaviour were identical in all places.
I am open to discuss and even help evolving the interpreter to be more friendly. But for this specific case I don't really see your point.
And documentation for all those functions is there, prove a missing one and will be fixed as said above.
There's $sht() that explicitly states that the key can be static or dynamic. What happens if the string contains something like $xyz and there is no such variable? Will it then use the string verbatim? That doesn't seem like a good idea.
Start a wiki page on kamailio.org/wiki/ in the development section collecting what you would like to have, then email to sr-dev to get input from other developers interested in the topic.
OK I'll try to think this through once I am finished with the current project at work.
Have a nice weekend! -Sven