Commit 1aaa1067 authored by Simon Morlat's avatar Simon Morlat

enhance nat helper mechanism so that even unchallenged requests can be...

enhance nat helper mechanism so that even unchallenged requests can be immediately resubmitted by the refresher if the contact could not be properly set the first time.
parent caa4ac56
......@@ -159,6 +159,13 @@ BELLESIP_EXPORT belle_sip_header_contact_t* belle_sip_header_contact_create (con
BELLESIP_EXPORT int belle_sip_header_contact_get_automatic(const belle_sip_header_contact_t *a);
/**
* Indicates whether a contact in automatic mode (see belle_sip_header_contact_set_automatic()) could be filled properly when the message was sent.
* If a message is sent through a connection that has just been initiated, public IP and port are unknown, they will be learned after receiving the first response.
* This can be used by the upper layer to decide to resubmit the request.
**/
BELLESIP_EXPORT int belle_sip_header_contact_is_unknown(const belle_sip_header_contact_t *a);
#define BELLE_SIP_RANDOM_TAG ((const char*)-1)
#define BELLE_SIP_HEADER_CONTACT(t) BELLE_SIP_CAST(t,belle_sip_header_contact_t)
#define BELLE_SIP_CONTACT "Contact"
......
......@@ -225,7 +225,8 @@ struct _belle_sip_header_contact {
belle_sip_header_address_t address;
unsigned char wildcard;
unsigned char automatic;
unsigned char pad[2];
unsigned char unknown;
unsigned char pad[1];
};
void belle_sip_header_contact_destroy(belle_sip_header_contact_t* contact) {
......@@ -295,6 +296,14 @@ void belle_sip_header_contact_set_automatic(belle_sip_header_contact_t *a, int e
int belle_sip_header_contact_get_automatic(const belle_sip_header_contact_t *a){
return a->automatic;
}
void belle_sip_header_contact_set_unknown(belle_sip_header_contact_t *a, int value){
a->unknown=value;
}
int belle_sip_header_contact_is_unknown(const belle_sip_header_contact_t *a){
return a->unknown;
}
/**************************
* From header object inherent from header_address
****************************
......
......@@ -865,4 +865,6 @@ BELLESIP_INTERNAL_EXPORT char* belle_sip_to_unescaped_string(const char* buff) ;
#define BELLE_SIP_TAG_LENGTH 6
#define BELLE_SIP_MAX_TO_STRING_SIZE 2048
void belle_sip_header_contact_set_unknown(belle_sip_header_contact_t *a, int value);
#endif
......@@ -240,6 +240,7 @@ static void belle_sip_channel_learn_public_ip_port(belle_sip_channel_t *obj, bel
}
belle_sip_channel_set_public_ip_port(obj,received,rport);
}
obj->learnt_ip_port=TRUE;
}
static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
......
......@@ -95,7 +95,8 @@ struct belle_sip_channel{
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*/
unsigned int force_close:1; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
unsigned char learnt_ip_port;
};
#define BELLE_SIP_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_channel_t)
......
......@@ -365,20 +365,25 @@ const char* belle_sip_message_get_body(belle_sip_message_t *msg) {
return msg->body;
}
void belle_sip_message_set_body(belle_sip_message_t *msg,const char* body,unsigned int size) {
void belle_sip_message_set_body(belle_sip_message_t *msg, const char* body, unsigned int size) {
if (msg->body) {
belle_sip_free((void*)msg->body);
belle_sip_free(msg->body);
msg->body=NULL;
}
if (body){
msg->body = belle_sip_malloc(size+1);
memcpy(msg->body,body,size);
msg->body[size]='\0';
}
msg->body = belle_sip_malloc(size+1);
memcpy(msg->body,body,size);
msg->body[size]='\0';
}
void belle_sip_message_assign_body(belle_sip_message_t *msg, char* body) {
if (msg->body) {
belle_sip_free((void*)body);
}
msg->body = body;
}
struct _belle_sip_response{
belle_sip_message_t base;
char *sip_version;
......@@ -574,8 +579,11 @@ void belle_sip_response_fill_for_dialog(belle_sip_response_t *obj, belle_sip_req
if (rr)
belle_sip_message_add_headers((belle_sip_message_t*)obj,rr);
if (belle_sip_response_get_status_code(obj)>=200 && belle_sip_response_get_status_code(obj)<300 && !ct){
/*add a dummy contact to be filled by channel later*/
belle_sip_message_add_header((belle_sip_message_t*)obj,(belle_sip_header_t*)belle_sip_header_contact_new());
const char *method=belle_sip_request_get_method(req);
if (strcmp(method,"INVITE")==0 || strcmp(method,"SUBSCRIBE")==0){
/*add a dummy contact to be filled by channel later*/
belle_sip_message_add_header((belle_sip_message_t*)obj,(belle_sip_header_t*)belle_sip_header_contact_new());
}
}
}
......
......@@ -283,6 +283,7 @@ static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_chan
if (prov->nat_helper){
ip=chan->public_ip ? chan->public_ip : chan->local_ip;
port=chan->public_port ? chan->public_port : chan->local_port;
belle_sip_header_contact_set_unknown(contact,!chan->learnt_ip_port);
}else{
ip=chan->local_ip;
port=chan->local_port;
......
......@@ -127,7 +127,18 @@ static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *e
}
}
static int check_contact_properly_set(belle_sip_request_t *req){
/*check if automatic contacts could be set by provider, if not resubmit the request immediately.*/
belle_sip_header_contact_t *contact;
const belle_sip_list_t *l;
for (l=belle_sip_message_get_headers((belle_sip_message_t*)req,"Contact");l!=NULL;l=l->next){
contact=(belle_sip_header_contact_t*)l->data;
if (belle_sip_header_contact_is_unknown(contact)){
return FALSE;
}
}
return TRUE;
}
static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
......@@ -160,9 +171,17 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
/*update expire if needed*/
set_expires_from_trans(refresher);
if (refresher->target_expires<=0) {
belle_sip_refresher_stop(refresher); /*doesn not make sens to refresh if expire =0;*/
belle_sip_refresher_stop(refresher); /*doesn't not make sense to refresh if expire =0;*/
}
if (refresher->state==started) {
if (check_contact_properly_set(request)==FALSE){
belle_sip_message("Refresher [%p]: resubmitting request because contact sent was not correct in original request.",refresher);
belle_sip_refresher_refresh(refresher,refresher->target_expires);
return;
}else{
schedule_timer(refresher); /*re-arm timer*/
}
}
if (refresher->state==started) schedule_timer(refresher); /*re-arm timer*/
else belle_sip_message("Refresher [%p] not scheduling next refresh, because it was stopped",refresher);
break;
case 401:
......@@ -465,8 +484,14 @@ int belle_sip_refresher_start(belle_sip_refresher_t* refresher) {
belle_sip_warning("Refresher [%p] already started",refresher);
} else {
if (refresher->target_expires>0) {
belle_sip_request_t* request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction));
refresher->state=started;
schedule_timer(refresher);
if (check_contact_properly_set(request)==FALSE){
belle_sip_message("belle_sip_refresher_start(): refresher [%p] is resubmitting request because contact sent was not correct in original request.",refresher);
belle_sip_refresher_refresh(refresher, refresher->target_expires);
}else{
schedule_timer(refresher);
}
belle_sip_message("Refresher [%p] started, next refresh in [%i] s",refresher,refresher->obtained_expires);
}else{
belle_sip_message("Refresher [%p] stopped, expires=%i",refresher,refresher->target_expires);
......@@ -493,7 +518,7 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
if ( strcmp("REGISTER",belle_sip_request_get_method(request))!=0
&& strcmp("PUBLISH",belle_sip_request_get_method(request))!=0
&& state!=BELLE_SIP_TRANSACTION_TERMINATED
&& state != BELLE_SIP_TRANSACTION_COMPLETED) {
&& state!=BELLE_SIP_TRANSACTION_COMPLETED) {
belle_sip_error("Invalid state [%s] for %s 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(transaction)))
,belle_sip_request_get_method(request)
......@@ -517,9 +542,11 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
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);
belle_sip_message("Refresher [%p] takes ownership of transaction [%p]",refresher,transaction);
transaction->base.is_internal=1;
refresher->state=started;
}else{
belle_sip_refresher_start(refresher);
}
return refresher;
}
......
......@@ -206,7 +206,6 @@ void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *
belle_sip_header_to_set_tag(to,t->to_tag);
}
/*12.1 Creation of a Dialog
Dialogs are created through the generation of non-failure responses
to requests with specific methods. Within this specification, only
2xx and 101-199 responses with a To tag, where the request was
......@@ -490,11 +489,7 @@ 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 && !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))) {
belle_sip_refresher_start(refresher);
}
return refresher;
return belle_sip_refresher_new(t);
}
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos) {
......
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