Commit 9a8378ba authored by jehan's avatar jehan

extend refresher to support transiant transaction

parent 4b6fe566
......@@ -74,8 +74,10 @@ BELLESIP_EXPORT belle_sip_refresher_t* belle_sip_client_transaction_create_refre
* Create an authenticated request based on an existing terminated transaction.
* <br>This function, update cseq, put route set and try to fill authorization headers. Initial request is not cloned.
* @param transaction . must be in state completed
* @param auth_infos if auth infos cannot be added for an authenticate header,
* a newly allocated belle_sip_auth_info_t object is added to this list. These object contains useful information like realm and username. May be NULL
* */
BELLESIP_EXPORT belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t);
BELLESIP_EXPORT belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos);
#define BELLE_SIP_TRANSACTION(t) BELLE_SIP_CAST(t,belle_sip_transaction_t)
#define BELLE_SIP_SERVER_TRANSACTION(t) BELLE_SIP_CAST(t,belle_sip_server_transaction_t)
......
......@@ -99,9 +99,7 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
struct dns_packet *ans;
struct dns_rr_i *I;
int error;
#ifndef HAVE_C99
struct dns_rr_i dns_rr_it;
#endif
if (revents & BELLE_SIP_EVENT_TIMEOUT) {
belle_sip_error("%s timed-out", __FUNCTION__);
......@@ -119,12 +117,9 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
enum dns_section section = DNS_S_AN;
ans = dns_res_fetch(ctx->R, &error);
#ifdef HAVE_C99
I = dns_rr_i_new(ans, .section = 0);
#else
memset(&dns_rr_it, 0, sizeof dns_rr_it);
I = dns_rr_i_init(&dns_rr_it, ans);
#endif
while (dns_rr_grep(&rr, 1, I, ans, &error)) {
if (rr.section == section) {
if ((error = dns_any_parse(dns_any_init(&any, sizeof(any)), &rr, ans))) {
......@@ -142,6 +137,7 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), host, sizeof(host), service, sizeof(service), NI_NUMERICHOST) != 0)
continue;
ctx->ai = belle_sip_ip_address_to_addrinfo(ctx->family, host, ctx->port);
ctx->done=TRUE;
belle_sip_message("%s has address %s", ctx->name, host);
break;
} else {
......@@ -155,6 +151,7 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
if (getnameinfo((struct sockaddr *)&sin, sizeof(sin), host, sizeof(host), service, sizeof(service), NI_NUMERICHOST) != 0)
continue;
ctx->ai = belle_sip_ip_address_to_addrinfo(ctx->family, host, ctx->port);
ctx->done=TRUE;
belle_sip_message("%s has address %s", ctx->name, host);
break;
}
......@@ -190,8 +187,10 @@ static int _resolver_start_query(belle_sip_resolver_context_t *ctx, belle_sip_so
return -1;
}
(*datafunc)(ctx, 0);
belle_sip_socket_source_init((belle_sip_source_t*)ctx, datafunc, ctx, dns_res_pollfd(ctx->R), BELLE_SIP_EVENT_READ | BELLE_SIP_EVENT_TIMEOUT, timeout);
if ((*datafunc)(ctx, 0) == BELLE_SIP_CONTINUE) {
/*only init source if res inprogress*/
belle_sip_socket_source_init((belle_sip_source_t*)ctx, datafunc, ctx, dns_res_pollfd(ctx->R), BELLE_SIP_EVENT_READ | BELLE_SIP_EVENT_TIMEOUT, timeout);
}
return 0;
}
......@@ -227,12 +226,9 @@ static int resolver_start_query(belle_sip_resolver_context_t *ctx, belle_sip_sou
if (!hosts(ctx))
return -1;
#ifdef HAVE_C99
opts = dns_opts();
#else
memset(&opts_st, 0, sizeof opts_st);
opts = &opts_st;
#endif
if (!(ctx->R = dns_res_open(ctx->resconf, ctx->hosts, dns_hints_mortal(hints(ctx->resconf, &error)), cache(ctx), opts, &error))) {
belle_sip_error("%s dns_res_open error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error));
return -1;
......@@ -293,8 +289,9 @@ static void belle_sip_resolver_context_destroy(belle_sip_resolver_context_t *ctx
belle_sip_free(ctx->name);
if (ctx->R)
dns_res_close(ctx->R);
if (ctx->hosts)
dns_hosts_release(ctx->hosts);
if (ctx->hosts) {
dns_hosts_close(ctx->hosts);
}
if (ctx->resconf)
free(ctx->resconf);
}
......@@ -322,11 +319,14 @@ unsigned long belle_sip_resolve(belle_sip_stack_t *stack, const char *name, int
belle_sip_object_unref(ctx);
return 0;
}
/* The resolver context must never be removed manually from the main loop */
belle_sip_main_loop_add_source(ml,(belle_sip_source_t*)ctx);
belle_sip_object_unref(ctx); /* The main loop has a ref on it */
return ctx->source.id;
if (ctx->done == FALSE) {
/* The resolver context must never be removed manually from the main loop */
belle_sip_main_loop_add_source(ml,(belle_sip_source_t*)ctx);
belle_sip_object_unref(ctx); /* The main loop has a ref on it */
return ctx->source.id;
} else {
return 0; /*resolution done synchronously*/
}
} else {
cb(data, name, res);
return 0;
......
......@@ -36,6 +36,7 @@ struct belle_sip_refresher {
static int set_expires_from_trans(belle_sip_refresher_t* refresher);
static int timer_cb(void *user_data, unsigned int events) ;
static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher,int expires,int auth_mandatory, belle_sip_list_t** auth_infos);
static void schedule_timer_at(belle_sip_refresher_t* refresher,int delay) {
if (delay>0) {
......@@ -98,6 +99,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
int response_code = belle_sip_response_get_status_code(response);
belle_sip_refresher_t* refresher=(belle_sip_refresher_t*)user_ctx;
belle_sip_list_t* auth_info=NULL;
if (refresher && (client_transaction !=refresher->transaction))
return; /*not for me*/
......@@ -112,8 +114,11 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
}
case 401:
case 407:{
belle_sip_refresher_refresh(refresher,refresher->expires); /*authorization is supposed to be available immediately*/
return;
if (belle_sip_refresher_refresh_internal(refresher,refresher->expires,TRUE,&auth_info))
break; /*Notify user of registration failure*/
else
return; /*ok, keep 401 internal*/
}
case 408:
case 480:
......@@ -159,8 +164,11 @@ void belle_sip_refresher_set_listener(belle_sip_refresher_t* refresher, belle_si
refresher->listener=listener;
refresher->user_data=user_pointer;
}
int belle_sip_refresher_refresh(belle_sip_refresher_t* refresher,int expires) {
belle_sip_refresher_stop(refresher);
return belle_sip_refresher_refresh_internal(refresher,expires,FALSE,NULL);
}
static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher,int expires,int auth_mandatory, belle_sip_list_t** auth_infos) {
belle_sip_request_t*old_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_response_t*old_response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_dialog_t* dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(refresher->transaction));
......@@ -171,7 +179,7 @@ int belle_sip_refresher_refresh(belle_sip_refresher_t* refresher,int expires) {
belle_sip_provider_t* prov=refresher->transaction->base.provider;
belle_sip_header_contact_t* contact;
/*first remove timer if any*/
belle_sip_refresher_stop(refresher);
refresher->expires=expires;
if (!dialog) {
const belle_sip_transaction_state_t state=belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction));
......@@ -186,7 +194,7 @@ int belle_sip_refresher_refresh(belle_sip_refresher_t* refresher,int expires) {
cseq=belle_sip_message_get_header_by_type(request,belle_sip_header_cseq_t);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
} else {
request=belle_sip_client_transaction_create_authenticated_request(refresher->transaction);
request=belle_sip_client_transaction_create_authenticated_request(refresher->transaction,auth_infos);
}
} else if (dialog && belle_sip_dialog_get_state(dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
request=belle_sip_dialog_create_request_from(dialog,old_request);
......@@ -199,7 +207,7 @@ int belle_sip_refresher_refresh(belle_sip_refresher_t* refresher,int expires) {
}
belle_sip_provider_add_authorization(prov,request,old_response,NULL);
belle_sip_provider_add_authorization(prov,request,old_response,auth_infos);
} else {
belle_sip_error("Unexpected dialog state [%s] for dialog [%p], cannot refresh [%s]"
,belle_sip_dialog_state_to_string(belle_sip_dialog_get_state(dialog))
......@@ -207,6 +215,12 @@ int belle_sip_refresher_refresh(belle_sip_refresher_t* refresher,int expires) {
,belle_sip_request_get_method(old_request));
return -1;
}
if (auth_mandatory && auth_infos && (*auth_infos!=NULL || belle_sip_list_size(*auth_infos)) >0) {
belle_sip_message("Auth info not found for this refresh operation on [%p]",refresher);
if (request) belle_sip_object_unref(request);
return -1;
}
/*update expires in any cases*/
expires_header = belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t);
if (expires_header)
......@@ -247,6 +261,8 @@ static belle_sip_header_contact_t* get_matching_contact(const belle_sip_transact
belle_sip_header_contact_t* fixed_local_contact;
char* tmp_string;
char* tmp_string2;
if (!response)
return NULL;
/*we assume, there is only one contact in request*/
unfixed_local_contact= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t);
fixed_local_contact= BELLE_SIP_HEADER_CONTACT(belle_sip_object_clone(BELLE_SIP_OBJECT(unfixed_local_contact)));
......@@ -304,7 +320,7 @@ static int set_expires_from_trans(belle_sip_refresher_t* refresher) {
}
if (refresher->expires==-1){
/*no contact with expire or not relevant, looking for Expires header*/
if ((expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES))) {
if (response && (expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES))) {
refresher->expires = belle_sip_header_expires_get_expires(expires_header);
}
}
......@@ -355,8 +371,10 @@ void belle_sip_refresher_stop(belle_sip_refresher_t* refresher) {
belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* transaction) {
belle_sip_refresher_t* refresher;
belle_sip_transaction_state_t state=belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction));
if (state != BELLE_SIP_TRANSACTION_COMPLETED && state!=BELLE_SIP_TRANSACTION_TERMINATED ) {
belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED"
if ( state != BELLE_SIP_TRANSACTION_COMPLETED
&& state!=BELLE_SIP_TRANSACTION_TERMINATED
&& state != BELLE_SIP_TRANSACTION_TRYING) {
belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED/BELLE_SIP_TRANSACTION_TERMINATED/BELLE_SIP_TRANSACTION_TRYNG"
,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction)))
,transaction);
return NULL;
......@@ -375,6 +393,10 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
if (set_expires_from_trans(refresher)){
belle_sip_error("Unable to extract refresh value from transaction [%p]",transaction);
}
if (belle_sip_transaction_state_is_transient(state)) {
belle_sip_message(" refresher [%p] takes ownership of transaction [%p]",refresher,transaction);
transaction->base.is_internal=1;
}
return refresher;
}
......
......@@ -461,13 +461,13 @@ void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, bell
belle_sip_refresher_t* belle_sip_client_transaction_create_refresher(belle_sip_client_transaction_t *t) {
belle_sip_refresher_t* refresher = belle_sip_refresher_new(t);
if (refresher) {
if (refresher && !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))) {
belle_sip_refresher_start(refresher);
}
return refresher;
}
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t) {
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos) {
belle_sip_request_t* req=BELLE_SIP_REQUEST(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t)))));
belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
......@@ -476,6 +476,7 @@ belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(b
belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED | BELLE_SIP_TRANSACTION_TERMINATED"
,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))
,t);
belle_sip_object_unref(req);
return NULL;
}
/*remove auth headers*/
......@@ -483,7 +484,7 @@ belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(b
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION);
/*put auth header*/
belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response,NULL);
belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response,auth_infos);
return req;
}
......@@ -367,7 +367,7 @@ static void register_base(endpoint_t* client,endpoint_t *server) {
} else {
CU_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredOne,1,1000));
/*update cseq*/
req=belle_sip_client_transaction_create_authenticated_request(trans);
req=belle_sip_client_transaction_create_authenticated_request(trans,NULL);
belle_sip_object_unref(trans);
trans=belle_sip_provider_create_client_transaction(client->provider,req);
belle_sip_object_ref(trans);
......@@ -462,7 +462,7 @@ static void subscribe_test(void) {
CU_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.fourHundredOne,1,1000));
req=belle_sip_client_transaction_create_authenticated_request(trans);
req=belle_sip_client_transaction_create_authenticated_request(trans,NULL);
belle_sip_object_unref(trans);
trans=belle_sip_provider_create_client_transaction(client->provider,req);
belle_sip_object_ref(trans);
......
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