Commit 4b2cf2c1 authored by jehan's avatar jehan

add replaces header support

parent 8376572a
......@@ -99,7 +99,9 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sip_refresher_t),
BELLE_SIP_TYPE_ID(belle_sip_header_subscription_state_t),
BELLE_SIP_TYPE_ID(belle_sip_header_service_route_t),
BELLE_SIP_TYPE_ID(belle_sip_header_refer_to_t)
BELLE_SIP_TYPE_ID(belle_sip_header_refer_to_t),
BELLE_SIP_TYPE_ID(belle_sip_header_referred_by_t),
BELLE_SIP_TYPE_ID(belle_sip_header_replaces_t)
BELLE_SIP_DECLARE_TYPES_END
......
......@@ -524,5 +524,41 @@ void belle_sip_header_subscription_state_set_retry_after(belle_sip_header_subscr
#define BELLE_SIP_HEADER_REFER_TO(t) BELLE_SIP_CAST(t,belle_sip_header_refer_to_t)
#define BELLE_SIP_REFER_TO "Refer-To"
/******************************
* Referred-by header object inherent from header_address
*
******************************/
typedef struct _belle_sip_header_referred_by belle_sip_header_referred_by_t;
belle_sip_header_referred_by_t* belle_sip_header_referred_by_new();
BELLESIP_EXPORT belle_sip_header_referred_by_t* belle_sip_header_referred_by_parse(const char* referred_by) ;
BELLESIP_EXPORT belle_sip_header_referred_by_t* belle_sip_header_referred_by_create(const belle_sip_header_address_t *address);
#define BELLE_SIP_HEADER_REFERRED_BY(t) BELLE_SIP_CAST(t,belle_sip_header_referred_by_t)
#define BELLE_SIP_REFERRED_BY "Referred-By"
/******************************
* Replace header object inherent from parameters
*
******************************/
typedef struct _belle_sip_header_replaces belle_sip_header_replaces_t;
belle_sip_header_replaces_t* belle_sip_header_replaces_new();
BELLESIP_EXPORT belle_sip_header_replaces_t* belle_sip_header_replaces_parse(const char* replaces) ;
BELLESIP_EXPORT belle_sip_header_replaces_t* belle_sip_header_replaces_create(const char* call_id,const char* from_tag,const char* to_tag);
/*
* Creates a Eeplaces header from an escaped value that can be found in Referred-by header
* @param escaped_replace ex : 12345%40192.168.118.3%3Bto-tag%3D12345%3Bfrom-tag%3D5FFE-3994
* @return a newly allocated Replace header
* */
BELLESIP_EXPORT belle_sip_header_replaces_t* belle_sip_header_replaces_create2(const char* escaped_replace);
BELLESIP_EXPORT const char* belle_sip_header_replaces_get_call_id(const belle_sip_header_replaces_t* obj);
BELLESIP_EXPORT const char* belle_sip_header_replaces_get_from_tag(const belle_sip_header_replaces_t* obj);
BELLESIP_EXPORT const char* belle_sip_header_replaces_get_to_tag(const belle_sip_header_replaces_t* obj);
BELLESIP_EXPORT void belle_sip_header_replaces_set_call_id(belle_sip_header_replaces_t* obj, const char* callid);
BELLESIP_EXPORT void belle_sip_header_replaces_set_from_tag(belle_sip_header_replaces_t* obj,const char* from_tag);
BELLESIP_EXPORT void belle_sip_header_replaces_set_to_tag(belle_sip_header_replaces_t* obj,const char* to_tag);
#define BELLE_SIP_HEADER_REPLACES(t) BELLE_SIP_CAST(t,belle_sip_header_replaces_t)
#define BELLE_SIP_REPLACES "Replaces"
#endif /* HEADERS_H_ */
......@@ -1187,29 +1187,86 @@ belle_sip_header_subscription_state_t* belle_sip_header_subscription_state_creat
return sub_state;
}
#define HEADER_TO_LIKE_IMPL(name,header_name) \
struct _belle_sip_header_##name { \
belle_sip_header_address_t address; \
}; \
\
static void belle_sip_header_##name##_destroy(belle_sip_header_##name##_t * obj) { \
} \
void belle_sip_header_##name##_clone(belle_sip_header_##name##_t *contact, const belle_sip_header_##name##_t *orig){ }\
int belle_sip_header_##name##_marshal(belle_sip_header_##name##_t* name, char* buff,unsigned int offset,unsigned int buff_size) {\
BELLE_SIP_FROM_LIKE_MARSHAL(name)\
}\
BELLE_SIP_NEW_HEADER(header_##name,header_address,header_name)\
BELLE_SIP_PARSE(header_##name)\
belle_sip_header_##name##_t* belle_sip_header_##name##_create(const belle_sip_header_address_t* address) { \
belle_sip_header_##name##_t* header= belle_sip_header_##name##_new();\
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);\
belle_sip_header_set_name(BELLE_SIP_HEADER(header),header_name); \
return header;\
}
/**************************
* Refer-To header object inherits from header_address
****************************
*/
struct _belle_sip_header_refer_to {
belle_sip_header_address_t address;
HEADER_TO_LIKE_IMPL(refer_to,BELLE_SIP_REFER_TO)
/**************************
* Referred-By header object inherits from header_address
****************************
*/
HEADER_TO_LIKE_IMPL(referred_by,BELLE_SIP_REFERRED_BY)
/**************************
* Replaces state header object inherent from parameters
****************************
*/
struct _belle_sip_header_replaces {
belle_sip_parameters_t parameters;
const char* call_id;
};
static void belle_sip_header_refer_to_destroy(belle_sip_header_refer_to_t* refer_to) {
static void belle_sip_header_replaces_destroy(belle_sip_header_replaces_t* replaces) {
DESTROY_STRING(replaces,call_id);
}
void belle_sip_header_refer_to_clone(belle_sip_header_refer_to_t *contact, const belle_sip_header_refer_to_t *orig){
}
int belle_sip_header_refer_to_marshal(belle_sip_header_refer_to_t* refer_to, char* buff,unsigned int offset,unsigned int buff_size) {
BELLE_SIP_FROM_LIKE_MARSHAL(refer_to)
static void belle_sip_header_replaces_clone(belle_sip_header_replaces_t* replaces,
const belle_sip_header_replaces_t *orig ) {
CLONE_STRING(belle_sip_header_replaces,call_id,replaces,orig)
}
BELLE_SIP_NEW_HEADER(header_refer_to,header_address,BELLE_SIP_REFER_TO)
BELLE_SIP_PARSE(header_refer_to)
belle_sip_header_refer_to_t* belle_sip_header_refer_to_create(const belle_sip_header_address_t* address) {
belle_sip_header_refer_to_t* header= belle_sip_header_refer_to_new();
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_REFER_TO); /*restaure header name*/
return header;
int belle_sip_header_replaces_marshal(belle_sip_header_replaces_t* replaces, char* buff,unsigned int offset,unsigned int buff_size) {
unsigned int current_offset=offset;
current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(replaces), buff,current_offset, buff_size);
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",replaces->call_id);
current_offset+=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(replaces), buff,current_offset, buff_size);
return current_offset-offset;
}
BELLE_SIP_NEW_HEADER(header_replaces,parameters,BELLE_SIP_REPLACES)
BELLE_SIP_PARSE(header_replaces)
GET_SET_STRING(belle_sip_header_replaces,call_id);
GET_SET_STRING_PARAM2(belle_sip_header_replaces,to-tag,to_tag);
GET_SET_STRING_PARAM2(belle_sip_header_replaces,from-tag,from_tag);
static void escaped_to_ascii(const char*a,char*b,size_t n) {
size_t index_a=0,index_b=0;
while (a[index_a]!='\0'&& index_a<n)
index_a+=belle_sip_get_char(a+index_a,n-index_a,b+index_b++);
}
#define REPLACES_PREF_OFFSET 10
belle_sip_header_replaces_t* belle_sip_header_replaces_create2(const char* escaped_replace) {
belle_sip_header_replaces_t* replaces;
size_t len=strlen(escaped_replace);
char* out=belle_sip_malloc(REPLACES_PREF_OFFSET+len);
strcpy(out,BELLE_SIP_REPLACES ": ");
escaped_to_ascii(escaped_replace,out+REPLACES_PREF_OFFSET,len);
/*now we can parse*/
replaces= belle_sip_header_replaces_parse(out);
belle_sip_free(out);
return replaces;
}
......@@ -180,6 +180,8 @@ BELLE_SIP_DECLARE_VPTR(belle_sip_refresher_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_subscription_state_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_service_route_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_refer_to_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_referred_by_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_replaces_t);
typedef void (*belle_sip_source_remove_callback_t)(belle_sip_source_t *);
......@@ -821,6 +823,10 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
#endif
/*
* returns a char, even if entry is escaped*/
int belle_sip_get_char (const char*a,int n,char*out);
/*include private headers */
#include "belle_sip_resolver.h"
......
......@@ -399,7 +399,7 @@ call_id_token: {IS_TOKEN(Call-ID)}? token;
header_call_id returns [belle_sip_header_call_id_t* ret]
scope { belle_sip_header_call_id_t* current; }
@init {$header_call_id::current = belle_sip_header_call_id_new(); $ret=$header_call_id::current; }
: call_id_token /*( 'Call-ID' | 'i' )*/ hcolon call_id;
: call_id_token /*( 'Call-ID' | 'i' )*/ hcolon call_id{belle_sip_header_call_id_set_call_id($header_call_id::current,(const char*) $call_id.text->chars); };
catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
{
belle_sip_message("[\%s] reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
......@@ -407,7 +407,7 @@ catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
$ret=NULL;
}
call_id
: word ( '@' word )? {belle_sip_header_call_id_set_call_id($header_call_id::current,(const char*) $text->chars); };
: word ( '@' word )? ;
/*
call_info
: 'Call-Info' HCOLON info (COMMA info)*;
......@@ -975,21 +975,25 @@ to_param
refer_to_token: {IS_TOKEN(Refer-To)}? token;
header_refer_to returns [belle_sip_header_refer_to_t* ret]
scope { belle_sip_header_refer_to_t* current; }
@init { $header_refer_to::current = belle_sip_header_refer_to_new(); }
: refer_to_token /*'Refer-To'*/ hcolon refer_to_spec {$ret = $header_refer_to::current;};
: refer_to_token /*'Refer-To'*/
hcolon
refer_to_spec[BELLE_SIP_HEADER_ADDRESS(belle_sip_header_refer_to_new())] {$ret = BELLE_SIP_HEADER_REFER_TO($refer_to_spec.ret);};
referred_by_token: {IS_TOKEN(Referred-By)}? token;
header_referred_by returns [belle_sip_header_referred_by_t* ret]
: referred_by_token /*'Referred-By'*/
hcolon
refer_to_spec[BELLE_SIP_HEADER_ADDRESS(belle_sip_header_referred_by_new())] {$ret = BELLE_SIP_HEADER_REFERRED_BY($refer_to_spec.ret);};
refer_to_spec [belle_sip_header_address_t* address] returns [belle_sip_header_address_t* ret]
: (( name_addr[address] | paramless_addr_spec[address] ) ( semi generic_param [BELLE_SIP_PARAMETERS(address)] )* ){$ret=address;};
catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
{
belle_sip_message("[\%s] reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
belle_sip_object_unref($header_refer_to::current);
belle_sip_object_unref(address);
$ret=NULL;
}
refer_to_spec
: ( name_addr[BELLE_SIP_HEADER_ADDRESS($header_refer_to::current)] | paramless_addr_spec[BELLE_SIP_HEADER_ADDRESS($header_refer_to::current)] )
( semi refer_to_param )*;
refer_to_param
: /*tag_param |*/ generic_param [BELLE_SIP_PARAMETERS($header_refer_to::current)];
}
/*
unsupported
......@@ -1102,6 +1106,8 @@ catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
belle_sip_object_unref($header_www_authenticate::current);
$ret=NULL;
}
state_value: token ;
header_subscription_state returns [belle_sip_header_subscription_state_t* ret]
scope { belle_sip_header_subscription_state_t* current; }
@init { $header_subscription_state::current = belle_sip_header_subscription_state_new();$ret = $header_subscription_state::current; }
......@@ -1114,7 +1120,30 @@ catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
belle_sip_object_unref($header_subscription_state::current);
$ret=NULL;
}
state_value: token ;
/*
Replaces = "Replaces" HCOLON replaces-values
*(COMMA replaces-values)
replaces-values = callid *( SEMI replaces-param )
callid = token [ "@" token ]
replaces-param = to-tag | from-tag | extension-param
to-tag = "to-tag" EQUAL ( UUID | "*" )
from-tag = "from-tag" EQUAL UUID
extension-param = token [ EQUAL ( token | quoted-string ) ]
*/
header_replaces returns [belle_sip_header_replaces_t* ret]
scope { belle_sip_header_replaces_t* current; }
@init { $header_replaces::current = belle_sip_header_replaces_new();$ret = $header_replaces::current; }
: {IS_TOKEN(Replaces)}? token /*"Replaces"*/
hcolon call_id {belle_sip_header_replaces_set_call_id($header_replaces::current,(const char*)$call_id.text->chars);}
(semi generic_param [BELLE_SIP_PARAMETERS($header_replaces::current)])* ;
catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
{
belle_sip_message("[\%s] reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
belle_sip_object_unref($header_replaces::current);
$ret=NULL;
}
header_extension[ANTLR3_BOOLEAN check_for_known_header] returns [belle_sip_header_t* ret]
: header_name
......@@ -1161,6 +1190,10 @@ header_extension[ANTLR3_BOOLEAN check_for_known_header] returns [belle_sip_head
$ret = BELLE_SIP_HEADER(belle_sip_header_service_route_parse((const char*)$header_extension.text->chars));
}else if (check_for_known_header && strcasecmp(BELLE_SIP_REFER_TO,(const char*)$header_name.text->chars) == 0) {
$ret = BELLE_SIP_HEADER(belle_sip_header_refer_to_parse((const char*)$header_extension.text->chars));
}else if (check_for_known_header && strcasecmp(BELLE_SIP_REFERRED_BY,(const char*)$header_name.text->chars) == 0) {
$ret = BELLE_SIP_HEADER(belle_sip_header_referred_by_parse((const char*)$header_extension.text->chars));
}else if (check_for_known_header && strcasecmp(BELLE_SIP_REPLACES,(const char*)$header_name.text->chars) == 0) {
$ret = BELLE_SIP_HEADER(belle_sip_header_replaces_parse((const char*)$header_extension.text->chars));
}else {
$ret = BELLE_SIP_HEADER(belle_sip_header_extension_new());
belle_sip_header_extension_set_value((belle_sip_header_extension_t*)$ret,(const char*)$header_value.text->chars);
......
......@@ -164,21 +164,7 @@ SIP_URI_GET_SET_INT_PARAM(ttl)
SIP_URI_HAS_SET_BOOL_PARAM(lr)
static int get_char (char*a,int n,char*out) {
char result;
char tmp;
if (*a=='%' && n>2) {
tmp=a[3];
a[3]='\0';
*out=(char)((atoi(a+1)*16)/10); /*convert to hexa*/;
a[3]=tmp;
return 3;
} else {
*out=*a;
return 1;
}
return result;
}
static int uri_strncmp_common(const char*a,const char*b,size_t n,int case_sensitive) {
int result=0;
......@@ -186,8 +172,8 @@ static int uri_strncmp_common(const char*a,const char*b,size_t n,int case_sensit
char char_a,char_b;
while (a[index_a]!='\0'&&b[index_b]!='\0'&&index_a<n&&index_b<n) {
index_a+=get_char((char*)a+index_a,n-index_a,&char_a);
index_b+=get_char((char*)b+index_b,n-index_b,&char_b);
index_a+=belle_sip_get_char(a+index_a,n-index_a,&char_a);
index_b+=belle_sip_get_char(b+index_b,n-index_b,&char_b);
if (!case_sensitive && char_a<0x7B && char_a>0x60) char_a-=0x20;
if (!case_sensitive && char_b<0x7B && char_b>0x60) char_b-=0x20;
result+=(char_a!=char_b);
......
......@@ -652,3 +652,17 @@ void belle_sip_util_copy_headers(belle_sip_message_t *orig, belle_sip_message_t
}
}
int belle_sip_get_char (const char*a,int n,char*out) {
char result;
char tmp[3];
if (*a=='%' && n>2) {
memcpy(tmp,a+1,sizeof(tmp)-1);
tmp[sizeof(tmp)-1]='\0';
*out=(char)((atoi(tmp)*16)/10); /*convert to hexa*/;
return 3;
} else {
*out=*a;
return 1;
}
return result;
}
......@@ -575,6 +575,51 @@ void test_simple_header_refer_to(void) {
belle_sip_object_unref(L_refer_to);
}
void test_simple_header_referred_by(void) {
belle_sip_uri_t* L_uri;
belle_sip_header_referred_by_t* L_referred_by = belle_sip_header_referred_by_parse("Referred-By: sip:r@ref.example;cid=\"2UWQFN309shb3@ref.example\"");
char* l_raw_header = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_referred_by));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_referred_by));
L_referred_by = belle_sip_header_referred_by_parse(l_raw_header);
belle_sip_free(l_raw_header);
L_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(L_referred_by));
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_user(L_uri),"r");
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "ref.example");
belle_sip_object_unref(BELLE_SIP_OBJECT(L_referred_by));
}
void test_header_replaces(void) {
belle_sip_header_replaces_t* L_tmp;
belle_sip_header_replaces_t* L_replaces = belle_sip_header_replaces_parse("Replaces: 12345@149.112.118.3;to-tag=12345;from-tag=54321");
char* l_raw_header = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_replaces));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_replaces));
L_tmp= belle_sip_header_replaces_parse(l_raw_header);
L_replaces = BELLE_SIP_HEADER_REPLACES(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
belle_sip_free(l_raw_header);
CU_ASSERT_STRING_EQUAL(belle_sip_header_replaces_get_call_id(L_replaces), "12345@149.112.118.3");
CU_ASSERT_STRING_EQUAL(belle_sip_header_replaces_get_from_tag(L_replaces), "54321");
CU_ASSERT_STRING_EQUAL(belle_sip_header_replaces_get_to_tag(L_replaces), "12345");
belle_sip_object_unref(BELLE_SIP_OBJECT(L_replaces));
}
void test_header_replaces_escaped(void) {
/* belle_sip_header_replaces_t* L_tmp;
belle_sip_header_replaces_t* L_replaces = belle_sip_header_replaces_create2("12345%40192.168.118.3%3Bto-tag%3D12345%3Bfrom-tag%3D5FFE-3994");
char* l_raw_header = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_replaces));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_replaces));
L_tmp= belle_sip_header_replaces_parse(l_raw_header);
L_replaces = BELLE_SIP_HEADER_REPLACES(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
belle_sip_free(l_raw_header);
CU_ASSERT_STRING_EQUAL(belle_sip_header_replaces_get_call_id(L_replaces), "12345@192.168.118.3");
CU_ASSERT_STRING_EQUAL(belle_sip_header_replaces_get_from_tag(L_replaces), "5FFE-3994");
CU_ASSERT_STRING_EQUAL(belle_sip_header_replaces_get_to_tag(L_replaces), "12345");
belle_sip_object_unref(BELLE_SIP_OBJECT(L_replaces));*/
}
int belle_sip_headers_test_suite() {
......@@ -668,5 +713,11 @@ int belle_sip_headers_test_suite() {
if (NULL == CU_add_test(pSuite, "test_simple_header_refer_to",test_simple_header_refer_to )) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "test_simple_header_referred_by",test_simple_header_referred_by )) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "test_header_replaces_escaped",test_header_replaces_escaped )) {
return CU_get_error();
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment