Hmmm [UPDATE]
Well, this updated version actually works with optimization turned on, doesn’t use custom structs for passing data.
It’s now using the sofia-sip way of passing type and value in multiple arguments, this one is still a simplified version though…
There’s some additional code for passing uri parameters each in a single tag now too.
Download: Tag based SIP URI generator example code #2
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
typedef int switch_core_session_t;
char * sofia_printf_uri( switch_core_session_t *session, ... );
typedef enum {
URI_TAG_TYPE_USERNAME = 1,
URI_TAG_TYPE_DESTINATION,
URI_TAG_TYPE_HOST,
URI_TAG_TYPE_PORT,
URI_TAG_TYPE_PARAMETER,
URI_TAG_TYPE_PARAMETER_LIST,
URI_TAG_TYPE_URIONLY
} uri_tag_type;
#define URI_TAG_USERNAME(x) URI_TAG_TYPE_USERNAME, (x)
#define URI_TAG_DESTINATION(x) URI_TAG_TYPE_DESTINATION, (x)
#define URI_TAG_HOST(x) URI_TAG_TYPE_HOST, (x)
#define URI_TAG_PARAMETER(n, v) URI_TAG_TYPE_PARAMETER, (n), (v)
#define URI_TAG_PARAMETER_LIST(x) URI_TAG_TYPE_PARAMETER_LIST, (x)
#define URI_TAG_PORT(x) URI_TAG_TYPE_PORT, (x)
#define URI_TAG_URI_ONLY(x) URI_TAG_TYPE_URIONLY, (x)
#define TAG_END NULL
#define URI_MAX_PARAMS 10
char * sofia_printf_uri( switch_core_session_t *session, ... )
{
va_list ap;
char *username = NULL,
*destination = NULL,
*host = NULL,
*param_str = NULL,
*uri_str = NULL;
struct { char *name, *val; } param[URI_MAX_PARAMS];
int tag, port = 0, uri_only = 0, num_params = 0, len_params = 0;
va_start( ap, session );
while( 1 ) {
tag = va_arg( ap, int );
if( !tag )
break;
switch( tag ) {
case URI_TAG_TYPE_USERNAME:
username = va_arg( ap, char * );
break;
case URI_TAG_TYPE_DESTINATION:
destination = va_arg( ap, char * );
break;
case URI_TAG_TYPE_HOST:
host = va_arg( ap, char * );
break;
case URI_TAG_TYPE_PARAMETER:
param[num_params].name = va_arg( ap, char * );
param[num_params].val = va_arg( ap, char * );
len_params += strlen(param[num_params].name) + strlen(param[num_params].val);
num_params++;
break;
case URI_TAG_TYPE_PARAMETER_LIST:
param_str = va_arg( ap, char * );
num_params = -1;
break;
case URI_TAG_TYPE_PORT:
port = va_arg( ap, int );
break;
case URI_TAG_TYPE_URIONLY:
uri_only = va_arg( ap, int );
break;
default:
printf( "Unknown tag type\n" );
}
}
va_end( ap );
/*
* We need at least host and destination here
*/
if( !host ) {
printf( "no host tag specified\n" );
return NULL;
}
if( !destination ) {
printf( "no destination tag specified\n" );
return NULL;
}
/*
* Default value
*/
if( !username )
username = "user";
/*
* Ugly code ahead...
* Now if we'd manually allocate memory here we could count string lengths
* and reserve enough room for the uri incl. parameters in one go and
* put the params in after snprint'ing the first part...
* (saving us the trouble of using alloca here)
*/
if( num_params > 0 ) {
int n, len;
char *p;
param_str = alloca( len_params + num_params );
if( !param_str )
return NULL;
p = param_str;
for( n=0; n < num_params; n++ ) {
len = strlen( param[n].name );
memcpy( p, param[n].name, len );
p += len;
*p++ = '=';
len = strlen( param[n].val );
memcpy( p, param[n].val, len );
p += len;
if( n < num_params - 1 )
*p++ = '&';
}
*p = '\0';
} else if( num_params == 0 ) {
param_str = "";
}
/*
* The (fugly) output part
*/
if( !uri_only ) {
if( port ) {
printf( "\"%s\" <sip:%s@%s:%d>%s%s\n",
username,
destination,
host,
port,
num_params ? ";" : "",
param_str );
} else {
printf( "\"%s\" <sip:%s@%s>%s%s\n",
username,
destination,
host,
num_params ? ";" : "",
param_str );
}
} else {
if( port ) {
printf( "sip:%s@%s:%d%s%s\n",
destination,
host,
port,
num_params ? ";" : "",
param_str );
} else {
printf( "sip:%s@%s%s%s\n",
destination,
host,
num_params ? ";" : "",
param_str );
}
}
return uri_str;
}
int main( void )
{
switch_core_session_t session;
printf( "\nCreating full uri...\n" );
sofia_printf_uri( &session,
URI_TAG_USERNAME( "foobar" ),
URI_TAG_HOST( "konata" ),
URI_TAG_PORT( 1234 ),
URI_TAG_DESTINATION( "myext" ),
URI_TAG_PARAMETER( "transport", "tls" ),
URI_TAG_PARAMETER( "rport", "12345" ),
TAG_END );
printf( "\nCreating uri only (output w/o username)...\n" );
sofia_printf_uri( &session,
URI_TAG_USERNAME( "foobar" ),
URI_TAG_HOST( "konata" ),
URI_TAG_PORT( 1234 ),
URI_TAG_DESTINATION( "myext" ),
URI_TAG_URI_ONLY( 1 ),
URI_TAG_PARAMETER( "transport", "tls" ),
TAG_END );
printf( "\nCreating full uri w/o port...\n" );
sofia_printf_uri( &session,
URI_TAG_USERNAME( "foobar" ),
URI_TAG_HOST( "konata" ),
URI_TAG_DESTINATION( "myext" ),
URI_TAG_PARAMETER_LIST( "transport=tls;bla=foo" ),
TAG_END );
return 0;
}