Commit 89abc5b1 authored by Simon Morlat's avatar Simon Morlat

dialog in progress

parent fe4d2326
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
......@@ -226,6 +226,11 @@ order to use an ANSI C compiler:
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
......
......@@ -37,31 +37,35 @@ belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *dialog,
void belle_sip_dialog_delete(belle_sip_dialog_t *dialog);
void *belle_sip_get_application_data(belle_sip_dialog_t *dialog);
void *belle_sip_get_application_data(const belle_sip_dialog_t *dialog);
void belle_sip_set_application_data(belle_sip_dialog_t *dialog, void *data);
const char *belle_sip_dialog_get_dialog_id(belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_dialog_id(const belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_get_local_party(belle_sip_dialog_t *dialog);
const belle_sip_header_call_id_t *belle_sip_dialog_get_call_id(const belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_get_remote_party(belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_get_local_party(const belle_sip_dialog_t *dialog);
unsigned int belle_sip_dialog_get_local_seq_number(belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_get_remote_party(const belle_sip_dialog_t *dialog);
unsigned int belle_sip_dialog_get_remote_seq_number(belle_sip_dialog_t *dialog);
unsigned int belle_sip_dialog_get_local_seq_number(const belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_local_tag(belle_sip_dialog_t *dialog);
unsigned int belle_sip_dialog_get_remote_seq_number(const belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_remote_tag(belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_local_tag(const belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_remote_tag(const belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_dialog_get_remote_target(belle_sip_dialog_t *dialog);
const belle_sip_list_t* belle_sip_dialog_get_route_set(belle_sip_dialog_t *dialog);
belle_sip_dialog_state_t belle_sip_dialog_get_state(belle_sip_dialog_t *dialog);
belle_sip_dialog_state_t belle_sip_dialog_get_state(const belle_sip_dialog_t *dialog);
int belle_sip_dialog_is_server(const belle_sip_dialog_t *dialog);
int belle_sip_dialog_is_server(belle_sip_dialog_t *dialog);
int belle_sip_dialog_is_secure(const belle_sip_dialog_t *dialog);
void belle_sip_dialog_send_ack(belle_sip_dialog_t *dialog, belle_sip_request_t *request);
......
......@@ -290,6 +290,7 @@ belle_sip_header_expires_t* belle_sip_header_expires_create(int expires);
belle_sip_header_record_route_t* belle_sip_header_record_route_parse (const char* route) ;
#define BELLE_SIP_HEADER_RECORD_ROUTE(t) BELLE_SIP_CAST(t,belle_sip_header_record_route_t)
#define BELLE_SIP_RECORD_ROUTE "Record-route"
/******************************
*
* user-Agent header inherit from header
......
......@@ -60,6 +60,11 @@ int belle_sip_message_is_response(const belle_sip_message_t *msg);
belle_sip_header_t *belle_sip_message_get_header(const belle_sip_message_t *msg, const char *header_name);
belle_sip_object_t *_belle_sip_message_get_header_by_type_id(const belle_sip_message_t *message, belle_sip_type_id_t id);
#define belle_sip_message_get_header_by_type(msg,header_type)\
(header_type*)_belle_sip_message_get_header_by_type_id(BELLE_SIP_MESSAGE(msg),BELLE_SIP_TYPE_ID(header_type))
const belle_sip_list_t* belle_sip_message_get_headers(const belle_sip_message_t *message,const char* header_name);
/**
......
......@@ -152,6 +152,9 @@ void belle_sip_object_set_name(belle_sip_object_t *obj,const char* name);
**/
const char* belle_sip_object_get_name(belle_sip_object_t *obj);
/*copy the content of ref object to new object, for the part they have in common in their inheritence diagram*/
void _belle_sip_object_copy(belle_sip_object_t *newobj, const belle_sip_object_t *ref);
belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj);
/**
......
......@@ -38,6 +38,8 @@ 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(const belle_sip_provider_t *prov);
belle_sip_dialog_t *belle_sip_provider_create_dialog(belle_sip_provider_t *prov, belle_sip_transaction_t *t);
belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(belle_sip_provider_t *p, belle_sip_request_t *req);
belle_sip_server_transaction_t *belle_sip_provider_create_server_transaction(belle_sip_provider_t *p, belle_sip_request_t *req);
......
......@@ -50,6 +50,7 @@ libbellesip_la_SOURCES= \
ist.c \
nict.c \
nist.c \
dialog.c \
transports/udp_listeningpoint.c \
transports/udp_channel.c \
transports/stream_channel.c \
......
......@@ -262,7 +262,7 @@ belle_sip_header_from_t* belle_sip_header_from_create2(const char *address, cons
}
belle_sip_header_from_t* belle_sip_header_from_create(const belle_sip_header_address_t* address, const char *tag) {
belle_sip_header_from_t* header= belle_sip_header_from_new();
belle_sip_header_address_clone(BELLE_SIP_HEADER_ADDRESS(header),address);
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
if (tag) belle_sip_header_from_set_tag(header,tag);
return header;
}
......@@ -317,7 +317,7 @@ belle_sip_header_to_t* belle_sip_header_to_create2(const char *address, const ch
}
belle_sip_header_to_t* belle_sip_header_to_create(const belle_sip_header_address_t* address, const char *tag) {
belle_sip_header_to_t* header= belle_sip_header_to_new();
belle_sip_header_address_clone(BELLE_SIP_HEADER_ADDRESS(header),address);
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
if (tag) belle_sip_header_to_set_tag(header,tag);
return header;
}
......
......@@ -278,9 +278,9 @@ char *belle_sip_strdup_printf(const char *fmt,...);
return obj->attribute;\
}\
void object_type##_set_##attribute (object_type##_t* obj,const char* value) {\
if (obj->attribute != NULL) free((void*)obj->attribute);\
if (obj->attribute != NULL) belle_sip_free((void*)obj->attribute);\
if (value) {\
obj->attribute=malloc(strlen(value)+1);\
obj->attribute=belle_sip_malloc(strlen(value)+1);\
strcpy((char*)(obj->attribute),value);\
} else obj->attribute=NULL;\
}
......@@ -526,6 +526,7 @@ struct belle_sip_transaction{
belle_sip_request_t *request;
belle_sip_response_t *last_response;
belle_sip_channel_t *channel;
belle_sip_dialog_t *dialog;
char *branch_id;
belle_sip_transaction_state_t state;
uint64_t start_time;
......@@ -650,6 +651,30 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_nist_t * belle_sip_nist_new(belle_sip_provider_t *prov, belle_sip_request_t *req);
/*
* Dialogs
*/
struct belle_sip_dialog{
belle_sip_object_t base;
belle_sip_dialog_state_t state;
void *appdata;
belle_sip_header_call_id_t *call_id;
belle_sip_header_address_t *local_party;
belle_sip_header_address_t *remote_party;
belle_sip_list_t *route_set;
belle_sip_header_address_t *remote_target;
char *local_tag;
char *remote_tag;
unsigned int local_cseq;
unsigned int remote_cseq;
int is_server:1;
int is_secure:1;
int terminate_on_bye:1;
};
belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t);
/*
belle_sip_response_t
*/
......
......@@ -148,27 +148,50 @@ void belle_sip_object_delete(void *ptr){
belle_sip_free(obj);
}
static belle_sip_object_vptr_t *find_common_floor(belle_sip_object_vptr_t *vptr1, belle_sip_object_vptr_t *vptr2){
belle_sip_object_vptr_t *it1,*it2;
for (it1=vptr1;it1!=NULL;it1=it1->parent){
if (it1==vptr2)
return vptr2;
}
for(it2=vptr2;it2!=NULL;it2=it2->parent){
if (vptr1==it2)
return vptr1;
}
return NULL;
}
/*copy the content of ref object to new object, for the part they have in common in their inheritence diagram*/
void _belle_sip_object_copy(belle_sip_object_t *newobj, const belle_sip_object_t *ref){
belle_sip_object_vptr_t *vptr;
vptr=find_common_floor(newobj->vptr,ref->vptr);
if (vptr==NULL){
belle_sip_fatal("Should not happen");
}
while(vptr!=NULL){
if (vptr->clone==NULL){
belle_sip_fatal("Object of type %s cannot be cloned, it does not provide a clone() implementation.",vptr->type_name);
return;
}else vptr->clone(newobj,ref);
vptr=vptr->parent;
}
}
belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj){
belle_sip_object_t *newobj;
belle_sip_object_vptr_t *vptr;
newobj=belle_sip_malloc0(obj->size);
newobj->ref=obj->vptr->initially_unowned ? 0 : 1;
newobj->vptr=obj->vptr;
newobj->size=obj->size;
if (obj->name) newobj->name=belle_sip_strdup(obj->name);
vptr=obj->vptr;
while(vptr!=NULL){
if (vptr->clone==NULL){
belle_sip_fatal("Object of type %s cannot be cloned, it does not provide a clone() implementation.",vptr->type_name);
return NULL;
}else vptr->clone(newobj,obj);
vptr=vptr->parent;
}
_belle_sip_object_copy(newobj,obj);
return newobj;
}
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno){
if (obj!=NULL){
if (has_type(obj,id)==0){
......
This diff is collapsed.
......@@ -63,7 +63,7 @@ static belle_sip_request_t *make_ack(belle_sip_ict_t *obj, belle_sip_response_t
belle_sip_message_add_header((belle_sip_message_t*)obj->ack,
(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((belle_sip_message_t*)base->request,BELLE_SIP_CSEQ)),
"CANCEL"));
"ACK"));
}
return obj->ack;
......
......@@ -154,6 +154,18 @@ const belle_sip_list_t* belle_sip_message_get_headers(const belle_sip_message_t
return headers_container ? headers_container->header_list:NULL;
}
belle_sip_object_t *_belle_sip_message_get_header_by_type_id(const belle_sip_message_t *message, belle_sip_type_id_t id){
const belle_sip_list_t *e1;
for(e1=message->header_list;e1!=NULL;e1=e1->next){
headers_container_t* headers_container=(headers_container_t*)e1->data;
if (headers_container->header_list){
belle_sip_object_t *ret=headers_container->header_list->data;
if (ret->vptr->id==id) return ret;
}
}
return NULL;
}
void belle_sip_message_remove_first(belle_sip_message_t *msg, const char *header_name){
headers_container_t* headers_container = belle_sip_headers_container_get(msg,header_name);
if (headers_container && headers_container->header_list){
......@@ -417,7 +429,7 @@ belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *requri, const cha
belle_sip_header_from_t *from,
belle_sip_header_to_t *to,
belle_sip_header_via_t *via,
int max_forward /*FIXME*/)
int max_forward)
{
belle_sip_request_t *ret=belle_sip_request_new();
belle_sip_header_max_forwards_t *mf=belle_sip_header_max_forwards_new();
......
......@@ -85,8 +85,6 @@ static void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, bell
belle_sip_object_unref(msg);
}
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"));
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"rport",NULL);
......@@ -143,19 +141,21 @@ static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_chan
fix_outgoing_via((belle_sip_provider_t*)obj,chan,msg);
}
/* fix the contact if empty*/
if (!(contact_uri =belle_sip_header_address_get_uri((belle_sip_header_address_t*)contact))) {
contact_uri = belle_sip_uri_new();
belle_sip_header_address_set_uri((belle_sip_header_address_t*)contact,contact_uri);
}
if (!belle_sip_uri_get_host(contact_uri)) {
belle_sip_uri_set_host(contact_uri,chan->local_ip);
}
if (belle_sip_uri_get_transport_param(contact_uri) == NULL && strcasecmp("udp",belle_sip_channel_get_transport_name(chan))!=0) {
belle_sip_uri_set_transport_param(contact_uri,belle_sip_channel_get_transport_name_lower_case(chan));
}
if (belle_sip_uri_get_port(contact_uri) == 0 && chan->local_port!=5060) {
belle_sip_uri_set_port(contact_uri,chan->local_port);
if (contact){
/* fix the contact if empty*/
if (!(contact_uri =belle_sip_header_address_get_uri((belle_sip_header_address_t*)contact))) {
contact_uri = belle_sip_uri_new();
belle_sip_header_address_set_uri((belle_sip_header_address_t*)contact,contact_uri);
}
if (!belle_sip_uri_get_host(contact_uri)) {
belle_sip_uri_set_host(contact_uri,chan->local_ip);
}
if (belle_sip_uri_get_transport_param(contact_uri) == NULL && strcasecmp("udp",belle_sip_channel_get_transport_name(chan))!=0) {
belle_sip_uri_set_transport_param(contact_uri,belle_sip_channel_get_transport_name_lower_case(chan));
}
if (belle_sip_uri_get_port(contact_uri) == 0 && chan->local_port!=5060) {
belle_sip_uri_set_port(contact_uri,chan->local_port);
}
}
if (!content_lenght && strcasecmp("udp",belle_sip_channel_get_transport_name(chan))!=0) {
content_lenght = belle_sip_header_content_length_create(0);
......@@ -224,6 +224,13 @@ belle_sip_header_call_id_t * belle_sip_provider_create_call_id(const belle_sip_p
return cid;
}
belle_sip_dialog_t * belle_sip_provider_create_dialog(belle_sip_provider_t *prov, belle_sip_transaction_t *t){
belle_sip_dialog_t *dialog=NULL;
dialog=belle_sip_dialog_new(t);
t->dialog=(belle_sip_dialog_t*)belle_sip_object_ref(dialog);
return dialog;
}
belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(belle_sip_provider_t *prov, belle_sip_request_t *req){
const char *method=belle_sip_request_get_method(req);
if (strcmp(method,"INVITE")==0)
......
/*
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"
static void belle_sip_sender_task_uninit(belle_sip_sender_task_t *t){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
belle_sip_object_unref(t->message);
if (t->channel) belle_sip_object_unref(t->channel);
if (t->source) {
belle_sip_main_loop_cancel_source(stack->ml,belle_sip_source_get_id(t->source));
belle_sip_object_unref(t->source);
}
if (t->resolver_id>0) belle_sip_main_loop_cancel_source (stack->ml,t->resolver_id);
}
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_sender_task_t,belle_sip_object_t,belle_sip_sender_task_uninit,NULL,NULL);
belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provider, belle_sip_sender_task_callback_t cb, void *data){
belle_sip_sender_task_t *t=belle_sip_object_new(belle_sip_sender_task_t);
t->provider=provider;
t->message=NULL;
t->cb=cb;
t->cb_data=data;
return t;
}
static int do_send(belle_sip_sender_task_t *t){
int err=belle_sip_channel_send(t->channel,t->buf,strlen(t->buf));
if (err>0){
t->cb(t,t->cb_data,0);
}else if (err!=-EWOULDBLOCK){
t->cb(t,t->cb_data,-1);
}
return err;
}
static int retry_send(belle_sip_sender_task_t *t, unsigned int revents){
if (revents & BELLE_SIP_EVENT_WRITE){
do_send(t);
return 0;
}
/*timeout : notify the failure*/
t->cb(t,t->cb_data,-1);
return 0;
}
static void sender_task_send(belle_sip_sender_task_t *t){
int err;
if (t->buf==NULL)
t->buf=belle_sip_message_to_string(t->message);
err=do_send(t);
if (err==-EWOULDBLOCK){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
/*need to retry later*/
if (t->source==NULL){
t->source=belle_sip_channel_create_source(t->channel,BELLE_SIP_EVENT_WRITE,BELLE_SIP_SOCKET_TIMEOUT,
(belle_sip_source_func_t)retry_send,t);
}
belle_sip_main_loop_add_source (stack->ml,t->source);
}
}
static void sender_task_find_channel_and_send(belle_sip_sender_task_t *t){
belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(t->provider,t->hop.transport);
if (lp==NULL){
belle_sip_error("No listening point available for transport %s",t->hop.transport);
goto error;
}else{
belle_sip_channel_t *chan=belle_sip_listening_point_find_output_channel (lp,t->dest);
if (chan==NULL) goto error;
t->channel=(belle_sip_channel_t*)belle_sip_object_ref(chan);
sender_task_send(t);
}
return;
error:
t->cb(t,t->cb_data,-1);
}
static void sender_task_res_done(void *data, const char *name, struct addrinfo *res){
belle_sip_sender_task_t *t=(belle_sip_sender_task_t*)data;
t->resolver_id=0;
if (res){
t->dest=res;
sender_task_find_channel_and_send(t);
}else{
belle_sip_io_error_event_t ev;
ev.transport=t->hop.transport;
ev.source=t->provider;
ev.port=t->hop.port;
ev.host=t->hop.host;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(t->provider,process_io_error,&ev);
t->cb(t,t->cb_data,-1);
}
}
void belle_sip_sender_task_send(belle_sip_sender_task_t *t, belle_sip_message_t *msg){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
if (t->message!=NULL && t->message!=msg && msg!=NULL){
belle_sip_object_unref(t->message);
t->message=NULL;
belle_sip_free(t->buf);
t->buf=NULL;
}
if (t->message==NULL){
t->message=(belle_sip_message_t*)belle_sip_object_ref(msg);
}
if (t->channel){
/*retransmission or new response to be sent, everything already done for setting up the transport*/
sender_task_send(t);
return;
}
if (belle_sip_message_is_request(t->message)){
belle_sip_stack_get_next_hop(stack,BELLE_SIP_REQUEST(t->message),&t->hop);
t->resolver_id=belle_sip_resolve(t->hop.host,t->hop.port,0,sender_task_res_done,t,stack->ml);
}else{
belle_sip_response_get_return_hop(BELLE_SIP_RESPONSE(t->message),&t->hop);
sender_task_find_channel_and_send(t);
}
}
int belle_sip_sender_task_is_reliable(belle_sip_sender_task_t *task){
if (task->channel==NULL) belle_sip_fatal("The transport isn't known yet");
return belle_sip_listening_point_is_reliable(task->channel->lp);
}
/*
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/>.
*/
#ifndef sender_task_h
#define sender_task_h
struct belle_sip_sender_task;
typedef void (*belle_sip_sender_task_callback_t)(struct belle_sip_sender_task* , void *data, int retcode);
struct belle_sip_sender_task{
belle_sip_object_t base;
belle_sip_provider_t *provider;
belle_sip_message_t *message;
belle_sip_source_t *source;
belle_sip_channel_t *channel;
belle_sip_hop_t hop;
struct addrinfo *dest;
unsigned long resolver_id;
char *buf;
belle_sip_sender_task_callback_t cb;
void *cb_data;
};
typedef struct belle_sip_sender_task belle_sip_sender_task_t;
belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provider, belle_sip_sender_task_callback_t cb, void *data);
void belle_sip_sender_task_send(belle_sip_sender_task_t *task, belle_sip_message_t *msg);
/*you can only call that after send has been called once */
int belle_sip_sender_task_is_reliable(belle_sip_sender_task_t *task);
#endif
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