Commit 58bbbe36 authored by jehan's avatar jehan
Browse files

Merge remote-tracking branch 'origin' into bctoolbox

parents fc237d85 c130b4eb
......@@ -61,6 +61,13 @@ BELLESIP_EXPORT unsigned char belle_sip_stack_dns_srv_enabled(const belle_sip_st
BELLESIP_EXPORT void belle_sip_stack_enable_dns_srv(belle_sip_stack_t *stack, unsigned char enable);
/**
* Override system's DNS servers used for DNS resolving by app-supplied list of dns servers.
* @param stack the stack
* @param servers a list of char*. It is copied internally.
**/
BELLESIP_EXPORT void belle_sip_stack_set_dns_servers(belle_sip_stack_t *stack, const belle_sip_list_t *servers);
/**
* Can be used to simulate network transmission delays, for tests.
**/
......
......@@ -523,13 +523,15 @@ struct belle_sip_stack{
int dscp;
char *dns_user_hosts_file; /* used to load additional hosts file for tests */
char *dns_resolv_conf; /*used to load custom resolv.conf, for tests*/
unsigned char dns_srv_enabled;
belle_sip_list_t *dns_servers; /*used when dns servers are supplied by app layer*/
/*http proxy stuff to be used by both http and sip provider*/
char *http_proxy_host;
int http_proxy_port;
char *http_proxy_username; /*for futur use*/
char *http_proxy_passwd; /*for futur use*/
char *http_proxy_username; /*for future use*/
char *http_proxy_passwd; /*for future use*/
unsigned char dns_srv_enabled;
};
belle_sip_hop_t* belle_sip_hop_new(const char* transport, const char *cname, const char* host,int port);
......@@ -584,6 +586,9 @@ typedef struct listener_ctx{
#define BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(t,callback,event) \
BELLE_SIP_PROVIDER_INVOKE_LISTENERS((t)->is_internal?(t)->provider->internal_listeners:(t)->provider->listeners,callback,event)
#define BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_DIALOG(d,callback,event) \
BELLE_SIP_PROVIDER_INVOKE_LISTENERS((d)->is_internal?(d)->provider->internal_listeners:(d)->provider->listeners,callback,event)
#define BELLE_SIP_PROVIDER_INVOKE_LISTENERS(listeners,callback,event) \
BELLE_SIP_INVOKE_LISTENERS_ARG((listeners),belle_sip_listener_t,callback,(event))
......@@ -816,6 +821,7 @@ struct belle_sip_dialog{
unsigned char needs_ack;
unsigned char is_expired;
unsigned char pending_trans_checking_enabled; /*use to disabled pending transaction check at request creation (testing)*/
unsigned char is_internal; /*Internal dialogs are those created by refreshers. */
};
belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t);
......
......@@ -168,8 +168,22 @@ void belle_sip_resolver_context_init(belle_sip_resolver_context_t *obj, belle_si
belle_sip_init_sockets(); /* Need to be called for DNS resolution to work on Windows platform. */
}
static int dns_resconf_nameservers_from_list(struct dns_resolv_conf *resconf, const belle_sip_list_t *l) {
int max_servers = sizeof(resconf->nameserver)/sizeof(struct sockaddr_storage);
int i;
const belle_sip_list_t *elem;
for (i = 0, elem = l; i < max_servers && elem != NULL; elem = elem->next) {
int error = dns_resconf_pton(&resconf->nameserver[i], (const char *) elem->data);
if (error == 0) ++i;
}
return i > 0 ? 0 : -1;
}
static struct dns_resolv_conf *resconf(belle_sip_simple_resolver_context_t *ctx) {
const char *path;
const belle_sip_list_t *servers;
int error;
if (ctx->resconf)
......@@ -180,8 +194,13 @@ static struct dns_resolv_conf *resconf(belle_sip_simple_resolver_context_t *ctx)
return NULL;
}
path=belle_sip_stack_get_dns_resolv_conf_file(ctx->base.stack);
if (!path){
path = belle_sip_stack_get_dns_resolv_conf_file(ctx->base.stack);
servers = ctx->base.stack->dns_servers;
if (servers){
belle_sip_message("%s using application supplied dns server list.", __FUNCTION__);
error = dns_resconf_nameservers_from_list(ctx->resconf, servers);
}else if (!path){
#if defined(USE_FIXED_NAMESERVERS)
error = dns_resconf_load_fixed_nameservers(ctx->resconf);
if (error) {
......
......@@ -554,7 +554,21 @@ void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream)
static void belle_sip_channel_process_stream(belle_sip_channel_t *obj, int eos){
belle_sip_channel_parse_stream(obj,eos);
if (obj->incoming_messages) notify_incoming_messages(obj);
if (obj->incoming_messages) {
if (obj->simulated_recv_return == 1500) {
belle_sip_list_t *elem;
for(elem=obj->incoming_messages;elem!=NULL;elem=elem->next){
belle_sip_message_t *msg=(belle_sip_message_t*)elem->data;
char* dump = belle_sip_message_to_string(msg);
belle_sip_message("Silently discarding incoming message [%.50s...] on channel [%p]",dump, obj);
belle_sip_free(dump);
}
belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
obj->incoming_messages=NULL;
} else {
notify_incoming_messages(obj);
}
}
}
static int belle_sip_channel_process_read_data(belle_sip_channel_t *obj){
......
......@@ -112,7 +112,7 @@ struct belle_sip_channel{
belle_sip_list_t* incoming_messages;
belle_sip_source_t *inactivity_timer;
uint64_t last_recv_time;
int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error*/
int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error, 1500 special number to silently discard incoming buffer*/
unsigned long bg_task_id;
unsigned long recv_bg_task_id;
unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
......
......@@ -449,21 +449,26 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
}
break;
case BELLE_SIP_DIALOG_CONFIRMED:
/*refreshing target is also true in case of subscribe*/
if ((is_invite || is_subscribe) && (code>=200 && code<300)) {
/*refresh the remote_target*/
belle_sip_header_contact_t *ct;
if (as_uas){
ct=belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
}else{
if (is_invite)
set_last_out_invite(obj,req);
ct=belle_sip_message_get_header_by_type(resp,belle_sip_header_contact_t);
}
if (ct){
belle_sip_object_unref(obj->remote_target);
obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct);
}
}
if (is_invite){
if (code>=200 && code<300){
/*refresh the remote_target*/
belle_sip_header_contact_t *ct;
if (as_uas){
ct=belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
}else{
set_last_out_invite(obj,req);
ct=belle_sip_message_get_header_by_type(resp,belle_sip_header_contact_t);
}
if (ct){
belle_sip_object_unref(obj->remote_target);
obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct);
}
/*handle possible retransmission of 200Ok */
if (!as_uas && (is_retransmition=(belle_sip_dialog_handle_200Ok(obj,resp)==0))) {
return is_retransmition;
......
......@@ -4017,7 +4017,7 @@ static enum dns_resconf_keyword dns_resconf_keyword(const char *word) {
/** OpenBSD-style "[1.2.3.4]:53" nameserver syntax */
static int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) {
int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) {
struct { char buf[128], *p; } addr = { "", addr.buf };
unsigned short port = 0;
char *percent;
......
......@@ -910,6 +910,8 @@ int dns_resconf_loadfile(struct dns_resolv_conf *, FILE *);
int dns_resconf_loadpath(struct dns_resolv_conf *, const char *);
int dns_resconf_pton(struct sockaddr_storage *ss, const char *src);
#ifdef USE_FIXED_NAMESERVERS
int dns_resconf_load_fixed_nameservers(struct dns_resolv_conf *resconf);
#endif /* USE_FIXED_NAMESERVERS */
......
......@@ -476,6 +476,9 @@ belle_sip_body_handler_t *belle_sip_message_get_body_handler(const belle_sip_mes
}
void belle_sip_message_set_body_handler(belle_sip_message_t *msg, belle_sip_body_handler_t *body_handler){
belle_sip_header_content_length_t *content_length_header = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t);
belle_sip_header_content_type_t *content_type_header = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
/* In case of multipart message, we must add the message Content-Type header containing the boundary */
if (body_handler != NULL) {
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(body_handler, belle_sip_multipart_body_handler_t)){
......@@ -516,14 +519,19 @@ void belle_sip_message_set_body_handler(belle_sip_message_t *msg, belle_sip_body
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(content_type), "boundary", BELLESIP_MULTIPART_BOUNDARY);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(msg), BELLE_SIP_HEADER(content_type));
} else {
const belle_sip_list_t *header = belle_sip_body_handler_get_headers(body_handler);
for(; header != NULL; header = header->next) {
belle_sip_message_add_header(BELLE_SIP_MESSAGE(msg), BELLE_SIP_HEADER(header->data));
const belle_sip_list_t *headers = belle_sip_body_handler_get_headers(body_handler);
for(; headers != NULL; headers = headers->next) {
belle_sip_header_t *header = BELLE_SIP_HEADER(headers->data);
if (strcasecmp(belle_sip_header_get_name(header),BELLE_SIP_CONTENT_LENGTH ) == 0 && content_length_header)
belle_sip_message_remove_header_from_ptr(msg, BELLE_SIP_HEADER(content_length_header));
if (strcasecmp(belle_sip_header_get_name(header),BELLE_SIP_CONTENT_TYPE ) == 0 && content_type_header)
belle_sip_message_remove_header_from_ptr(msg, BELLE_SIP_HEADER(content_type_header));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(msg), header);
}
}
} else {
belle_sip_header_content_length_t *content_length_header = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t);
belle_sip_header_content_type_t *content_type_header = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t);
if (content_length_header != NULL) belle_sip_message_remove_header_from_ptr(msg, BELLE_SIP_HEADER(content_length_header));
if (content_type_header != NULL) belle_sip_message_remove_header_from_ptr(msg, BELLE_SIP_HEADER(content_type_header));
}
......
......@@ -680,7 +680,7 @@ void belle_sip_provider_add_dialog(belle_sip_provider_t *prov, belle_sip_dialog_
}
static void notify_dialog_terminated(belle_sip_dialog_terminated_event_t* ev) {
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(((belle_sip_provider_t*)ev->source)->listeners,process_dialog_terminated,ev);
BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_DIALOG(ev->dialog,process_dialog_terminated,ev);
belle_sip_object_unref(ev->dialog);
belle_sip_free(ev);
}
......
......@@ -39,6 +39,8 @@ struct belle_sip_refresher {
belle_sip_refresher_listener_t listener;
belle_sip_source_t* timer;
belle_sip_client_transaction_t* transaction;
belle_sip_request_t* first_acknoleged_request; /*store first request sucessfully acknoleged, usefull to re-build a dialog iff needed*/
belle_sip_dialog_t* dialog; /*Cannot rely on transaction to store dialog because of belle_sip_transaction_reset_dialog*/
char* realm;
int target_expires;
int obtained_expires;
......@@ -51,7 +53,9 @@ struct belle_sip_refresher {
int number_of_retry; /*counter to count number of unsuccesfull retry, used to know when to retry*/
timer_purpose_t timer_purpose;
unsigned char manual;
unsigned int publish_pending;
};
static void set_or_update_dialog(belle_sip_refresher_t* refresher, belle_sip_dialog_t* dialog);
static int set_expires_from_trans(belle_sip_refresher_t* refresher);
static int timer_cb(void *user_data, unsigned int events) ;
......@@ -95,10 +99,15 @@ static void schedule_timer(belle_sip_refresher_t* refresher) {
static void process_dialog_terminated(belle_sip_listener_t *user_ctx, const belle_sip_dialog_terminated_event_t *event){
belle_sip_refresher_t* refresher=(belle_sip_refresher_t*)user_ctx;
belle_sip_dialog_t *dialog =belle_sip_dialog_terminated_event_get_dialog(event);
if (event->is_expired){
belle_sip_warning("Refresher [%p]: forced to stop because dialog has expired.", refresher);
belle_sip_refresher_stop_internal(refresher, 0);
if (refresher && refresher->transaction && dialog != belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(refresher->transaction)))
return; /*not for me*/
if (refresher->state == started) {
belle_sip_warning("Refresher [%p] still started but receiving unexpected dialog deleted event on [%p], retrying",refresher,dialog);
retry_later_on_io_error(refresher);
if (refresher->listener) refresher->listener(refresher,refresher->user_data,481, "dialod terminated");
}
}
......@@ -202,6 +211,7 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
if (refresher && (client_transaction !=refresher->transaction))
return; /*not for me*/
set_or_update_dialog(refresher,belle_sip_response_event_get_dialog(event));
/*success case:*/
if (response_code>=200 && response_code<300){
refresher->auth_failures=0;
......@@ -215,8 +225,8 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
/*update request for next refresh*/
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),"SIP-If-Match");
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),sip_if_match);
} else {
belle_sip_warning("Refresher [%p] receive 200ok to a publish without etag",refresher);
} else if (refresher->target_expires > 0){
belle_sip_warning("Refresher [%p] received 200ok to a publish without etag",refresher);
}
}
/*update expire if needed*/
......@@ -240,6 +250,8 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
}
if (refresher->state==started) {
if (!refresher->first_acknoleged_request)
belle_sip_object_ref(refresher->first_acknoleged_request = request);
if (is_contact_address_acurate(refresher,request)) {
schedule_timer(refresher); /*re-arm timer*/
} else {
......@@ -280,6 +292,17 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
/*In case of 403, we will retry later, just in case*/
if (refresher->target_expires>0) retry_later(refresher);
break;
case 412:
if (strcmp(belle_sip_request_get_method(request),"PUBLISH")==0) {
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),"SIP-If-Match");
if (refresher->target_expires>0) {
retry_later_on_io_error(refresher);
return; /*do not notify this kind of error*/
}
} else {
if (refresher->target_expires>0) retry_later(refresher);
}
break;
case 423:{
belle_sip_header_extension_t *min_expires=BELLE_SIP_HEADER_EXTENSION(belle_sip_message_get_header((belle_sip_message_t*)response,"Min-Expires"));
if (min_expires){
......@@ -295,10 +318,17 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
}else belle_sip_warning("Receiving 423 but no min-expires header.");
break;
}
case 491: {
if (refresher->target_expires>0) {
retry_later_on_io_error(refresher);
return; /*do not notify this kind of error*/
}
}
case 505:
case 501:
/*irrecoverable errors, probably no need to retry later*/
break;
default:
/*for all other errors, retry later*/
if (refresher->target_expires>0) retry_later(refresher);
......@@ -324,7 +354,19 @@ static void process_timeout(belle_sip_listener_t *user_ctx, const belle_sip_time
}
static void process_transaction_terminated(belle_sip_listener_t *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
/*belle_sip_message("process_transaction_terminated Transaction terminated [%p]",event);*/
belle_sip_refresher_t* refresher=(belle_sip_refresher_t*)user_ctx;
belle_sip_client_transaction_t*client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
if (refresher && (client_transaction !=refresher->transaction))
return; /*not for me*/
if (refresher->publish_pending && refresher->state==started) {
refresher->publish_pending = FALSE;
belle_sip_message("Publish pending on refresher [%p], doing it",refresher);
belle_sip_refresher_refresh(refresher,refresher->target_expires);
} else {
refresher->publish_pending = FALSE;
}
}
static void process_auth_requested(belle_sip_listener_t *l, belle_sip_auth_event_t *event){
......@@ -340,6 +382,8 @@ static void destroy(belle_sip_refresher_t *refresher){
refresher->transaction=NULL;
if (refresher->realm) belle_sip_free(refresher->realm);
if (refresher->auth_events) refresher->auth_events=belle_sip_list_free_with_data(refresher->auth_events,(void (*)(void*))belle_sip_auth_event_destroy);
if (refresher->first_acknoleged_request) belle_sip_object_unref(refresher->first_acknoleged_request);
if (refresher->dialog) belle_sip_object_unref(refresher->dialog);
}
BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_sip_refresher_t,belle_sip_listener_t)
......@@ -376,7 +420,7 @@ static int unfilled_auth_info(const void* info,const void* userptr) {
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_uri_t *requri) {
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));
belle_sip_dialog_t* dialog = refresher->dialog;
belle_sip_client_transaction_t* client_transaction;
belle_sip_request_t* request;
belle_sip_header_expires_t* expires_header;
......@@ -400,9 +444,16 @@ static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher
belle_sip_message("Refresher [%p] already has transaction [%p] in state [%s]" ,refresher
,refresher->transaction
,belle_sip_transaction_state_to_string(state));
request=belle_sip_request_clone_with_body(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction)));
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);
if (strcmp(belle_sip_request_get_method(old_request),"PUBLISH")==0) {
belle_sip_message("Refresher [%p] new publish is delayed to end of ongoing transaction" ,refresher);
refresher->publish_pending = TRUE;
return 0;
} else {
request=belle_sip_request_clone_with_body(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction)));
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,auth_infos,refresher->realm);
}
......@@ -413,44 +464,65 @@ static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION);
}
} else if (dialog && belle_sip_dialog_get_state(dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
if (belle_sip_dialog_request_pending(dialog)){
belle_sip_message("Cannot refresh now, there is a pending request in the dialog.");
return -1;
}
request=belle_sip_dialog_create_request_from(dialog,old_request);
if (strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0) {
belle_sip_header_content_type_t *content_type;
/*put expire header*/
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));
} else {
switch (belle_sip_dialog_get_state(dialog)) {
case BELLE_SIP_DIALOG_CONFIRMED: {
if (belle_sip_dialog_request_pending(dialog)){
belle_sip_message("Cannot refresh now, there is a pending request in the dialog.");
return -1;
}
request=belle_sip_dialog_create_request_from(dialog,old_request);
if (strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0) {
belle_sip_header_content_type_t *content_type;
/*put expire header*/
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));
}
if ((content_type = belle_sip_message_get_header_by_type(request, belle_sip_header_content_type_t))
&& strcasecmp("application", belle_sip_header_content_type_get_type(content_type)) == 0
&& strcasecmp("resource-lists+xml", belle_sip_header_content_type_get_subtype(content_type)) == 0) {
/*rfc5367
3.2. Subsequent SUBSCRIBE Requests
...
At this point, there are no semantics associated with resource-list
bodies in subsequent SUBSCRIBE requests (although future extensions
can define them). Therefore, UACs SHOULD NOT include resource-list
bodies in subsequent SUBSCRIBE requests to a resource list server.
*/
belle_sip_message("Removing body, content type and content length for refresher [%p]",refresher);
belle_sip_message_set_body(BELLE_SIP_MESSAGE(request), NULL, 0);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTENT_TYPE);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTENT_LENGTH);
}
}
belle_sip_provider_add_authorization(prov,request,old_response,NULL,auth_infos,refresher->realm);
break;
}
if ((content_type = belle_sip_message_get_header_by_type(request, belle_sip_header_content_type_t))
&& strcasecmp("application", belle_sip_header_content_type_get_type(content_type)) == 0
&& strcasecmp("resource-lists+xml", belle_sip_header_content_type_get_subtype(content_type)) == 0) {
/*rfc5367
3.2. Subsequent SUBSCRIBE Requests
...
At this point, there are no semantics associated with resource-list
bodies in subsequent SUBSCRIBE requests (although future extensions
can define them). Therefore, UACs SHOULD NOT include resource-list
bodies in subsequent SUBSCRIBE requests to a resource list server.
*/
belle_sip_message("Removing body, content type and content length for refresher [%p]",refresher);
belle_sip_message_set_body(BELLE_SIP_MESSAGE(request), NULL, 0);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTENT_TYPE);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CONTENT_LENGTH);
case BELLE_SIP_DIALOG_TERMINATED: {
if (refresher->first_acknoleged_request) {
char tmp[11];
belle_sip_message("Dialog [%p] is in state terminated, recreating a new one for refresher [%p]",dialog,refresher);
request = refresher->first_acknoleged_request;
belle_sip_header_cseq_set_seq_number(belle_sip_message_get_header_by_type(request,belle_sip_header_cseq_t)
,20);
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(belle_sip_message_get_header_by_type(request,belle_sip_header_to_t)),"tag");
belle_sip_header_call_id_set_call_id( belle_sip_message_get_header_by_type(request,belle_sip_header_call_id_t)
, belle_sip_random_token(tmp,sizeof(tmp)));
break;
} /*else nop, error case*/
}
default: {
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))
,dialog
,belle_sip_request_get_method(old_request));
return -1;
}
}
belle_sip_provider_add_authorization(prov,request,old_response,NULL,auth_infos,refresher->realm);
} 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))
,dialog
,belle_sip_request_get_method(old_request));
return -1;
}
if (auth_mandatory && auth_infos && belle_sip_list_find_custom(*auth_infos, unfilled_auth_info, NULL)) {
......@@ -481,7 +553,12 @@ static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
client_transaction->base.is_internal=1;
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),refresher);
if (request == refresher->first_acknoleged_request) { /*request is now ref by transaction so no need to keepo it*/
belle_sip_object_unref(refresher->first_acknoleged_request);
refresher->first_acknoleged_request = NULL;
}
switch (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction))) {
case BELLE_SIP_TRANSACTION_INIT:
case BELLE_SIP_TRANSACTION_CALLING:
......@@ -678,6 +755,9 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
belle_sip_object_ref(transaction);
refresher->retry_after=DEFAULT_RETRY_AFTER;
if (belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(transaction))) {
set_or_update_dialog(refresher, belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(transaction)));
}
belle_sip_provider_add_internal_sip_listener(transaction->base.provider,BELLE_SIP_LISTENER(refresher), is_register);
if (set_expires_from_trans(refresher)==-1){
belle_sip_error("Unable to extract refresh value from transaction [%p]",transaction);
......@@ -732,3 +812,18 @@ void belle_sip_refresher_enable_manual_mode(belle_sip_refresher_t *refresher, in
char *belle_sip_refresher_get_public_uri(belle_sip_refresher_t* refresher) {
return belle_sip_channel_get_public_ip_port(refresher->transaction->base.channel);
}
static void set_or_update_dialog(belle_sip_refresher_t* refresher, belle_sip_dialog_t* dialog) {
if (refresher->dialog!=dialog){
belle_sip_message("refresher [%p] : set_or_update_dialog() current=[%p] new=[%p]",refresher,refresher->dialog,dialog);
if (refresher->dialog){
belle_sip_object_unref(refresher->dialog);
}
if (dialog) {
belle_sip_object_ref(dialog);
/*make sure dialog is internal now*/
dialog->is_internal = TRUE;
}
refresher->dialog=dialog;
}
}
......@@ -104,6 +104,7 @@ static void belle_sip_stack_destroy(belle_sip_stack_t *stack){
if (stack->http_proxy_host) belle_sip_free(stack->http_proxy_host);
if (stack->http_proxy_passwd) belle_sip_free(stack->http_proxy_passwd);
if (stack->http_proxy_username) belle_sip_free(stack->http_proxy_username);
belle_sip_list_free_with_data(stack->dns_servers, belle_sip_free);
}
......@@ -251,6 +252,15 @@ void belle_sip_stack_set_dns_resolv_conf_file(belle_sip_stack_t *stack, const ch
stack->dns_resolv_conf = resolv_conf_file?belle_sip_strdup(resolv_conf_file):NULL;
}
void belle_sip_stack_set_dns_servers(belle_sip_stack_t *stack, const belle_sip_list_t *servers){
belle_sip_list_t *newservers = NULL;
if (servers) newservers = belle_sip_list_copy_with_data(servers, (void *(*)(void*))belle_sip_strdup);
if (stack->dns_servers){
belle_sip_list_free_with_data(stack->dns_servers, belle_sip_free);
}
stack->dns_servers = newservers;
}
const char* belle_sip_version_to_string() {
#ifdef BELLESIP_VERSION
return BELLESIP_VERSION;
......
......@@ -66,6 +66,7 @@ static void transaction_destroy(belle_sip_transaction_t *t){
if (t->channel) belle_sip_object_unref(t->channel);
if (t->branch_id) belle_sip_free(t->branch_id);
belle_sip_transaction_set_dialog(t,NULL);
belle_sip_message("Transaction [%p] deleted",t);
}
......@@ -412,8 +413,8 @@ int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t
/*this request was created by belle_sip_dialog_create_queued_request().*/
if (belle_sip_dialog_request_pending(dialog) || dialog->queued_ct!=NULL){
/*it cannot be sent immediately, queue the transaction into dialog*/
belle_sip_message("belle_sip_client_transaction_send_request(): transaction [%p], cannot send request now because dialog is busy"
" or other transactions are queued, so queuing into dialog.",t);
belle_sip_message("belle_sip_client_transaction_send_request(): transaction [%p], cannot send request now because dialog [%p] is busy"
" or other transactions are queued, so queuing into dialog.",t, dialog);
belle_sip_dialog_queue_client_transaction(dialog,t);
return 0;
}
......
......@@ -50,9 +50,11 @@ typedef enum auth_mode {
typedef struct _status {
int twoHundredOk;
int fourHundredOne;
int fourHundredEightyOne;
int refreshOk;
int refreshKo;
int dialogTerminated;
int fiveHundredTree;
}status_t;
typedef struct endpoint {
......@@ -318,10 +320,14 @@ static void belle_sip_refresher_listener (belle_sip_refresher_t* refresher
endpoint_t* endpoint = (endpoint_t*)user_pointer;
BELLESIP_UNUSED(refresher);
belle_sip_message("belle_sip_refresher_listener [%i] reason [%s]",status_code,reason_phrase);
if (status_code >=300)
endpoint->stat.refreshKo++;
switch (status_code) {
case 200:endpoint->stat.refreshOk++; break;
case 481:endpoint->stat.fourHundredEightyOne++;break;
case 503:endpoint->stat.fiveHundredTree++;break;
default:
endpoint->stat.refreshKo++;
/*nop*/
break;
}
if (endpoint->stat.refreshKo==1 && endpoint->transiant_network_failure) {
......@@ -506,6 +512,8 @@ static void subscribe_base(int with_resource_lists) {
belle_sip_uri_t *dest_uri;
belle_sip_refresher_t* refresher;
belle_sip_header_contact_t* contact=belle_sip_header_contact_new();
belle_sip_dialog_t * client_dialog;
int dummy = 0;
uint64_t begin;
uint64_t end;
memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
......@@ -559,7 +567,7 @@ static void subscribe_base(int with_resource_lists) {
belle_sip_client_transaction_send_request(trans);
BC_ASSERT_TRUE_FATAL(wait_for(server->stack,client->stack,&client->stat.twoHundredOk,1,1000));