Commit b6d22963 authored by Simon Morlat's avatar Simon Morlat

implement matching and handling of requests received from old rfc2543 stacks.

(to be tested).
parent 836a6cdf
......@@ -553,6 +553,7 @@ struct _belle_sip_request {
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*/
char *rfc2543_branch; /*computed 'branch' id in case we receive this request from an old RFC2543 stack*/
unsigned char dialog_queued;
};
......@@ -883,6 +884,7 @@ BELLESIP_INTERNAL_EXPORT char* belle_sip_to_unescaped_string(const char* buff) ;
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_request_set_rfc2543_branch(belle_sip_request_t *req, const char *rfc2543branch);
void belle_sip_dialog_update_request(belle_sip_dialog_t *dialog, belle_sip_request_t *req);
#endif
......@@ -332,6 +332,8 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* tra
belle_sip_request_t *req=belle_sip_transaction_get_request(transaction);
belle_sip_response_t *resp=belle_sip_transaction_get_response(transaction);
belle_sip_message("Dialog [%p]: now updated by transaction [%p].",obj, transaction);
belle_sip_object_ref(transaction);
if (obj->last_transaction) belle_sip_object_unref(obj->last_transaction);
obj->last_transaction=transaction;
......
......@@ -266,6 +266,7 @@ 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);
if (request->rfc2543_branch) belle_sip_free(request->rfc2543_branch);
}
static void belle_sip_request_init(belle_sip_request_t *message){
......@@ -274,6 +275,7 @@ static void belle_sip_request_init(belle_sip_request_t *message){
static void belle_sip_request_clone(belle_sip_request_t *request, const belle_sip_request_t *orig){
if (orig->method) request->method=belle_sip_strdup(orig->method);
if (orig->uri) request->uri=(belle_sip_uri_t*)belle_sip_object_ref(belle_sip_object_clone((belle_sip_object_t*)orig->uri));
if (orig->rfc2543_branch) request->rfc2543_branch=belle_sip_strdup(orig->rfc2543_branch);
}
belle_sip_error_code belle_sip_request_marshal(belle_sip_request_t* request, char* buff, size_t buff_size, size_t *offset) {
......@@ -295,6 +297,7 @@ belle_sip_error_code belle_sip_request_marshal(belle_sip_request_t* request, cha
BELLE_SIP_NEW(request,message)
BELLE_SIP_PARSE(request)
GET_SET_STRING(belle_sip_request,method);
GET_SET_STRING(belle_sip_request,rfc2543_branch);
void belle_sip_request_set_dialog(belle_sip_request_t *req, belle_sip_dialog_t *dialog){
if (dialog) belle_sip_object_ref(dialog);
......
......@@ -204,19 +204,59 @@ static void compute_hash_from_invariants(belle_sip_message_t *msg, char *branchi
if (prev_via){
size_t offset=0;
belle_sip_object_marshal((belle_sip_object_t*)prev_via,tmp,sizeof(tmp)-1,&offset);
belle_sip_md5_append(&ctx,(uint8_t*)tmp,strlen(tmp));
belle_sip_md5_append(&ctx,(uint8_t*)tmp,offset);
}
}else{
if (via){
size_t offset=0;
belle_sip_object_marshal((belle_sip_object_t*)via,tmp,sizeof(tmp)-1,&offset);
belle_sip_md5_append(&ctx,(uint8_t*)tmp,strlen(tmp));
belle_sip_md5_append(&ctx,(uint8_t*)tmp,offset);
}
}
belle_sip_md5_finish(&ctx,digest);
belle_sip_octets_to_text(digest,sizeof(digest),branchid,branchid_size);
}
static char *compute_rfc2543_branch(belle_sip_request_t *req, char *branchid, size_t branchid_size){
md5_state_t ctx;
unsigned int cseq=belle_sip_header_cseq_get_seq_number(belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t));
char tmp[256]={0};
uint8_t digest[16];
const char*callid=belle_sip_header_call_id_get_call_id(belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t));
const char *from_tag=belle_sip_header_from_get_tag(belle_sip_message_get_header_by_type(req,belle_sip_header_from_t));
const char *to_tag=belle_sip_header_to_get_tag(belle_sip_message_get_header_by_type(req,belle_sip_header_to_t));
belle_sip_uri_t *requri=NULL;
belle_sip_header_via_t *via=NULL;
const belle_sip_list_t *vias=belle_sip_message_get_headers((belle_sip_message_t*)req,"via");
requri=belle_sip_request_get_uri(req);
belle_sip_md5_init(&ctx);
if (requri){
size_t offset=0;
belle_sip_object_marshal((belle_sip_object_t*)requri,tmp,sizeof(tmp)-1,&offset);
belle_sip_md5_append(&ctx,(uint8_t*)tmp,strlen(tmp));
}
if (from_tag)
belle_sip_md5_append(&ctx,(uint8_t*)from_tag,strlen(from_tag));
if (to_tag)
belle_sip_md5_append(&ctx,(uint8_t*)to_tag,strlen(to_tag));
belle_sip_md5_append(&ctx,(uint8_t*)callid,strlen(callid));
belle_sip_md5_append(&ctx,(uint8_t*)&cseq,sizeof(cseq));
for(;vias!=NULL;vias=vias->next){
size_t offset=0;
via=(belle_sip_header_via_t*)vias->data;
belle_sip_object_marshal((belle_sip_object_t*)via,tmp,sizeof(tmp)-1,&offset);
belle_sip_md5_append(&ctx,(uint8_t*)tmp,offset);
}
belle_sip_md5_finish(&ctx,digest);
belle_sip_octets_to_text(digest,sizeof(digest),branchid,branchid_size);
return branchid;
}
static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan, belle_sip_message_t *msg){
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);
......@@ -665,7 +705,7 @@ struct transaction_matcher{
int is_ack_or_cancel;
};
static int rfc3261_transaction_match(const void *p_tr, const void *p_matcher){
static int transaction_match(const void *p_tr, const void *p_matcher){
belle_sip_transaction_t *tr=(belle_sip_transaction_t*)p_tr;
struct transaction_matcher *matcher=(struct transaction_matcher*)p_matcher;
const char *req_method=belle_sip_request_get_method(tr->request);
......@@ -681,19 +721,24 @@ belle_sip_transaction_t * belle_sip_provider_find_matching_transaction(belle_sip
belle_sip_header_via_t *via=(belle_sip_header_via_t*)belle_sip_message_get_header((belle_sip_message_t*)req,"via");
belle_sip_transaction_t *ret=NULL;
belle_sip_list_t *elem=NULL;
if (via==NULL){
belle_sip_warning("Request has no via.");
return NULL;
}
matcher.branchid=belle_sip_header_via_get_branch(via);
const char *branch;
char token[BELLE_SIP_BRANCH_ID_LENGTH];
matcher.method=belle_sip_request_get_method(req);
matcher.is_ack_or_cancel=(strcmp(matcher.method,"ACK")==0 || strcmp(matcher.method,"CANCEL")==0);
if (strncmp(matcher.branchid,BELLE_SIP_BRANCH_MAGIC_COOKIE,strlen(BELLE_SIP_BRANCH_MAGIC_COOKIE))==0){
/*compliant to RFC3261*/
elem=belle_sip_list_find_custom(transactions,rfc3261_transaction_match,&matcher);
if (via!=NULL && (branch=belle_sip_header_via_get_branch(via))!=NULL &&
strncmp(branch,BELLE_SIP_BRANCH_MAGIC_COOKIE,strlen(BELLE_SIP_BRANCH_MAGIC_COOKIE))==0){
matcher.branchid=branch;
}else{
//FIXME
/*this request comes from an old equipment, we need to compute our own branch for this request.*/
matcher.branchid=compute_rfc2543_branch(req,token,sizeof(token));
belle_sip_request_set_rfc2543_branch(req,token);
belle_sip_message("Message from old RFC2543 stack, computed branch is %s", token);
}
elem=belle_sip_list_find_custom(transactions,transaction_match,&matcher);
if (elem){
ret=(belle_sip_transaction_t*)elem->data;
......
......@@ -91,6 +91,7 @@ const char *belle_sip_transaction_get_branch_id(const belle_sip_transaction_t *t
belle_sip_transaction_state_t belle_sip_transaction_get_state(const belle_sip_transaction_t *t){
return t->state;
}
int belle_sip_transaction_state_is_transient(const belle_sip_transaction_state_t state) {
switch(state){
case BELLE_SIP_TRANSACTION_INIT:
......@@ -100,9 +101,9 @@ int belle_sip_transaction_state_is_transient(const belle_sip_transaction_state_t
return 1;
default:
return 0;
}
}
void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t))!=BELLE_SIP_TRANSACTION_TERMINATED) {
belle_sip_transaction_set_state(t,BELLE_SIP_TRANSACTION_TERMINATED);
......@@ -182,8 +183,15 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_server_transaction_t)={
};
void belle_sip_server_transaction_init(belle_sip_server_transaction_t *t, belle_sip_provider_t *prov,belle_sip_request_t *req){
const char *branch;
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
t->base.branch_id=belle_sip_strdup(belle_sip_header_via_get_branch(via));
branch=belle_sip_header_via_get_branch(via);
if (branch==NULL){
branch=req->rfc2543_branch;
if (branch==NULL) belle_sip_fatal("No computed branch for RFC2543 style of message, this should never happen.");
}
t->base.branch_id=belle_sip_strdup(branch);
belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req);
belle_sip_random_token(t->to_tag,sizeof(t->to_tag));
}
......
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