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){
......
......@@ -21,6 +21,8 @@
static void belle_sip_dialog_init_200Ok_retrans(belle_sip_dialog_t *obj, belle_sip_response_t *resp);
static void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj);
static int belle_sip_dialog_handle_200Ok(belle_sip_dialog_t *obj, belle_sip_response_t *msg);
static void belle_sip_dialog_process_queue(belle_sip_dialog_t* dialog);
static belle_sip_request_t *create_request(belle_sip_dialog_t *obj, const char *method, int full);
static void belle_sip_dialog_uninit(belle_sip_dialog_t *obj){
if (obj->route_set)
......@@ -326,6 +328,7 @@ static void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj){
int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* transaction, int as_uas){
int code;
int is_retransmition=FALSE;
int delete_dialog=FALSE;
belle_sip_request_t *req=belle_sip_transaction_get_request(transaction);
belle_sip_response_t *resp=belle_sip_transaction_get_response(transaction);
......@@ -349,30 +352,31 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* tra
break;
case BELLE_SIP_DIALOG_CONFIRMED:
code=belle_sip_response_get_status_code(resp);
if (strcmp(belle_sip_request_get_method(req),"INVITE")==0 && 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 (strcmp(belle_sip_request_get_method(req),"INVITE")==0){
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;
} else {
obj->needs_ack=TRUE; /*REINVITE case, ack needed by both uas and uac*/
}
}else if (code>=300){
/*final response, ack will be automatically sent by transaction layer*/
obj->needs_ack=FALSE;
}
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;
} else {
obj->needs_ack=TRUE; /*REINVITE case, ack needed by both uas and uac*/
}
}if (strcmp(belle_sip_request_get_method(req),"INVITE")==0 && code >=300) {
/*final response, ack will be automatically sent by transaction layer*/
obj->needs_ack=FALSE;
} else if (strcmp(belle_sip_request_get_method(req),"BYE")==0 && (/*(*/code>=200 /*&& code<300) || code==481 || code==408*/)){
/*15.1.1 UAC Behavior
......@@ -389,14 +393,18 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* tra
returned by the client transaction), the UAC MUST consider the
session and the dialog terminated. */
/*what should we do with other reponse >300 ?? */
if (obj->terminate_on_bye) belle_sip_dialog_delete(obj);
obj->needs_ack=FALSE; /*no longuer need ACK*/
if (obj->terminate_on_bye) delete_dialog=TRUE;
}
break;
case BELLE_SIP_DIALOG_TERMINATED:
/*ignore*/
break;
}
if (delete_dialog) belle_sip_dialog_delete(obj);
else {
belle_sip_dialog_process_queue(obj);
}
return 0;
}
......@@ -459,6 +467,7 @@ belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *obj, unsign
belle_sip_header_cseq_t *cseqh;
belle_sip_request_t *invite=obj->last_out_invite;
belle_sip_request_t *ack;
if (!invite){
belle_sip_error("No INVITE to ACK.");
return NULL;
......@@ -468,7 +477,7 @@ belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *obj, unsign
belle_sip_error("No INVITE with cseq %i to create ack for.",cseq);
return NULL;
}
ack=belle_sip_dialog_create_request(obj,"ACK");
ack=create_request(obj,"ACK",TRUE);
/*
22 Usage of HTTP Authentication
22.1 Framework
......@@ -495,21 +504,9 @@ belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *obj, unsign
return ack;
}
belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *obj, const char *method){
static belle_sip_request_t *create_request(belle_sip_dialog_t *obj, const char *method, int full){
belle_sip_request_t *req;
if (obj->state != BELLE_SIP_DIALOG_CONFIRMED && obj->state != BELLE_SIP_DIALOG_EARLY) {
belle_sip_error("belle_sip_dialog_create_request(): cannot create [%s] request from dialog [%p] in state [%s]",method,obj,belle_sip_dialog_state_to_string(obj->state));
return NULL;
}
if (strcmp(method,"BYE")!=0 && obj->last_transaction && belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(obj->last_transaction))){
/*don't prevent to send a BYE in any case */
belle_sip_error("belle_sip_dialog_create_request(): cannot create [%s] request from dialog [%p] while pending transaction in state [%s]",method,obj,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(obj->last_transaction)));
return NULL;
}
if (obj->local_cseq==0) obj->local_cseq=110;
if (strcmp(method,"ACK")!=0) obj->local_cseq++;
req=belle_sip_request_create(belle_sip_header_address_get_uri(obj->remote_target),
method,
obj->call_id,
......@@ -518,12 +515,50 @@ belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *obj, co
belle_sip_header_to_create(obj->remote_party,NULL),
belle_sip_header_via_new(),
0);
if (obj->route_set) {
if (full && obj->route_set) {
belle_sip_message_add_headers((belle_sip_message_t*)req,obj->route_set);
}
if (obj->privacy) {
belle_sip_message_add_header((belle_sip_message_t*)req,BELLE_SIP_HEADER(obj->privacy));
}
belle_sip_request_set_dialog(req,obj);
return req;
}
BELLESIP_EXPORT belle_sip_request_t * belle_sip_dialog_create_queued_request(belle_sip_dialog_t *obj, const char *method){
belle_sip_request_t *req;
if (strcmp(method,"INVITE")==0 || strcmp(method,"SUBSCRIBE")==0){
/*we don't allow requests that can update the dialog's state to be sent asynchronously*/
belle_sip_error("belle_sip_dialog_create_queued_request([%p]): [%s] requests are forbidden using this method.",obj,method);
return NULL;
}
req=create_request(obj,method,FALSE);
req->dialog_queued=TRUE;
return req;
}
static void belle_sip_dialog_update_local_cseq(belle_sip_dialog_t *obj, const char *method){
if (obj->local_cseq==0) obj->local_cseq=110;
if (strcmp(method,"ACK")!=0) obj->local_cseq++;
}
belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *obj, const char *method){
belle_sip_request_t *req;
if (obj->state != BELLE_SIP_DIALOG_CONFIRMED && obj->state != BELLE_SIP_DIALOG_EARLY) {
belle_sip_error("belle_sip_dialog_create_request(): cannot create [%s] request from dialog [%p] in state [%s]",method,obj,belle_sip_dialog_state_to_string(obj->state));
return NULL;
}
if (strcmp(method,"BYE")!=0 && obj->last_transaction && belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(obj->last_transaction))){
/*don't prevent to send a BYE in any case */
belle_sip_error("belle_sip_dialog_create_request(): cannot create [%s] request from dialog [%p] while pending transaction in state [%s]",method,obj,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(obj->last_transaction)));
return NULL;
}
belle_sip_dialog_update_local_cseq(obj,method);
req=create_request(obj,method,TRUE);
return req;
}
......@@ -569,8 +604,14 @@ belle_sip_request_t *belle_sip_dialog_create_request_from(belle_sip_dialog_t *ob
}
void belle_sip_dialog_delete(belle_sip_dialog_t *obj){
int dropped_transactions;
belle_sip_dialog_stop_200Ok_retrans(obj); /*if any*/
set_state(obj,BELLE_SIP_DIALOG_TERMINATED);
dropped_transactions=belle_sip_list_size(obj->queued_ct);
if (dropped_transactions>0) belle_sip_warning("dialog [%p]: leaves %i queued transaction aborted.",obj,dropped_transactions);
belle_sip_list_for_each(obj->queued_ct,(void(*)(void*))belle_sip_transaction_terminate);
obj->queued_ct=belle_sip_list_free_with_data(obj->queued_ct,belle_sip_object_unref);
belle_sip_provider_remove_dialog(obj->provider,obj);
}
......@@ -644,6 +685,7 @@ void belle_sip_dialog_send_ack(belle_sip_dialog_t *obj, belle_sip_request_t *req
belle_sip_object_unref(obj->last_out_ack);
obj->last_out_ack=(belle_sip_request_t*)belle_sip_object_ref(request);
belle_sip_provider_send_request(obj->provider,request);
belle_sip_dialog_process_queue(obj);
}else{
belle_sip_error("Why do you want to send an ACK ?");
}
......@@ -715,6 +757,7 @@ int belle_sip_dialog_handle_ack(belle_sip_dialog_t *obj, belle_sip_request_t *ac
belle_sip_message("Incoming INVITE has ACK, dialog is happy");
obj->needs_ack=FALSE;
belle_sip_dialog_stop_200Ok_retrans(obj);
belle_sip_dialog_process_queue(obj);
return 0;
}
belle_sip_message("Dialog ignoring incoming ACK (surely a retransmission)");
......@@ -749,6 +792,7 @@ belle_sip_transaction_t* belle_sip_dialog_get_last_transaction(const belle_sip_d
}
int belle_sip_dialog_request_pending(const belle_sip_dialog_t *dialog){
if (dialog->needs_ack) return TRUE;
return dialog->last_transaction ? belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(dialog->last_transaction)) : FALSE;
}
......@@ -791,3 +835,29 @@ int belle_sip_dialog_is_authorized_transaction(const belle_sip_dialog_t *dialog,
return TRUE;
}
}
void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle_sip_client_transaction_t *tr){
dialog->queued_ct=belle_sip_list_append(dialog->queued_ct, belle_sip_object_ref(tr));
}
void belle_sip_dialog_process_queue(belle_sip_dialog_t* dialog){
belle_sip_client_transaction_t *tr=NULL;
if (belle_sip_dialog_request_pending(dialog)) return;
dialog->queued_ct=belle_sip_list_pop_front(dialog->queued_ct,(void**)&tr);
if (tr){
belle_sip_message("Dialog [%p]: sending queued request.",dialog);
belle_sip_client_transaction_send_request(tr);
belle_sip_object_unref(tr);
}
}
void belle_sip_dialog_update_request(belle_sip_dialog_t *dialog, belle_sip_request_t *req){
belle_sip_header_cseq_t *cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
belle_sip_dialog_update_local_cseq(dialog,belle_sip_request_get_method(req));
if (dialog->route_set)
belle_sip_message_add_headers((belle_sip_message_t*)req,dialog->route_set);
belle_sip_request_set_uri(req,belle_sip_header_address_get_uri(dialog->remote_target));
belle_sip_header_cseq_set_seq_number(cseq,dialog->local_cseq);
}
......@@ -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