Commit e43c0000 authored by Simon Morlat's avatar Simon Morlat

implement transaction queue in dialog, to avoid rejecting new requests while...

implement transaction queue in dialog, to avoid rejecting new requests while there is pending transaction within this dialog.
remove circular references between dialog and transaction
optimize dialog matching for client transaction (avoid lookup in dialog list)
parent 64a97bd3
......@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.61])
AC_INIT([belle-sip], [1.1.0], [jehan.monnier@linphone.org])
AC_INIT([belle-sip], [1.2.0], [jehan.monnier@linphone.org])
AC_CONFIG_SRCDIR([src/belle_sip_utils.c])
AC_CONFIG_HEADERS([config.h])
......
......@@ -44,6 +44,8 @@ BELLESIP_EXPORT belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_d
*/
BELLESIP_EXPORT belle_sip_request_t * belle_sip_dialog_create_request_from(belle_sip_dialog_t *obj, const belle_sip_request_t *initial_req);
BELLESIP_EXPORT belle_sip_request_t * belle_sip_dialog_create_queued_request(belle_sip_dialog_t *obj, const char *method);
BELLESIP_EXPORT void belle_sip_dialog_delete(belle_sip_dialog_t *dialog);
BELLESIP_EXPORT void *belle_sip_dialog_get_application_data(const belle_sip_dialog_t *dialog);
......
......@@ -31,6 +31,7 @@ BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_last_elem(const belle_sip_list
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_free(belle_sip_list_t * elem);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_concat(belle_sip_list_t * first, belle_sip_list_t * second);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_remove(belle_sip_list_t * first, void *data);
BELLESIP_EXPORT belle_sip_list_t * belle_sip_list_pop_front(belle_sip_list_t *list, void **front_data);
BELLESIP_EXPORT int belle_sip_list_size(const belle_sip_list_t * first);
BELLESIP_EXPORT void belle_sip_list_for_each(const belle_sip_list_t * list, void (*func)(void *));
BELLESIP_EXPORT void belle_sip_list_for_each2(const belle_sip_list_t * list, void (*func)(void *, void *), void *user_data);
......
......@@ -541,6 +541,21 @@ typedef struct listener_ctx{
BELLE_SIP_INVOKE_LISTENERS_ARG((listeners),belle_sip_listener_t,callback,(event))
struct _belle_sip_message {
belle_sip_object_t base;
belle_sip_list_t* header_list;
char* body;
unsigned int body_length;
};
struct _belle_sip_request {
belle_sip_message_t message;
char* method;
belle_sip_uri_t* uri;
belle_sip_dialog_t *dialog;/*set if request was created by a dialog to avoid to search in dialog list*/
unsigned char dialog_queued;
};
/*
belle_sip_transaction_t
*/
......@@ -555,8 +570,8 @@ struct belle_sip_transaction{
char *branch_id;
belle_sip_transaction_state_t state;
void *appdata;
unsigned int is_internal:1;
unsigned int timed_out:1;
unsigned char is_internal;
unsigned char timed_out;
};
......@@ -710,12 +725,13 @@ struct belle_sip_dialog{
char *remote_tag;
unsigned int local_cseq;
unsigned int remote_cseq;
int is_server:1;
int is_secure:1;
int terminate_on_bye:1;
int needs_ack:1;
belle_sip_transaction_t* last_transaction;
belle_sip_header_privacy_t* privacy;
belle_sip_list_t *queued_ct;/* queued client transactions*/
unsigned char is_server;
unsigned char is_secure;
unsigned char terminate_on_bye;
unsigned char needs_ack;
};
belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t);
......@@ -727,6 +743,7 @@ int belle_sip_dialog_match(belle_sip_dialog_t *obj, belle_sip_message_t *msg, in
int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* transaction, int as_uas);
void belle_sip_dialog_check_ack_sent(belle_sip_dialog_t*obj);
int belle_sip_dialog_handle_ack(belle_sip_dialog_t *obj, belle_sip_request_t *ack);
void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle_sip_client_transaction_t *tr);
/*
belle_sip_response_t
......@@ -865,5 +882,7 @@ BELLESIP_INTERNAL_EXPORT char* belle_sip_to_unescaped_string(const char* buff) ;
#define BELLE_SIP_MAX_TO_STRING_SIZE 2048
void belle_sip_header_contact_set_unknown(belle_sip_header_contact_t *a, int value);
void belle_sip_request_set_dialog(belle_sip_request_t *req, belle_sip_dialog_t *dialog);
void belle_sip_dialog_update_request(belle_sip_dialog_t *dialog, belle_sip_request_t *req);
#endif
......@@ -294,6 +294,16 @@ void belle_sip_list_for_each2(const belle_sip_list_t* list, void (*func)(void *,
}
}
belle_sip_list_t * belle_sip_list_pop_front(belle_sip_list_t *list, void **front_data){
if (list==NULL){
*front_data=NULL;
return NULL;
}
*front_data=list->data;
list=belle_sip_list_remove_link(list,list);
return list;
}
belle_sip_list_t* belle_sip_list_remove_link(belle_sip_list_t* list, belle_sip_list_t* elem){
belle_sip_list_t* ret;
if (elem==list){
......
This diff is collapsed.
......@@ -37,13 +37,6 @@ static void belle_sip_headers_container_delete(headers_container_t *obj){
belle_sip_free(obj);
}
struct _belle_sip_message {
belle_sip_object_t base;
belle_sip_list_t* header_list;
char* body;
unsigned int body_length;
};
static void belle_sip_message_destroy(belle_sip_message_t *msg){
belle_sip_list_free_with_data(msg->header_list,(void (*)(void*))belle_sip_headers_container_delete);
if (msg->body)
......@@ -269,15 +262,10 @@ belle_sip_error_code belle_sip_headers_marshal(belle_sip_message_t *message, cha
return error;
}
struct _belle_sip_request {
belle_sip_message_t message;
char* method;
belle_sip_uri_t* uri;
};
static void belle_sip_request_destroy(belle_sip_request_t* request) {
if (request->method) belle_sip_free(request->method);
if (request->uri) belle_sip_object_unref(request->uri);
if (request->dialog) belle_sip_object_unref(request->dialog);
}
static void belle_sip_request_init(belle_sip_request_t *message){
......@@ -308,6 +296,16 @@ BELLE_SIP_NEW(request,message)
BELLE_SIP_PARSE(request)
GET_SET_STRING(belle_sip_request,method);
void belle_sip_request_set_dialog(belle_sip_request_t *req, belle_sip_dialog_t *dialog){
if (dialog) belle_sip_object_ref(dialog);
if (req->dialog) {
belle_sip_object_unref(req->dialog);
req->dialog=NULL;
}
req->dialog=dialog;
}
void belle_sip_request_set_uri(belle_sip_request_t* request,belle_sip_uri_t* uri) {
belle_sip_object_ref(uri);
if (request->uri) {
......
......@@ -221,15 +221,11 @@ static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan,
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(msg,"via"));
if (p->rport_enabled) belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"rport",NULL);
if (belle_sip_header_via_get_host(via)==NULL){
const char *local_ip;
int local_port;
local_ip=belle_sip_channel_get_local_address(chan,&local_port);
belle_sip_header_via_set_host(via,local_ip);
belle_sip_header_via_set_port(via,local_port);
belle_sip_header_via_set_protocol(via,"SIP/2.0");
belle_sip_header_via_set_transport(via,belle_sip_channel_get_transport_name(chan));
}
belle_sip_header_via_set_host(via,chan->local_ip);
belle_sip_header_via_set_port(via,chan->local_port);
belle_sip_header_via_set_protocol(via,"SIP/2.0");
belle_sip_header_via_set_transport(via,belle_sip_channel_get_transport_name(chan));
if (belle_sip_header_via_get_branch(via)==NULL){
/*branch id should not be set random here (stateless forwarding): but rather a hash of message invariants*/
char branchid[24];
......@@ -408,12 +404,18 @@ belle_sip_dialog_t *belle_sip_provider_find_dialog_from_msg(belle_sip_provider_t
belle_sip_dialog_t *returned_dialog=NULL;
belle_sip_header_call_id_t *call_id;
belle_sip_header_from_t *from;
belle_sip_header_to_t *to=belle_sip_message_get_header_by_type(msg,belle_sip_header_to_t);
belle_sip_header_to_t *to;
const char *from_tag;
const char *to_tag;
const char *call_id_value;
const char *local_tag,*remote_tag;
if (msg->dialog){
return msg->dialog;
}
to=belle_sip_message_get_header_by_type(msg,belle_sip_header_to_t);
if (to==NULL || (to_tag=belle_sip_header_to_get_tag(to))==NULL){
/* a request without to tag cannot be part of a dialog */
return NULL;
......@@ -491,6 +493,8 @@ belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(bel
}
}
belle_sip_transaction_set_dialog((belle_sip_transaction_t*)t,belle_sip_provider_find_dialog_from_msg(prov,req,FALSE));
belle_sip_request_set_dialog(req,NULL);/*get rid of the reference to the dialog, which is no longer needed in the message.
This is to avoid circular references.*/
return t;
}
......
......@@ -112,6 +112,12 @@ void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
,t);
BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_terminate(t);
belle_sip_provider_set_transaction_terminated(t->provider,t);
/*remove reference to the dialog to avoid circular references*/
if (t->dialog){
belle_sip_object_unref(t->dialog);
t->dialog=NULL;
}
}
}
......@@ -153,9 +159,6 @@ void belle_sip_transaction_set_dialog(belle_sip_transaction_t *t, belle_sip_dial
if (dialog) belle_sip_object_ref(dialog);
if (t->dialog) belle_sip_object_unref(t->dialog); /*to avoid keeping unexpected ref*/
t->dialog=dialog;
if (t->dialog){
belle_sip_dialog_update(dialog,t,BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t));
}
}
/*
......@@ -304,9 +307,11 @@ int belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t)
return belle_sip_client_transaction_send_request_to(t,NULL);
}
int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t *t,belle_sip_uri_t* outbound_proxy) {
belle_sip_channel_t *chan;
belle_sip_provider_t *prov=t->base.provider;
belle_sip_dialog_t *dialog=t->base.dialog;
int result=-1;
if (t->base.state!=BELLE_SIP_TRANSACTION_INIT){
......@@ -315,11 +320,33 @@ int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t
}
/*store preset route for future use by refresher*/
t->preset_route=outbound_proxy;
if (t->preset_route) belle_sip_object_ref(t->preset_route);
if (outbound_proxy){
t->preset_route=outbound_proxy;
belle_sip_object_ref(t->preset_route);
}
if (t->base.request->dialog_queued){
/*this request was created by belle_sip_dialog_create_queued_request().*/
if (belle_sip_dialog_request_pending(dialog)){
/*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, so queuing into dialog.",t);
belle_sip_dialog_queue_client_transaction(dialog,t);
return 0;
}else{
belle_sip_request_t *req=t->base.request;
/*it can be sent immediately, so update the request with latest cseq and route_set */
/*update route and contact just in case they changed*/
belle_sip_dialog_update_request(dialog,req);
}
}
if (dialog){
belle_sip_dialog_update(dialog,(belle_sip_transaction_t*)t,BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t));
}
if (!t->next_hop) {
if (outbound_proxy) {
t->next_hop=belle_sip_hop_new_from_uri(outbound_proxy);
if (t->preset_route) {
t->next_hop=belle_sip_hop_new_from_uri(t->preset_route);
} else {
t->next_hop = belle_sip_stack_get_next_hop(prov->stack,t->base.request);
}
......@@ -347,7 +374,6 @@ int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t
belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(t));
result=-1;
}
return result;
}
......
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