Commit e115c36b authored by Simon Morlat's avatar Simon Morlat

start implementing transaction state machines

parent 8cedab5a
......@@ -40,8 +40,8 @@ struct belle_sip_dialog_terminated_event{
struct belle_sip_io_error_event{
belle_sip_provider_t *source;
char *transport;
char *host;
const char *transport;
const char *host;
int port;
};
......
......@@ -34,7 +34,7 @@ typedef struct belle_sip_channel belle_sip_channel_t;
BELLE_SIP_BEGIN_DECLS
/**
* belle_sip_transport_t is an object representing a single communication channel (=unix socket),
* belle_sip_transport_t is an object representing a single communication channel (=unix socket or file descriptor),
* unlike the belle_sip_listening_point_t that can owns several channels for TCP or TLS (incoming server child sockets or
* outgoing client sockets).
**/
......@@ -52,7 +52,7 @@ const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_p
int belle_sip_listening_point_get_port(const belle_sip_listening_point_t *lp);
const char *belle_sip_listening_point_get_transport(const belle_sip_listening_point_t *ip);
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *ip);
int belle_sip_listening_point_is_reliable(const belle_sip_listening_point_t *lp);
BELLE_SIP_END_DECLS
......
......@@ -38,6 +38,9 @@ typedef int (*belle_sip_source_func_t)(void *user_data, unsigned int events);
typedef struct belle_sip_main_loop belle_sip_main_loop_t;
#define BELLE_SIP_CONTINUE TRUE
#define BELLE_SIP_STOP FALSE
BELLE_SIP_BEGIN_DECLS
void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source);
......
......@@ -28,6 +28,15 @@ struct belle_sip_hop{
typedef struct belle_sip_hop belle_sip_hop_t;
struct belle_sip_timer_config{
int T1;
int T2;
int T3;
int T4;
};
typedef struct belle_sip_timer_config belle_sip_timer_config_t;
BELLE_SIP_BEGIN_DECLS
belle_sip_stack_t * belle_sip_stack_new(const char *properties);
......
......@@ -57,12 +57,16 @@ typedef struct _belle_sip_uri belle_sip_uri_t;
* Returns the value of the method parameter, or null if this is not set.
*
*/
const char* belle_sip_uri_get_method_param(const belle_sip_uri_t* uri) ;
const char* belle_sip_uri_get_method_param(const belle_sip_uri_t* uri) ;
/**
* Returns the port part of this SipURI.
*
*/
unsigned int belle_sip_uri_get_port(const belle_sip_uri_t* uri) ;
unsigned int belle_sip_uri_get_port(const belle_sip_uri_t* uri) ;
/**
* Returns the port of the uri, if not specified in the uri returns the well known port according to the transport.
**/
int belle_sip_uri_get_listening_port(const belle_sip_uri_t *uri);
/**
* Returns the value of the "transport" parameter, or null if this is not set.
*
......
......@@ -375,14 +375,24 @@ struct belle_sip_stack{
belle_sip_object_t base;
belle_sip_main_loop_t *ml;
belle_sip_list_t *lp;/*list of listening points*/
belle_sip_timer_config_t timer_config;
};
void belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req, belle_sip_hop_t *hop);
const belle_sip_timer_config_t *belle_sip_stack_get_timer_config(const belle_sip_stack_t *stack);
/*
belle_sip_provider_t
*/
struct belle_sip_provider{
belle_sip_object_t base;
belle_sip_stack_t *stack;
belle_sip_list_t *lps; /*listening points*/
belle_sip_list_t *listeners;
};
belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
typedef struct listener_ctx{
......@@ -395,7 +405,7 @@ typedef struct listener_ctx{
belle_sip_list_t *_elem; \
for(_elem=(provider)->listeners;_elem!=NULL;_elem=_elem->next){ \
listener_ctx_t *_lctx=(listener_ctx_t*)_elem->data; \
_lctx->##callback(_lctx->data,event); \
_lctx->listener->callback(_lctx->data,(event)); \
} \
}
......
......@@ -87,7 +87,13 @@ const belle_sip_list_t* belle_sip_uri_get_header_names(const belle_sip_uri_t* ur
return belle_sip_parameters_get_parameter_names(uri->header_list);
}
int belle_sip_uri_get_listening_port(const belle_sip_uri_t *uri){
int port=belle_sip_uri_get_port(uri);
const char *transport=belle_sip_uri_get_transport_param(uri);
if (port==-1)
port=belle_sip_listening_point_get_well_known_port(transport ? transport : "UDP");
return port;
}
SIP_URI_GET_SET_BOOL(secure)
......
......@@ -31,6 +31,7 @@
struct belle_sip_channel{
belle_sip_object_t base;
belle_sip_listening_point_t *lp; /* the listening point this channel belongs */
struct addrinfo peer;
struct sockaddr_storage peer_addr;
};
......@@ -41,8 +42,9 @@ typedef struct belle_sip_channel_vptr{
belle_sip_source_t *(*create_source)(belle_sip_channel_t *obj, unsigned int events, unsigned int timeout, belle_sip_source_func_t callback, void *data);
}belle_sip_channel_vptr_t;
static void belle_sip_channel_init(belle_sip_channel_t *obj){
static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_listening_point_t *lp){
belle_sip_object_init_type(obj,belle_sip_channel_t);
obj->lp=lp;
obj->peer.ai_addr=(struct sockaddr*)&obj->peer_addr;
}
......@@ -137,9 +139,9 @@ static int create_udp_socket(const char *addr, int port){
return sock;
}
belle_sip_udp_channel_t *belle_sip_udp_channel_new(int sock, const struct addrinfo *dest){
belle_sip_udp_channel_t *belle_sip_udp_channel_new(belle_sip_listening_point_t *lp, int sock, const struct addrinfo *dest){
belle_sip_udp_channel_t *obj=belle_sip_object_new_with_vptr(belle_sip_udp_channel_t,&udp_channel_vptr,udp_channel_uninit);
belle_sip_channel_init((belle_sip_channel_t*)obj);
belle_sip_channel_init((belle_sip_channel_t*)obj,lp);
obj->sock=sock;
memcpy(obj->base.peer.ai_addr,dest->ai_addr,dest->ai_addrlen);
obj->base.peer.ai_addrlen=dest->ai_addrlen;
......@@ -156,6 +158,7 @@ struct belle_sip_listening_point{
char *transport;
char *addr;
int port;
int is_reliable;
};
typedef struct belle_sip_listening_point_vptr{
......@@ -187,6 +190,18 @@ const char *belle_sip_listening_point_get_transport(const belle_sip_listening_po
return lp->transport;
}
int belle_sip_listening_point_is_reliable(const belle_sip_listening_point_t *lp){
return lp->is_reliable;
}
int belle_sip_listening_point_get_well_known_port(const char *transport){
if (strcasecmp(transport,"UDP")==0 || strcasecmp(transport,"TCP")==0 ) return 5060;
if (strcasecmp(transport,"DTLS")==0 || strcasecmp(transport,"TLS")==0 ) return 5061;
belle_sip_error("No well known port for transport %s", transport);
return -1;
}
belle_sip_channel_t *belle_sip_listening_point_find_output_channel (belle_sip_listening_point_t *lp,const struct addrinfo *dest){
return ((belle_sip_listening_point_vptr_t*)lp->base.vptr)->find_output_channel(lp,dest);
}
......@@ -200,7 +215,7 @@ struct belle_sip_udp_listening_point{
static belle_sip_channel_t *udp_listening_point_find_output_channel(belle_sip_listening_point_t* obj,const struct addrinfo *dest){
belle_sip_udp_listening_point_t *lp=(belle_sip_udp_listening_point_t*)obj;
belle_sip_udp_channel_t * chan=belle_sip_udp_channel_new (lp->sock,dest);
belle_sip_udp_channel_t * chan=belle_sip_udp_channel_new (obj,lp->sock,dest);
return BELLE_SIP_CHANNEL(chan);
}
......@@ -222,14 +237,8 @@ belle_sip_listening_point_t * belle_sip_udp_listening_point_new(belle_sip_stack_
belle_sip_object_unref(s);
return NULL;
}
lp->base.is_reliable=FALSE;
return BELLE_SIP_LISTENING_POINT(lp);
}
int belle_sip_listening_point_get_well_known_port(const char *transport){
if (strcasecmp(transport,"UDP")==0 || strcasecmp(transport,"TCP")==0 ) return 5060;
if (strcasecmp(transport,"DTLS")==0 || strcasecmp(transport,"TLS")==0 ) return 5061;
belle_sip_error("No well known port for transport %s", transport);
return -1;
}
......@@ -77,6 +77,11 @@ BELLE_SIP_PARSE(request)
void belle_sip_request_set_uri(belle_sip_request_t* request,belle_sip_uri_t* uri) {
}
belle_sip_uri_t * belle_sip_request_get_uri(belle_sip_request_t *request){
return NULL;
}
void belle_sip_request_set_method(belle_sip_request_t* request,const char* method) {
}
......
......@@ -26,12 +26,6 @@ static int listener_ctx_compare(const void *c1, const void *c2){
return !(lc1->listener==lc2->listener && lc1->data==lc2->data);
}
struct belle_sip_provider{
belle_sip_object_t base;
belle_sip_stack_t *stack;
belle_sip_list_t *lps; /*listening points*/
belle_sip_list_t *listeners;
};
static void belle_sip_provider_uninit(belle_sip_provider_t *p){
belle_sip_list_for_each (p->listeners,belle_sip_free);
......
......@@ -96,6 +96,12 @@ static void sender_task_res_done(void *data, const char *name, struct addrinfo *
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);
}
}
......
......@@ -28,9 +28,16 @@ static void belle_sip_stack_destroy(belle_sip_stack_t *stack){
belle_sip_stack_t * belle_sip_stack_new(const char *properties){
belle_sip_stack_t *stack=belle_sip_object_new(belle_sip_stack_t,belle_sip_stack_destroy);
stack->ml=belle_sip_main_loop_new ();
stack->timer_config.T1=500;
stack->timer_config.T2=4000;
stack->timer_config.T4=5000;
return stack;
}
const belle_sip_timer_config_t *belle_sip_stack_get_timer_config(const belle_sip_stack_t *stack){
return &stack->timer_config;
}
belle_sip_listening_point_t *belle_sip_stack_create_listening_point(belle_sip_stack_t *s, const char *ipaddress, int port, const char *transport){
belle_sip_listening_point_t *lp=NULL;
if (strcasecmp(transport,"UDP")==0){
......@@ -67,6 +74,15 @@ void belle_sip_stack_sleep(belle_sip_stack_t *stack, unsigned int milliseconds){
}
void belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req, belle_sip_hop_t *hop){
hop->transport="UDP";
/*should find top most route or request uri */
belle_sip_header_route_t *route=BELLE_SIP_HEADER_ROUTE(belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"route"));
belle_sip_uri_t *uri;
if (route!=NULL){
uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(route));
}else{
uri=belle_sip_request_get_uri(req);
}
hop->transport=belle_sip_uri_get_transport_param(uri);
if (hop->transport==NULL) hop->transport="UDP";
hop->host=belle_sip_uri_get_host(uri);
hop->port=belle_sip_uri_get_listening_port(uri);
}
......@@ -17,23 +17,42 @@
*/
#include "belle_sip_internal.h"
#include "sender_task.h"
struct belle_sip_transaction{
belle_sip_object_t base;
belle_sip_provider_t *provider; /*the provider that created this transaction */
belle_sip_request_t *request;
char *branch_id;
belle_sip_transaction_state_t state;
belle_sip_sender_task_t *stask;
void *appdata;
belle_sip_request_t *request;
};
struct belle_sip_server_transaction{
belle_sip_transaction_t base;
};
struct belle_sip_client_transaction{
belle_sip_transaction_t base;
};
static unsigned long transaction_add_timeout(belle_sip_transaction_t *t, belle_sip_source_func_t func, unsigned int time_ms){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
return belle_sip_main_loop_add_timeout (stack->ml,func,t,time_ms);
}
/*
static void transaction_remove_timeout(belle_sip_transaction_t *t, unsigned long id){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
belle_sip_main_loop_cancel_source (stack->ml,id);
}
*/
static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_object_init_type(t,belle_sip_transaction_t);
if (req) belle_sip_object_ref(req);
t->request=req;
t->provider=prov;
}
static void transaction_destroy(belle_sip_transaction_t *t){
if (t->request) belle_sip_object_unref(t->request);
if (t->stask) belle_sip_object_unref(t->stask);
}
void *belle_sip_transaction_get_application_data(const belle_sip_transaction_t *t){
return t->appdata;
......@@ -59,34 +78,72 @@ belle_sip_request_t *belle_sip_transaction_get_request(belle_sip_transaction_t *
return t->request;
}
/*
Server transaction
*/
struct belle_sip_server_transaction{
belle_sip_transaction_t base;
};
void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t){
}
static void server_transaction_destroy(belle_sip_server_transaction_t *t){
transaction_destroy((belle_sip_transaction_t*)t);
}
belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_provider_t *prov,belle_sip_request_t *req){
belle_sip_server_transaction_t *t=belle_sip_object_new(belle_sip_server_transaction_t,(belle_sip_object_destroy_t)server_transaction_destroy);
belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req);
return t;
}
/*
Client transaction
*/
struct belle_sip_client_transaction{
belle_sip_transaction_t base;
unsigned long timer_id;
uint64_t start_time;
uint64_t time_F;
uint64_t time_E;
};
belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t){
return NULL;
}
void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t){
static int on_client_transaction_timer(void *data, unsigned int revents){
return BELLE_SIP_CONTINUE;
}
static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_object_init_type(t,belle_sip_transaction_t);
if (req) belle_sip_object_ref(req);
t->request=req;
t->provider=prov;
static void client_transaction_cb(belle_sip_sender_task_t *task, void *data, int retcode){
belle_sip_client_transaction_t *t=(belle_sip_client_transaction_t*)data;
const belle_sip_timer_config_t *tc=belle_sip_stack_get_timer_config (belle_sip_provider_get_sip_stack (t->base.provider));
if (retcode==0){
t->base.state=BELLE_SIP_TRANSACTION_TRYING;
t->timer_id=transaction_add_timeout(&t->base,on_client_transaction_timer,tc->T1);
}else{
belle_sip_transaction_terminated_event_t ev;
ev.source=t->base.provider;
ev.transaction=(belle_sip_transaction_t*)t;
ev.is_server_transaction=FALSE;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(t->base.provider,process_transaction_terminated,&ev);
}
}
static void transaction_destroy(belle_sip_transaction_t *t){
if (t->request) belle_sip_object_unref(t->request);
void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t){
t->base.stask=belle_sip_sender_task_new(t->base.provider,BELLE_SIP_MESSAGE(t->base.request),client_transaction_cb,t);
belle_sip_sender_task_send(t->base.stask);
}
static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
transaction_destroy((belle_sip_transaction_t*)t);
}
static void server_transaction_destroy(belle_sip_server_transaction_t *t){
transaction_destroy((belle_sip_transaction_t*)t);
}
belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_client_transaction_t *t=belle_sip_object_new(belle_sip_client_transaction_t,(belle_sip_object_destroy_t)client_transaction_destroy);
......@@ -94,10 +151,5 @@ belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_prov
return t;
}
belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_provider_t *prov,belle_sip_request_t *req){
belle_sip_server_transaction_t *t=belle_sip_object_new(belle_sip_server_transaction_t,(belle_sip_object_destroy_t)server_transaction_destroy);
belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req);
return t;
}
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