Commit 6b41cfa0 authored by jehan's avatar jehan

add header Subscription state

fix refresher
parent 73acfcd2
......@@ -17,6 +17,7 @@ bellesip_HEADERS=\
utils.h \
auth-helper.h \
belle-sdp.h \
belle-sip.h
belle-sip.h \
refresher-helper.h
EXTRA_DIST=$(bellesip_HEADERS)
......@@ -104,6 +104,7 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sdp_mime_parameter_t),
BELLE_SIP_TYPE_ID(belle_sip_callbacks_t),
BELLE_SIP_TYPE_ID(belle_sip_refresher_t),
BELLE_SIP_TYPE_ID(belle_sip_header_subscription_state_t),
BELLE_SIP_DECLARE_TYPES_END
......
......@@ -36,6 +36,13 @@ const char* belle_sip_dialog_state_to_string(const belle_sip_dialog_state_t stat
belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *dialog, unsigned int cseq);
belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *dialog, const char *method);
/**
* Create a request within a dialog keeping non system header from an initial request. This function is very usefull to resend request after expiration or chalange.
* @param obj dialog associated to the request
* @param initial_req, all headers + body are re-used from this request except: Via,From, To, Allows, CSeq, Call-ID, Max-Forwards
*
*/
belle_sip_request_t * belle_sip_dialog_create_request_from(belle_sip_dialog_t *obj, const belle_sip_request_t *initial_req);
void belle_sip_dialog_delete(belle_sip_dialog_t *dialog);
......
......@@ -92,6 +92,7 @@ belle_sip_header_allow_t* belle_sip_header_allow_create (const char* methods) ;
const char* belle_sip_header_allow_get_method(const belle_sip_header_allow_t* allow);
void belle_sip_header_allow_set_method(belle_sip_header_allow_t* allow,const char* method);
#define BELLE_SIP_HEADER_ALLOW(t) BELLE_SIP_CAST(t,belle_sip_header_allow_t)
#define BELLE_SIP_ALLOW "Allow"
/***********************
* Contact header object
......@@ -461,6 +462,35 @@ int belle_sip_header_max_forwards_get_max_forwards(const belle_sip_header_max_fo
void belle_sip_header_max_forwards_set_max_forwards(belle_sip_header_max_forwards_t* max_forwards,int value);
int belle_sip_header_max_forwards_decrement_max_forwards(belle_sip_header_max_forwards_t* max_forwards);
#define BELLE_SIP_HEADER_MAX_FORWARDS(t) BELLE_SIP_CAST(t,belle_sip_header_max_forwards_t)
#define BELLE_SIP_MAX_FORWARDS "Max-Forwards"
/******************************
*
* Subscription state inherit from parameters
*
******************************/
typedef struct _belle_sip_header_subscription_state belle_sip_header_subscription_state_t;
belle_sip_header_subscription_state_t* belle_sip_header_subscription_state_new();
belle_sip_header_subscription_state_t* belle_sip_header_subscription_state_parse (const char* subscription_state) ;
const char* belle_sip_header_subscription_state_get_state(const belle_sip_header_subscription_state_t* subscription_state);
int belle_sip_header_subscription_state_get_expires(const belle_sip_header_subscription_state_t* subscription_state);
const char* belle_sip_header_subscription_state_get_reason(const belle_sip_header_subscription_state_t* subscription_state);
int belle_sip_header_subscription_state_get_retry_after(const belle_sip_header_subscription_state_t* subscription_state);
void belle_sip_header_subscription_state_set_state(belle_sip_header_subscription_state_t* subscription_state,const char* state);
void belle_sip_header_subscription_state_set_expires(belle_sip_header_subscription_state_t* subscription_state,int expire);
void belle_sip_header_subscription_state_set_reason(belle_sip_header_subscription_state_t* subscription_state, const char* reason);
void belle_sip_header_subscription_state_set_retry_after(belle_sip_header_subscription_state_t* subscription_state, int retry_after );
#define BELLE_SIP_HEADER_SUBSCRIPTION_STATE(t) BELLE_SIP_CAST(t,belle_sip_header_subscription_state_t)
#define BELLE_SIP_SUBSCRIPTION_STATE "Subscription-State"
#define BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE "active"
#define BELLE_SIP_SUBSCRIPTION_STATE_PENDING "pending"
#define BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED "terminated"
#endif /* HEADERS_H_ */
......@@ -72,7 +72,12 @@ belle_sip_object_t *_belle_sip_message_get_header_by_type_id(const belle_sip_mes
(header_type*)_belle_sip_message_get_header_by_type_id(BELLE_SIP_MESSAGE(msg),BELLE_SIP_TYPE_ID(header_type))
const belle_sip_list_t* belle_sip_message_get_headers(const belle_sip_message_t *message,const char* header_name);
/*
* Get list of all headers present in the message.
* @param message
* @return a newly allocated list of belle_sip_header_t
* */
belle_sip_list_t* belle_sip_message_get_all_headers(const belle_sip_message_t *message);
/**
* add an header to this message
* @param msg
......
......@@ -58,7 +58,7 @@ libbellesip_la_SOURCES= \
transports/stream_channel.h \
transports/stream_listeningpoint.c \
transports/tls_listeningpoint.c \
refresher.c
refresher.c refresher-helper.h
if BUILD_TLS
libbellesip_la_SOURCES+=transports/tls_channel.c
endif
......
......@@ -1104,3 +1104,34 @@ GET_SET_INT(belle_sip_header_max_forwards,max_forwards,int)
int belle_sip_header_max_forwards_decrement_max_forwards(belle_sip_header_max_forwards_t* max_forwards) {
return max_forwards->max_forwards--;
}
/**************************
* Subscription state header object inherent from parameters
****************************
*/
struct _belle_sip_header_subscription_state {
belle_sip_parameters_t parameters;
const char* state;
};
static void belle_sip_header_subscription_state_destroy(belle_sip_header_subscription_state_t* subscription_state) {
DESTROY_STRING(subscription_state,state);
}
static void belle_sip_header_subscription_state_clone(belle_sip_header_subscription_state_t* subscription_state,
const belle_sip_header_subscription_state_t *orig ) {
CLONE_STRING(belle_sip_header_subscription_state,state,subscription_state,orig)
}
int belle_sip_header_subscription_state_marshal(belle_sip_header_subscription_state_t* subscription_state, char* buff,unsigned int offset,unsigned int buff_size) {
unsigned int current_offset=offset;
current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(subscription_state), buff,current_offset, buff_size);
current_offset+=snprintf(buff+current_offset,buff_size-current_offset," %s",subscription_state->state);
current_offset+=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(subscription_state), buff,current_offset, buff_size);
return current_offset-offset;
}
BELLE_SIP_NEW_HEADER(header_subscription_state,parameters,BELLE_SIP_SUBSCRIPTION_STATE)
BELLE_SIP_PARSE(header_subscription_state)
GET_SET_STRING(belle_sip_header_subscription_state,state);
GET_SET_STRING_PARAM(belle_sip_header_subscription_state,reason);
GET_SET_INT_PARAM2(belle_sip_header_subscription_state,retry-after,int,retry_after);
GET_SET_INT_PARAM(belle_sip_header_subscription_state,expires,int)
......@@ -205,7 +205,7 @@ BELLE_SIP_DECLARE_VPTR(belle_sdp_version_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_base_description_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_mime_parameter_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_refresher_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_subscription_state_t);
typedef void (*belle_sip_source_remove_callback_t)(belle_sip_source_t *);
......
......@@ -1040,6 +1040,19 @@ catch [ANTLR3_MISMATCHED_TOKEN_EXCEPTION]
belle_sip_object_unref($header_www_authenticate::current);
$ret=NULL;
}
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; }
: {IS_TOKEN(Subscription-State)}? token /*"Subscription-State"*/
hcolon state_value {belle_sip_header_subscription_state_set_state($header_subscription_state::current,(const char*)$state_value.text->chars);}
(semi generic_param [BELLE_SIP_PARAMETERS($header_subscription_state::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_subscription_state::current);
$ret=NULL;
}
state_value: token ;
header_extension[ANTLR3_BOOLEAN check_for_known_header] returns [belle_sip_header_t* ret]
: header_name
......@@ -1080,6 +1093,8 @@ header_extension[ANTLR3_BOOLEAN check_for_known_header] returns [belle_sip_head
$ret = BELLE_SIP_HEADER(belle_sip_header_expires_parse((const char*)$header_extension.text->chars));
} else if (check_for_known_header && strcasecmp("Allow",(const char*)$header_name.text->chars) == 0) {
$ret = BELLE_SIP_HEADER(belle_sip_header_allow_parse((const char*)$header_extension.text->chars));
} else if (check_for_known_header && strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE,(const char*)$header_name.text->chars) == 0) {
$ret = BELLE_SIP_HEADER(belle_sip_header_subscription_state_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);
......
......@@ -360,6 +360,38 @@ belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *obj, co
}
return req;
}
static unsigned int is_system_header(belle_sip_header_t* header) {
const char* name=belle_sip_header_get_name(header);
return strcasecmp(BELLE_SIP_VIA,name) ==0
|| strcasecmp(BELLE_SIP_FROM,name) ==0
|| strcasecmp(BELLE_SIP_TO,name) ==0
|| strcasecmp(BELLE_SIP_CSEQ,name) ==0
|| strcasecmp(BELLE_SIP_CALL_ID,name) ==0
|| strcasecmp(BELLE_SIP_PROXY_AUTHORIZATION,name) == 0
|| strcasecmp(BELLE_SIP_AUTHORIZATION,name) == 0
|| strcasecmp(BELLE_SIP_MAX_FORWARDS,name) == 0
|| strcasecmp(BELLE_SIP_ALLOW,name) ==0
|| strcasecmp(BELLE_SIP_ROUTE,name) ==0;
}
static void copy_non_system_headers(belle_sip_header_t* header,belle_sip_request_t* req ) {
if (!is_system_header(header)) {
belle_sip_object_ref(header);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),header);
}
}
belle_sip_request_t *belle_sip_dialog_create_request_from(belle_sip_dialog_t *obj, const belle_sip_request_t *initial_req){
belle_sip_request_t* req = belle_sip_dialog_create_request(obj, belle_sip_request_get_method(initial_req));
belle_sip_header_content_length_t* content_lenth = belle_sip_message_get_header_by_type(initial_req,belle_sip_header_content_length_t);
/*first copy non system headers*/
belle_sip_list_t* headers = belle_sip_message_get_all_headers(BELLE_SIP_MESSAGE(initial_req));
belle_sip_list_for_each2(headers,(void (*)(void *, void *))copy_non_system_headers,req);
belle_sip_list_free(headers);
/*copy body*/
if (content_lenth && belle_sip_header_content_length_get_content_length(content_lenth)>0) {
belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),belle_sip_message_get_body(BELLE_SIP_MESSAGE(initial_req)),belle_sip_header_content_length_get_content_length(content_lenth));
}
return req;
}
void belle_sip_dialog_delete(belle_sip_dialog_t *obj){
/*belle_sip_dialog_state_t prevstate=obj->state;*/
......
......@@ -218,8 +218,31 @@ int belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");\
}
*/
typedef void (*heach_header_cb)(const belle_sip_header_t* header,void* userdata);
static void belle_sip_message_for_each_header(const belle_sip_message_t *message,heach_header_cb cb,void* user_data) {
belle_sip_list_t* headers_list;
belle_sip_list_t* header_list;
for(headers_list=message->header_list;headers_list!=NULL;headers_list=headers_list->next){
for(header_list=((headers_container_t*)(headers_list->data))->header_list
;header_list!=NULL
;header_list=header_list->next) {
cb(BELLE_SIP_HEADER(header_list->data),user_data);
}
}
return;
}
static void append_header(const belle_sip_header_t* header,void* user_data) {
*(belle_sip_list_t**)user_data=belle_sip_list_append((*(belle_sip_list_t**)user_data),(void*)header);
}
belle_sip_list_t* belle_sip_message_get_all_headers(const belle_sip_message_t *message) {
belle_sip_list_t* headers=NULL;
belle_sip_message_for_each_header(message,append_header,&headers);
return headers;
}
int belle_sip_headers_marshal(belle_sip_message_t *message, char* buff,unsigned int offset,unsigned int buff_size) {
unsigned int current_offset=offset;
/*FIXME, replace this code by belle_sip_message_for_each_header*/
belle_sip_list_t* headers_list;
belle_sip_list_t* header_list;
for(headers_list=message->header_list;headers_list!=NULL;headers_list=headers_list->next){
......
......@@ -116,15 +116,21 @@ static int refresh(belle_sip_refresher_t* refresher) {
belle_sip_dialog_t* dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_client_transaction_t* client_transaction;
belle_sip_request_t* request;
belle_sip_header_expires_t* expires_header;
belle_sip_provider_t* prov=refresher->transaction->base.provider;
if (!dialog) {
/*create new request*/
request=belle_sip_client_transaction_create_authenticated_request(refresher->transaction);
} else if (dialog && belle_sip_dialog_get_state(dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
request=belle_sip_dialog_create_request(dialog,belle_sip_request_get_method(old_request));
request=belle_sip_dialog_create_request_from(dialog,old_request);
if (strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0) {
/*put expire header*/
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(belle_sip_header_expires_create(refresher->expires)));
if (!(expires_header = belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t))) {
expires_header = belle_sip_header_expires_new();
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header));
}
belle_sip_header_expires_set_expires(expires_header,refresher->expires);
}
belle_sip_provider_add_authorization(prov,request,NULL);
} else {
......
......@@ -488,6 +488,21 @@ static void test_header_address() {
CU_ASSERT_EQUAL(belle_sip_uri_get_port(L_uri), 5060);
belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
}
void test_header_subscription_state(void) {
belle_sip_header_subscription_state_t* L_tmp;
belle_sip_header_subscription_state_t* L_subscription_state = belle_sip_header_subscription_state_parse("Subscription-State: terminated;expires=600");
char* l_raw_header = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_subscription_state));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_subscription_state));
L_tmp = belle_sip_header_subscription_state_parse(l_raw_header);
L_subscription_state = BELLE_SIP_HEADER_SUBSCRIPTION_STATE(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_subscription_state_get_state(L_subscription_state), "terminated");
CU_ASSERT_EQUAL(belle_sip_header_subscription_state_get_expires(L_subscription_state), 600);
belle_sip_object_unref(BELLE_SIP_OBJECT(L_subscription_state));
}
int belle_sip_headers_test_suite() {
CU_pSuite pSuite = NULL;
......@@ -562,5 +577,8 @@ int belle_sip_headers_test_suite() {
if (NULL == CU_add_test(pSuite, "test-header-address",test_header_address )) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "test_header_subscription_state",test_header_subscription_state )) {
return CU_get_error();
}
return 0;
}
......@@ -352,6 +352,7 @@ static void subscribe_test() {
70);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(1)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_create("Event","Presence")));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(destination_route));
trans=belle_sip_provider_create_client_transaction(client->provider,req);
......
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