Commit 7032fc5d authored by jehan's avatar jehan
Browse files

Merge branch 'master' of gitosis@git.linphone.org:belle-sip

parents f56dbf86 63fe8e76
......@@ -40,7 +40,7 @@ BELLE_SIP_DECLARE_INTERFACE_END
belle_sip_response_t* belle_sip_response_event_get_response(const belle_sip_response_event_t* event);
belle_sip_client_transaction_t *belle_sip_response_event_get_client_transaction(const belle_sip_response_event_t* event);
......
......@@ -45,11 +45,13 @@ libbellesip_la_SOURCES= \
message.c \
md5.c md5.h \
auth_helper.c \
siplistener.c \
ict.c \
nict.c \
transports/udp_listeningpoint.c \
transports/udp_channel.c \
transports/stream_channel.c \
transports/stream_channel.h \
transports/stream_listeningpoint.c \
transports/tls_listeningpoint.c
if BUILD_TLS
......
......@@ -511,7 +511,7 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_client_transaction_t,belle_sip_tra
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, belle_sip_provider_t *prov, belle_sip_request_t *req);
void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp);
int belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp);
struct belle_sip_ict{
belle_sip_client_transaction_t base;
......
......@@ -525,13 +525,13 @@ unsigned int belle_sip_random(void){
* Write a random text token of supplied size.
**/
char * belle_sip_random_token(char *ret, size_t size){
static const char *symbols="0123456789abcdefghijklmnopqrstuvwxyz";
static const char *symbols="aAbBcCdDeEfFgGhHiIjJkKlLmMnN0pPqQrRsStTuUvVwWxXyYzZ";
unsigned int val;
int i,j;
for(i=0,j=0;i<size-1;++i,++j){
if (j%8==0) val=belle_sip_random();
if (j%6==0) val=belle_sip_random();
ret[i]=symbols[val & 31];
val=val>>4;
val=val>>5;
}
ret[i]=0;
return ret;
......
......@@ -134,7 +134,6 @@ static void nict_send_request(belle_sip_nict_t *obj){
belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)base->request);
if (!belle_sip_channel_is_reliable(base->channel)){
belle_sip_message("channel is not reliable");
obj->timer_E=belle_sip_timeout_source_new((belle_sip_source_func_t)nict_on_timer_E,obj,cfg->T1);
belle_sip_transaction_start_timer(base,obj->timer_E);
}
......
......@@ -29,8 +29,6 @@ static void channel_state_changed(belle_sip_channel_listener_t *obj, belle_sip_c
}
static void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, belle_sip_message_t *msg){
/*should find existing transaction*/
if (belle_sip_message_is_request(msg)){
belle_sip_request_event_t event;
event.source=prov;
......@@ -40,12 +38,17 @@ static void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, bell
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov,process_request_event,&event);
}else{
belle_sip_response_event_t event;
int pass=1;
event.source=prov;
event.client_transaction=NULL;
event.client_transaction=belle_sip_provider_find_matching_client_transaction(prov,(belle_sip_response_t*)msg);
event.dialog=NULL;
event.response=(belle_sip_response_t*)msg;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov,process_response_event,&event);
if (event.client_transaction){
pass=belle_sip_client_transaction_add_response(event.client_transaction,event.response);
}
if (pass) BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov,process_response_event,&event);
}
belle_sip_object_unref(msg);
}
......@@ -169,17 +172,20 @@ void belle_sip_provider_remove_sip_listener(belle_sip_provider_t *p, belle_sip_l
belle_sip_header_call_id_t * belle_sip_provider_create_call_id(belle_sip_provider_t *prov){
belle_sip_header_call_id_t *cid=belle_sip_header_call_id_new();
char tmp[32];
snprintf(tmp,sizeof(tmp),"%u",belle_sip_random());
belle_sip_header_call_id_set_call_id(cid,tmp);
char tmp[11];
belle_sip_header_call_id_set_call_id(cid,belle_sip_random_token(tmp,sizeof(tmp)));
return cid;
}
belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(belle_sip_provider_t *prov, belle_sip_request_t *req){
if (strcmp(belle_sip_request_get_method(req),"INVITE")==0)
const char *method=belle_sip_request_get_method(req);
if (strcmp(method,"INVITE")==0)
return (belle_sip_client_transaction_t*)belle_sip_ict_new(prov,req);
else
return (belle_sip_client_transaction_t*)belle_sip_nict_new(prov,req);
else if (strcmp(method,"ACK")==0){
belle_sip_error("belle_sip_provider_create_client_transaction() cannot be used for ACK requests.");
return NULL;
}
else return (belle_sip_client_transaction_t*)belle_sip_nict_new(prov,req);
}
belle_sip_server_transaction_t *belle_sip_provider_create_server_transaction(belle_sip_provider_t *prov, belle_sip_request_t *req){
......@@ -233,9 +239,7 @@ void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_respons
if (chan) belle_sip_channel_queue_message(chan,BELLE_SIP_MESSAGE(resp));
}
belle_sip_response_t* belle_sip_response_event_get_response(const belle_sip_response_event_t* event) {
return event->response;
}
/*private provider API*/
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t){
......@@ -248,11 +252,45 @@ void belle_sip_provider_add_client_transaction(belle_sip_provider_t *prov, belle
prov->client_transactions=belle_sip_list_prepend(prov->client_transactions,belle_sip_object_ref(t));
}
struct client_transaction_matcher{
const char *branchid;
const char *method;
};
static int client_transaction_match(const void *p_tr, const void *p_matcher){
belle_sip_client_transaction_t *tr=(belle_sip_client_transaction_t*)p_tr;
struct client_transaction_matcher *matcher=(struct client_transaction_matcher*)p_matcher;
const char *req_method=belle_sip_request_get_method(tr->base.request);
if (strcmp(matcher->branchid,tr->base.branch_id)==0 && strcmp(matcher->method,req_method)==0) return 0;
return -1;
}
belle_sip_client_transaction_t * belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t *prov,
belle_sip_response_t *resp){
return NULL;
struct client_transaction_matcher matcher;
belle_sip_header_via_t *via=(belle_sip_header_via_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"via");
belle_sip_header_cseq_t *cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"cseq");
belle_sip_client_transaction_t *ret=NULL;
belle_sip_list_t *elem;
if (via==NULL){
belle_sip_warning("Response has no via.");
return NULL;
}
if (via==NULL){
belle_sip_warning("Response has no cseq.");
return NULL;
}
matcher.branchid=belle_sip_header_via_get_branch(via);
matcher.method=belle_sip_header_cseq_get_method(cseq);
elem=belle_sip_list_find_custom(prov->client_transactions,client_transaction_match,&matcher);
if (elem){
ret=(belle_sip_client_transaction_t*)elem->data;
belle_sip_message("Found transaction matching response.");
}
return ret;
}
void belle_sip_provider_remove_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t){
void belle_sip_provider_remove_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t){
prov->client_transactions=belle_sip_list_remove(prov->client_transactions,t);
belle_sip_object_unref(t);
}
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle_sip_internal.h"
belle_sip_response_t* belle_sip_response_event_get_response(const belle_sip_response_event_t* event) {
return event->response;
}
belle_sip_client_transaction_t *belle_sip_response_event_get_client_transaction(const belle_sip_response_event_t* event){
return event->client_transaction;
}
......@@ -18,6 +18,27 @@
#include "belle_sip_internal.h"
const char *belle_sip_transaction_state_to_string(belle_sip_transaction_state_t state){
switch(state){
case BELLE_SIP_TRANSACTION_INIT:
return "INIT";
case BELLE_SIP_TRANSACTION_TRYING:
return "TRYING";
case BELLE_SIP_TRANSACTION_CALLING:
return "CALLING";
case BELLE_SIP_TRANSACTION_COMPLETED:
return "COMPLETED";
case BELLE_SIP_TRANSACTION_CONFIRMED:
return "CONFIRMED";
case BELLE_SIP_TRANSACTION_PROCEEDING:
return "PROCEEDING";
case BELLE_SIP_TRANSACTION_TERMINATED:
return "TERMINATED";
}
belle_sip_fatal("Invalid transaction state.");
return "INVALID";
}
static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_provider_t *prov, belle_sip_request_t *req){
t->request=(belle_sip_request_t*)belle_sip_object_ref(req);
t->provider=prov;
......@@ -119,8 +140,44 @@ void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *
*/
static void clone_headers(belle_sip_message_t *orig, belle_sip_message_t *dest, const char*header, int multiple){
const belle_sip_list_t *elem;
elem=belle_sip_message_get_headers(orig,header);
for (;elem!=NULL;elem=elem->next){
belle_sip_header_t *ref_header=(belle_sip_header_t*)elem->data;
if (ref_header){
belle_sip_message_add_header(dest,
(belle_sip_header_t*)belle_sip_object_clone((belle_sip_object_t*)ref_header));
}
if (!multiple) break; /*just one*/
}
}
belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t){
return NULL;
belle_sip_message_t *orig=(belle_sip_message_t*)t->base.request;
belle_sip_request_t *req;
const char *orig_method=belle_sip_request_get_method((belle_sip_request_t*)orig);
if (strcmp(orig_method,"ACK")==0 || strcmp(orig_method,"INVITE")!=0){
belle_sip_error("belle_sip_client_transaction_create_cancel() cannot be used for ACK or non-INVITE transactions.");
return NULL;
}
if (t->base.state==BELLE_SIP_TRANSACTION_PROCEEDING){
belle_sip_error("belle_sip_client_transaction_create_cancel() can only be used in state BELLE_SIP_TRANSACTION_PROCEEDING"
" but current transaction state is %s",belle_sip_transaction_state_to_string(t->base.state));
}
req=belle_sip_request_new();
belle_sip_request_set_method(req,"CANCEL");
belle_sip_request_set_uri(req,(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri((belle_sip_request_t*)orig)));
clone_headers(orig,(belle_sip_message_t*)req,"via",FALSE);
clone_headers(orig,(belle_sip_message_t*)req,"call-id",FALSE);
clone_headers(orig,(belle_sip_message_t*)req,"from",FALSE);
clone_headers(orig,(belle_sip_message_t*)req,"to",FALSE);
clone_headers(orig,(belle_sip_message_t*)req,"route",TRUE);
belle_sip_message_add_header((belle_sip_message_t*)req,
(belle_sip_header_t*)belle_sip_header_cseq_create(
belle_sip_header_cseq_get_seq_number((belle_sip_header_cseq_t*)belle_sip_message_get_header(orig,"cseq")),
"CANCEL"));
return req;
}
......@@ -147,22 +204,15 @@ void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t
}else belle_sip_error("belle_sip_client_transaction_send_request(): no channel available");
}
void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
int belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)t;
int pass=BELLE_SIP_OBJECT_VPTR(t,belle_sip_client_transaction_t)->on_response(t,resp);
if (pass){
belle_sip_response_event_t ev;
if (base->prov_response)
belle_sip_object_unref(base->prov_response);
base->prov_response=(belle_sip_response_t*)belle_sip_object_ref(resp);
ev.source=base->provider;
ev.response=resp;
ev.client_transaction=t;
ev.dialog=NULL;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(base->provider,process_response_event,&ev);
}
return pass;
}
static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
......@@ -206,11 +256,16 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_client_transaction_t)={
void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
char token[10];
obj->base.branch_id=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",belle_sip_random_token(token,sizeof(token)));
if (via){
if (!via){
belle_sip_fatal("belle_sip_client_transaction_init(): No via in request.");
}
if (strcmp(belle_sip_request_get_method(req),"CANCEL")!=0){
obj->base.branch_id=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",belle_sip_random_token(token,sizeof(token)));
belle_sip_header_via_set_branch(via,obj->base.branch_id);
}else{
belle_sip_fatal("belle_sip_client_transaction_init(): No via in request.");
obj->base.branch_id=belle_sip_strdup(belle_sip_header_via_get_branch(via));
}
belle_sip_transaction_init((belle_sip_transaction_t*)obj, prov,req);
}
......
......@@ -23,6 +23,7 @@
const char *test_domain="localhost";
static int is_register_ok;
static int using_transaction;
static belle_sip_stack_t * stack;
static belle_sip_provider_t *prov;
......@@ -40,7 +41,7 @@ static void process_response_event(belle_sip_listener_t *obj, const belle_sip_re
CU_ASSERT_PTR_NOT_NULL_FATAL(belle_sip_response_event_get_response(event));
CU_ASSERT_EQUAL(belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)),200);
is_register_ok=1;
belle_sip_object_unref(belle_sip_response_event_get_response(event));
using_transaction=belle_sip_response_event_get_client_transaction(event)!=NULL;
belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
}
static void process_timeout(belle_sip_listener_t *obj, const belle_sip_timeout_event_t *event){
......@@ -121,6 +122,7 @@ static void register_test(const char *transport, int use_transaction) {
70);
is_register_ok=0;
using_transaction=0;
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(600)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_contact_new()));
if (use_transaction){
......@@ -129,6 +131,7 @@ static void register_test(const char *transport, int use_transaction) {
}else belle_sip_provider_send_request(prov,req);
belle_sip_stack_sleep(stack,33000);
CU_ASSERT_EQUAL(is_register_ok,1);
CU_ASSERT_EQUAL(using_transaction,use_transaction);
return;
}
......
......@@ -30,16 +30,16 @@ static int cleanup_cast_suite(){
static void cast_test(){
belle_sip_stack_t *stack=belle_sip_stack_new(NULL);
belle_sip_listening_point_t *lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",5040,"UDP");
CU_ASSERT_PTR_NOT_NULL(lp);
belle_sip_provider_t *provider=belle_sip_stack_create_provider(stack,lp);
belle_sip_listening_point_t *lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7060,"UDP");
belle_sip_provider_t *provider;
belle_sip_request_t *req=belle_sip_request_new();
belle_sip_response_t *resp=belle_sip_response_new();
belle_sip_message_t *msg;
int tmp;
CU_ASSERT_PTR_NOT_NULL(stack);
CU_ASSERT_PTR_NOT_NULL(lp);
provider=belle_sip_stack_create_provider(stack,lp);
CU_ASSERT_PTR_NOT_NULL(provider);
CU_ASSERT_PTR_NOT_NULL(req);
CU_ASSERT_PTR_NOT_NULL(resp);
......@@ -58,6 +58,7 @@ static void cast_test(){
belle_sip_object_unref(req);
belle_sip_object_unref(resp);
belle_sip_object_unref(provider);
belle_sip_object_unref(lp);
belle_sip_object_unref(stack);
}
......
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