Commit b9bc6942 authored by Simon Morlat's avatar Simon Morlat

transactions start working

parent bb76663d
......@@ -22,42 +22,7 @@
#include <sys/socket.h>
#include <unistd.h>
#if defined(WIN32) || defined(WIN32_WCE)
typedef SOCKET belle_sip_fd_t;
static inline void close_socket(belle_sip_fd_t s){
closesocket(s);
}
static inline int get_socket_error(void){
return WSAGetLastError();
}
const char *getSocketErrorString();
#define belle_sip_get_socket_error_string() getSocketErrorString()
#define usleep(us) Sleep((us)/1000)
static inline int inet_aton(const char *ip, struct in_addr *p){
*(long*)p=inet_addr(ip);
return 0;
}
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#else
typedef int belle_sip_fd_t;
static inline void close_socket(belle_sip_fd_t s){
close(s);
}
static inline int get_socket_error(void){
return errno;
}
#define belle_sip_get_socket_error_string() strerror(errno)
#endif
#define BELLE_SIP_EVENT_READ 1
#define BELLE_SIP_EVENT_WRITE (1<<1)
......@@ -66,7 +31,7 @@ static inline int get_socket_error(void){
typedef struct belle_sip_source belle_sip_source_t;
int belle_sip_source_set_event(belle_sip_source_t* source, int event_mask);
int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask);
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source);
/**
......@@ -80,7 +45,7 @@ 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
#define BELLE_SIP_STOP FALSE
BELLE_SIP_BEGIN_DECLS
......
......@@ -21,6 +21,8 @@
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
/***************/
/* logging api */
......@@ -129,6 +131,47 @@ void belle_sip_set_log_handler(belle_sip_log_function_t func);
void belle_sip_set_log_level(int level);
char * belle_sip_random_token(char *ret, size_t size);
#if defined(WIN32) || defined(WIN32_WCE)
typedef SOCKET belle_sip_fd_t;
static inline void close_socket(belle_sip_fd_t s){
closesocket(s);
}
static inline int get_socket_error(void){
return WSAGetLastError();
}
const char *getSocketErrorString();
#define belle_sip_get_socket_error_string() getSocketErrorString()
#define belle_sip_get_socket_error_string_from_code(code) getSocketErrorString()
#define usleep(us) Sleep((us)/1000)
static inline int inet_aton(const char *ip, struct in_addr *p){
*(long*)p=inet_addr(ip);
return 0;
}
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#else
typedef int belle_sip_fd_t;
static inline void close_socket(belle_sip_fd_t s){
close(s);
}
static inline int get_socket_error(void){
return errno;
}
#define belle_sip_get_socket_error_string() strerror(errno)
#define belle_sip_get_socket_error_string_from_code(code) strerror(code)
#endif
BELLE_SIP_END_DECLS
#endif
......
......@@ -40,12 +40,13 @@
#define BELLE_SIP_INTERFACE_GET_METHODS(obj,interface) \
((BELLE_SIP_INTERFACE_METHODS_TYPE(interface)*)belle_sip_object_get_interface_methods((belle_sip_object_t*)obj,BELLE_SIP_INTERFACE_ID(interface)))
#define __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name) \
#define __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name,method) \
if (list!=NULL) {\
const belle_sip_list_t *__elem=list;\
do{\
interface_name *__obj=(interface_name*)__elem->data;\
BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->
void *__method=BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->method;\
if (__method) BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->
#define __BELLE_SIP_INVOKE_LISTENER_END \
__elem=__elem->next;\
......@@ -53,18 +54,18 @@
}
#define BELLE_SIP_INVOKE_LISTENERS_VOID(list,interface_name,method) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name,method)\
method(__obj);\
__BELLE_SIP_INVOKE_LISTENER_END
#define BELLE_SIP_INVOKE_LISTENERS_ARG(list,interface_name,method,arg) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name,method)\
method(__obj,arg);\
__BELLE_SIP_INVOKE_LISTENER_END
#define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(list,interface_name,method,arg1,arg2) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name,method)\
method(__obj,arg1,arg2);\
__BELLE_SIP_INVOKE_LISTENER_END
......@@ -395,7 +396,6 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
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;
};
......@@ -412,9 +412,13 @@ struct belle_sip_provider{
belle_sip_stack_t *stack;
belle_sip_list_t *lps; /*listening points*/
belle_sip_list_t *listeners;
belle_sip_list_t *client_transactions;
};
belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
void belle_sip_provider_add_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t);
belle_sip_client_transaction_t *belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t *prov, belle_sip_response_t *resp);
void belle_sip_provider_remove_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t);
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t);
belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, const char *name, int port, const char *transport);
......
......@@ -59,6 +59,16 @@ unsigned long belle_sip_source_get_id(belle_sip_source_t *s){
return s->id;
}
int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask) {
source->events = event_mask;
return 0;
}
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source) {
return source->fd;
}
struct belle_sip_main_loop{
belle_sip_object_t base;
belle_sip_list_t *sources;
......@@ -271,10 +281,3 @@ void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds){
belle_sip_main_loop_add_timeout(ml,(belle_sip_source_func_t)belle_sip_main_loop_quit,ml,milliseconds);
belle_sip_main_loop_run(ml);
}
int belle_sip_source_set_event(belle_sip_source_t* source, int event_mask) {
source->events = event_mask;
return 0;
}
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source) {
return source->fd;
}
......@@ -66,9 +66,13 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_resolver_context_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_resolver_context_t, belle_sip_source_t,belle_sip_resolver_context_destroy, NULL, NULL,FALSE);
static int resolver_callback(belle_sip_resolver_context_t *ctx){
char tmp;
ctx->cb(ctx->cb_data, ctx->name, ctx->ai);
ctx->ai=NULL;
return 0;
if (read(ctx->source.fd,&tmp,1)!=1){
belle_sip_fatal("Unexpected read from resolver_callback");
}
return BELLE_SIP_STOP;
}
belle_sip_resolver_context_t *belle_sip_resolver_context_new(){
......
......@@ -507,4 +507,35 @@ char* _belle_sip_str_dup_and_unquote_string(const char* quoted_string) {
return unquoted_string;
}
unsigned int belle_sip_random(void){
#ifdef __linux
static int fd=-1;
if (fd==-1) fd=open("/dev/urandom",O_RDONLY);
if (fd!=-1){
unsigned int tmp;
if (read(fd,&tmp,4)!=4){
belle_sip_error("Reading /dev/urandom failed.");
}else return tmp;
}else belle_sip_error("Could not open /dev/urandom");
#endif
return (unsigned int) random();
}
/**
* Write a random text token of supplied size.
**/
char * belle_sip_random_token(char *ret, size_t size){
static const char *symbols="0123456789abcdefghijklmnopqrstuvwxyz";
unsigned int val;
int i,j;
for(i=0,j=0;i<size-1;++i,++j){
if (j%8==0) val=belle_sip_random();
ret[i]=symbols[val & 31];
val=val>>4;
}
ret[i]=0;
return ret;
}
......@@ -19,7 +19,7 @@
#include "belle_sip_internal.h"
static const char *channel_state_to_string(belle_sip_channel_state_t state){
const char *belle_sip_channel_state_to_string(belle_sip_channel_state_t state){
switch(state){
case BELLE_SIP_CHANNEL_INIT:
return "INIT";
......@@ -182,16 +182,16 @@ void belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revent
}
}
return;
message_ready:
obj->incoming_messages=belle_sip_list_append(obj->incoming_messages,obj->input_stream.msg);
belle_sip_channel_input_stream_reset(&obj->input_stream,message_size);
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,revents);
if (obj->input_stream.write_ptr-obj->input_stream.read_ptr>0) {
/*process residu*/
belle_sip_channel_process_data(obj,revents);
}
return;
return;
message_ready:
obj->incoming_messages=belle_sip_list_append(obj->incoming_messages,obj->input_stream.msg);
belle_sip_channel_input_stream_reset(&obj->input_stream,message_size);
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,revents);
if (obj->input_stream.write_ptr-obj->input_stream.read_ptr>0) {
/*process residu*/
belle_sip_channel_process_data(obj,revents);
}
return;
} else {
belle_sip_error("Receive error on channel [%p]",obj);
}
......@@ -282,7 +282,7 @@ belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj) {
}
void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state) {
belle_sip_message("channel %p: state %s",obj,channel_state_to_string(state));
belle_sip_message("channel %p: state %s",obj,belle_sip_channel_state_to_string(state));
obj->state=state;
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_state_changed,obj,state);
}
......@@ -303,25 +303,34 @@ static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
}
void belle_sip_channel_prepare(belle_sip_channel_t *obj){
obj->prepare=1;
channel_process_queue(obj);
}
void channel_process_queue(belle_sip_channel_t *obj){
if (obj->msg){
switch(obj->state){
case BELLE_SIP_CHANNEL_INIT:
belle_sip_channel_resolve(obj);
break;
case BELLE_SIP_CHANNEL_RES_DONE:
belle_sip_channel_connect(obj);
break;
case BELLE_SIP_CHANNEL_READY:
switch(obj->state){
case BELLE_SIP_CHANNEL_INIT:
if (obj->prepare) belle_sip_channel_resolve(obj);
break;
case BELLE_SIP_CHANNEL_RES_DONE:
if (obj->prepare) belle_sip_channel_connect(obj);
break;
case BELLE_SIP_CHANNEL_READY:
if (obj->msg) {
send_message(obj, obj->msg);
/* no break */
case BELLE_SIP_CHANNEL_ERROR:
belle_sip_object_unref(obj->msg);
obj->msg=NULL;
}
break;
default:
break;
}
case BELLE_SIP_CHANNEL_ERROR:
if (obj->msg){
belle_sip_object_unref(obj->msg);
obj->msg=NULL;
}
break;
default:
break;
}
}
......@@ -340,6 +349,7 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr
}
}
channel_set_state(obj,BELLE_SIP_CHANNEL_READY);
obj->prepare=0;
channel_process_queue(obj);
}
......@@ -364,7 +374,7 @@ void belle_sip_channel_resolve(belle_sip_channel_t *obj){
void belle_sip_channel_connect(belle_sip_channel_t *obj){
channel_set_state(obj,BELLE_SIP_CHANNEL_CONNECTING);
if(BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->connect(obj,obj->peer->ai_addr,obj->peer->ai_addrlen)) {
belle_sip_error("Cannot connect to [%s://%s:%s]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
channel_process_queue(obj);
}
......@@ -373,10 +383,12 @@ void belle_sip_channel_connect(belle_sip_channel_t *obj){
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
if (obj->msg!=NULL){
belle_sip_error("Queue is not a queue.");
belle_sip_error("Queue is not a queue, state=%s", belle_sip_channel_state_to_string(obj->state));
return -1;
}
obj->msg=(belle_sip_message_t*)belle_sip_object_ref(msg);
if (obj->state==BELLE_SIP_CHANNEL_INIT)
belle_sip_channel_prepare(obj);
channel_process_queue(obj);
return 0;
}
......
......@@ -36,6 +36,7 @@ typedef enum belle_sip_channel_state{
BELLE_SIP_CHANNEL_ERROR
}belle_sip_channel_state_t;
const char * belle_sip_channel_state_to_string(belle_sip_channel_state_t state);
/**
* belle_sip_channel_t is an object representing a single communication channel ( socket or file descriptor),
......@@ -78,6 +79,7 @@ struct belle_sip_channel{
int peer_port;
char *local_ip;
int local_port;
int prepare;
unsigned long resolver_id;
struct addrinfo *peer;
belle_sip_message_t *msg;
......@@ -103,6 +105,8 @@ void belle_sip_channel_resolve(belle_sip_channel_t *obj);
void belle_sip_channel_connect(belle_sip_channel_t *obj);
void belle_sip_channel_prepare(belle_sip_channel_t *obj);
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen);
int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen);
......
......@@ -134,6 +134,7 @@ 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);
}
......
......@@ -22,7 +22,7 @@
static void belle_sip_provider_uninit(belle_sip_provider_t *p){
belle_sip_list_free(p->listeners);
belle_sip_list_free(p->lps);
belle_sip_list_free_with_data(p->lps,belle_sip_object_unref);
}
static void channel_state_changed(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
......@@ -53,6 +53,7 @@ static void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, bell
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);
char token[7]="fixme";
if (belle_sip_header_via_get_host(via)==NULL){
const char *local_ip;
int local_port;
......@@ -63,7 +64,8 @@ static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan,
belle_sip_header_via_set_transport(via,belle_sip_channel_get_transport_name(chan));
}
if (belle_sip_header_via_get_branch(via)==NULL){
char *branchid=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE "%x",belle_sip_random());
/*FIXME: should not be set random here: but rather a hash of message invariants*/
char *branchid=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",token);
belle_sip_header_via_set_branch(via,branchid);
belle_sip_free(branchid);
}
......@@ -100,11 +102,8 @@ static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_chan
belle_sip_uri_t* contact_uri;
/*probably better to be in channel*/
fix_outgoing_via((belle_sip_provider_t*)obj,chan,msg);
/*fill contact if needeed*/
if (!contact) {
contact = belle_sip_header_contact_new();
belle_sip_message_add_header(msg,(belle_sip_header_t*)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);
......@@ -142,7 +141,7 @@ belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_lis
}
int belle_sip_provider_add_listening_point(belle_sip_provider_t *p, belle_sip_listening_point_t *lp){
p->lps=belle_sip_list_append(p->lps,lp);
p->lps=belle_sip_list_append(p->lps,belle_sip_object_ref(lp));
return 0;
}
......@@ -240,6 +239,20 @@ belle_sip_response_t* belle_sip_response_event_get_response(const belle_sip_resp
/*private provider API*/
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t){
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t)){
belle_sip_provider_remove_client_transaction(p,(belle_sip_client_transaction_t*)t);
}
}
void belle_sip_provider_add_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t){
prov->client_transactions=belle_sip_list_prepend(prov->client_transactions,belle_sip_object_ref(t));
}
belle_sip_client_transaction_t * belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t *prov,
belle_sip_response_t *resp){
return NULL;
}
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);
}
......@@ -20,8 +20,6 @@
#include "listeningpoint_internal.h"
static void belle_sip_stack_destroy(belle_sip_stack_t *stack){
belle_sip_list_for_each (stack->lp,belle_sip_object_unref);
belle_sip_list_free(stack->lp);
belle_sip_object_unref(stack->ml);
}
......@@ -50,14 +48,10 @@ belle_sip_listening_point_t *belle_sip_stack_create_listening_point(belle_sip_st
} else {
belle_sip_fatal("Unsupported transport %s",transport);
}
if (lp!=NULL){
s->lp=belle_sip_list_append(s->lp,lp);
}
return lp;
}
void belle_sip_stack_delete_listening_point(belle_sip_stack_t *s, belle_sip_listening_point_t *lp){
s->lp=belle_sip_list_remove(s->lp,lp);
belle_sip_object_unref(lp);
}
......@@ -96,17 +90,4 @@ void belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t
hop->port=belle_sip_uri_get_listening_port(uri);
}
unsigned int belle_sip_random(void){
#ifdef __linux
static int fd=-1;
if (fd==-1) fd=open("/dev/urandom",O_RDONLY);
if (fd!=-1){
unsigned int tmp;
if (read(fd,&tmp,4)!=4){
belle_sip_error("Reading /dev/urandom failed.");
}else return tmp;
}else belle_sip_error("Could not open /dev/urandom");
#endif
return (unsigned int) random();
}
......@@ -19,7 +19,6 @@
#include "belle_sip_internal.h"
static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_provider_t *prov, belle_sip_request_t *req){
if (req) belle_sip_object_ref(req);
t->request=(belle_sip_request_t*)belle_sip_object_ref(req);
t->provider=prov;
}
......@@ -28,6 +27,7 @@ static void transaction_destroy(belle_sip_transaction_t *t){
if (t->request) belle_sip_object_unref(t->request);
if (t->prov_response) belle_sip_object_unref(t->prov_response);
if (t->final_response) belle_sip_object_unref(t->final_response);
if (t->channel) belle_sip_object_unref(t->channel);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_transaction_t);
......@@ -114,14 +114,15 @@ void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *
//BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_response((belle_sip_transaction_t*)t,resp);
}
/*
* client transaction
*/
belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t){
return NULL;
}
/*
* client transaction
*/
void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t){
belle_sip_hop_t hop={0};
......@@ -132,16 +133,18 @@ void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t
belle_sip_error("belle_sip_client_transaction_send_request: bad state.");
return;
}
belle_sip_stack_get_next_hop(prov->stack,t->base.request,&hop);
chan=belle_sip_provider_get_channel(prov,hop.host, hop.port, hop.transport);
if (chan){
belle_sip_object_ref(chan);
belle_sip_channel_add_listener(chan,BELLE_SIP_CHANNEL_LISTENER(t));
t->base.channel=chan;
if (belle_sip_channel_get_state(chan)==BELLE_SIP_CHANNEL_READY){
BELLE_SIP_OBJECT_VPTR(t,belle_sip_client_transaction_t)->send_request(t);
if (belle_sip_channel_get_state(chan)==BELLE_SIP_CHANNEL_INIT)
belle_sip_channel_prepare(chan);
if (belle_sip_channel_get_state(chan)!=BELLE_SIP_CHANNEL_READY){
belle_sip_message("belle_sip_client_transaction_send_request(): waiting channel to be ready");
}
}
}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){
......@@ -167,8 +170,10 @@ static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
belle_sip_client_transaction_t *t=(belle_sip_client_transaction_t*)l;
belle_sip_message("transaction on_channel_state_changed");
switch(state){
case BELLE_SIP_CHANNEL_READY:
belle_sip_provider_add_client_transaction(t->base.provider,t);
BELLE_SIP_OBJECT_VPTR(t,belle_sip_client_transaction_t)->send_request(t);
break;
default:
......@@ -199,6 +204,14 @@ 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){
belle_sip_header_via_set_branch(via,obj->base.branch_id);
}else{
belle_sip_fatal("belle_sip_client_transaction_init(): No via in request.");
}
belle_sip_transaction_init((belle_sip_transaction_t*)obj, prov,req);
}
......
......@@ -74,13 +74,13 @@ int stream_channel_connect(belle_sip_channel_t *obj, const struct sockaddr *addr
belle_sip_error("setsockopt TCP_NODELAY failed: [%s]",belle_sip_get_socket_error_string());
}
fcntl(sock,F_SETFL,fcntl(sock,F_GETFL) | O_NONBLOCK);
belle_sip_source_set_event((belle_sip_source_t*)obj,BELLE_SIP_EVENT_WRITE|BELLE_SIP_EVENT_ERROR);
belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_WRITE|BELLE_SIP_EVENT_ERROR);
belle_sip_main_loop_add_source(obj->stack->ml,(belle_sip_source_t*)obj);
err = connect(sock,addr,socklen);
if (err != 0 && get_socket_error()!=EINPROGRESS) {
belle_sip_error("stream connect failed %s",belle_sip_get_socket_error_string());
close_socket(sock);
return -1;
belle_sip_error("stream connect failed %s",belle_sip_get_socket_error_string());
close_socket(sock);
return -1;
}
return 0;
......@@ -112,6 +112,9 @@ static int process_data(belle_sip_channel_t *obj,unsigned int revents){
int err, errnum;
socklen_t optlen=sizeof(errnum);
belle_sip_fd_t fd=belle_sip_source_get_fd((belle_sip_source_t*)obj);
belle_sip_message("TCP channel process_data");
if (obj->state == BELLE_SIP_CHANNEL_CONNECTING && (revents&BELLE_SIP_EVENT_WRITE)) {
err=getsockopt(fd,SOL_SOCKET,SO_ERROR,&errnum,&optlen);
if (err!=0){
......@@ -127,11 +130,11 @@ static int process_data(belle_sip_channel_t *obj,unsigned int revents){
belle_sip_error("Failed to retrieve sockname for channel [%p]: cause [%s]",obj,belle_sip_get_socket_error_string());
goto connect_error;
}
belle_sip_source_set_event((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
belle_sip_channel_set_ready(obj,(struct sockaddr*)&ss,addrlen);
return BELLE_SIP_CONTINUE;
}else{
belle_sip_error("Connection failed for channel [%p]: cause [%s]",obj,belle_sip_get_socket_error_string());
belle_sip_error("Connection failed for channel [%p]: cause [%s]",obj,belle_sip_get_socket_error_string_from_code(errnum));
goto connect_error;
}
......@@ -139,16 +142,16 @@ static int process_data(belle_sip_channel_t *obj,unsigned int revents){
} else if ( obj->state == BELLE_SIP_CHANNEL_READY) {
belle_sip_channel_process_data(obj,revents);
} else {
belle_sip_error("Unexpected event [%i], for channel [%p]",revents,obj);
belle_sip_warning("Unexpected event [%i], for channel [%p]",revents,obj);
}
return BELLE_SIP_CONTINUE;
connect_error:
belle_sip_error("Cannot connect to [%s://%s:%s]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
channel_process_queue(obj);
return BELLE_SIP_STOP;
return BELLE_SIP_STOP;
}
belle_sip_channel_t * belle_sip_channel_new_tcp(belle_sip_stack_t *stack,const char *bindip, int localport, const char *dest, int port){
belle_sip_stream_channel_t *obj=belle_sip_object_new(belle_sip_stream_channel_t);
belle_sip_channel_init((belle_sip_channel_t*)obj
......
if BUILD_TESTS
noinst_PROGRAMS=belle_sip_tester belle_sip_object_describe
......@@ -27,6 +28,6 @@ AM_CFLAGS=$(STRICT_OPTIONS)
test: belle_sip_tester
./belle_sip_tester
./belle_sip_tester $(TEST_OPTIONS)
endif
......@@ -20,10 +20,11 @@
#include "CUnit/Basic.h"
#include "belle-sip/belle-sip.h"
#include "pthread.h"
const char *test_domain="localhost";
static int is_register_ok;
static belle_sip_stack_t * stack;
#define TEST_DOMAIN "localhost"
/*#define TEST_DOMAIN "test.linphone.org"*/
static belle_sip_provider_t *prov;
static void process_dialog_terminated(belle_sip_listener_t *obj, const belle_sip_dialog_terminated_event_t *event){
belle_sip_message("process_dialog_terminated called");
......@@ -77,65 +78,91 @@ BELLE_SIP_IMPLEMENT_INTERFACE_END
BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(test_listener_t,belle_sip_listener_t);
BELLE_SIP_INSTANCIATE_VPTR(test_listener_t,belle_sip_object_t,NULL,NULL,NULL,FALSE);
static test_listener_t *listener;
static int init(void) {
stack=belle_sip_stack_new(NULL);
belle_sip_listening_point_t *lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7060,"UDP");
prov=belle_sip_stack_create_provider(stack,lp);
belle_sip_object_unref(lp);
lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7060,"TCP");
belle_sip_provider_add_listening_point(prov,lp);
belle_sip_object_unref(lp);
listener=belle_sip_object_new(test_listener_t);
belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(listener));
return 0;
}
static int uninit(void) {
belle_sip_object_unref(prov);
belle_sip_object_unref(stack);
belle_sip_object_unref(listener);
return 0;
}
static void register_test(belle_sip_listening_point_t* lp,belle_sip_uri_t* uri) {
belle_sip_provider_t *prov;
static void register_test(const char *transport, int use_transaction) {
belle_sip_request_t *req;
test_listener_t *listener=belle_sip_object_new(test_listener_t);
char token[10];
char identity[256];
char uri[256];
belle_sip_set_log_level(BELLE_SIP_LOG_DEBUG);
if (transport)
snprintf(uri,sizeof(uri),"sip:%s;transport=%s",test_domain,transport);
else snprintf(uri,sizeof(uri),"sip:%s",test_domain);
prov=belle_sip_stack_create_provider(stack,lp);
belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(listener));
snprintf(identity,sizeof(identity),"Tester <sip:tester@%s>",test_domain);
req=belle_sip_request_create(