Commit efd3a29e authored by Simon Morlat's avatar Simon Morlat
Browse files

add TCP server socket with ipv4 and ipv6

parent c84fb68c
......@@ -251,15 +251,28 @@ int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,const char *bindip,int localport,const char *peername, int peer_port){
obj->peer_name=belle_sip_strdup(peername);
obj->peer_port=peer_port;
obj->peer=NULL;
obj->stack=stack;
if (strcmp(bindip,"::0")!=0 && strcmp(bindip,"0.0.0.0")!=0)
if (bindip && strcmp(bindip,"::0")!=0 && strcmp(bindip,"0.0.0.0")!=0)
obj->local_ip=belle_sip_strdup(bindip);
obj->local_port=localport;
obj->recv_error=1;/*not set*/
belle_sip_channel_input_stream_reset(&obj->input_stream);
}
void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const struct sockaddr *peer_addr, socklen_t addrlen){
char remoteip[64];
struct addrinfo ai;
int peer_port;
memset(&ai,0,sizeof(ai));
ai.ai_family=peer_addr->sa_family;
ai.ai_addr=(struct sockaddr*)peer_addr;
ai.ai_addrlen=addrlen;
belle_sip_addrinfo_to_ip(&ai,remoteip,sizeof(remoteip),&peer_port);
belle_sip_channel_init(obj,stack,NULL,0,remoteip,peer_port);
obj->peer=belle_sip_ip_address_to_addrinfo(ai.ai_family, obj->peer_name,obj->peer_port);
}
void belle_sip_channel_set_socket(belle_sip_channel_t *obj, belle_sip_socket_t sock, belle_sip_source_func_t datafunc){
belle_sip_socket_source_init((belle_sip_source_t*)obj
, datafunc
......@@ -477,7 +490,7 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr
if (obj->local_ip==NULL){
int err=getnameinfo(addr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
if (err!=0){
belle_sip_error("belle_sip_channel_connect(): getnameinfo() failed: %s",gai_strerror(err));
belle_sip_error("belle_sip_channel_set_ready(): getnameinfo() failed: %s",gai_strerror(err));
}else{
obj->local_ip=belle_sip_strdup(name);
obj->local_port=atoi(serv);
......
......@@ -117,6 +117,7 @@ int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen);
/*only used by channels implementation*/
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen);
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const char *bindip,int localport,const char *peername, int peer_port);
void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const struct sockaddr *peer_addr, socklen_t addrlen);
void belle_sip_channel_set_socket(belle_sip_channel_t *obj, belle_sip_socket_t sock, belle_sip_source_func_t datafunc);
/*end of channel implementations*/
/**
......
......@@ -66,7 +66,7 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
/*stream*/
typedef struct belle_sip_stream_listening_point belle_sip_stream_listening_point_t;
belle_sip_channel_t * belle_sip_channel_new_tcp(belle_sip_stack_t *stack, const char *bindip, int localport,const char *name, int port);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_stream_listening_point_t,belle_sip_listening_point_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
#define BELLE_SIP_STREAM_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,belle_sip_stream_listening_point_t)
......@@ -89,6 +89,7 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_listening_point_t * belle_sip_tls_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port);
belle_sip_channel_t * belle_sip_channel_new_tls(belle_sip_tls_listening_point_t* lp, const char *bindip, int localport,const char *name, int port);
#include "transports/stream_channel.h"
#endif /* LISTENINGPOINT_INTERNAL_H_ */
......@@ -324,7 +324,8 @@ void belle_sip_refresher_stop(belle_sip_refresher_t* refresher) {
belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* transaction) {
belle_sip_refresher_t* refresher;
if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction)) != BELLE_SIP_TRANSACTION_COMPLETED) {
belle_sip_transaction_state_t state=belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction));
if (state != BELLE_SIP_TRANSACTION_COMPLETED && state!=BELLE_SIP_TRANSACTION_TERMINATED ) {
belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED"
,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction)))
,transaction);
......
......@@ -127,6 +127,7 @@ int finalize_stream_connection (belle_sip_socket_t sock, struct sockaddr *addr,
belle_sip_error("Failed to retrieve sockname for fd [%i]: cause [%s]",sock,belle_sip_get_socket_error_string());
return -1;
}
belle_sip_address_remove_v4_mapping(addr,addr,slen);
return 0;
}else{
belle_sip_error("Connection failed for fd [%i]: cause [%s]",sock,belle_sip_get_socket_error_string_from_code(errnum));
......@@ -134,6 +135,7 @@ int finalize_stream_connection (belle_sip_socket_t sock, struct sockaddr *addr,
}
}
}
static int stream_channel_process_data(belle_sip_channel_t *obj,unsigned int revents){
struct sockaddr_storage ss;
socklen_t addrlen=sizeof(ss);
......@@ -161,10 +163,34 @@ static int stream_channel_process_data(belle_sip_channel_t *obj,unsigned int rev
return BELLE_SIP_CONTINUE;
}
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_channel_t * belle_sip_stream_channel_new_client(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
,stack
,bindip,localport,dest,port);
return (belle_sip_channel_t*)obj;
}
belle_sip_channel_t * belle_sip_stream_channel_new_child(belle_sip_stack_t *stack, belle_sip_socket_t sock, struct sockaddr *remote_addr, socklen_t slen){
struct sockaddr_storage localaddr;
socklen_t local_len=sizeof(localaddr);
belle_sip_stream_channel_t *obj;
if (getsockname(sock,(struct sockaddr*)&localaddr,&local_len)==-1){
belle_sip_error("getsockname() failed: %s",belle_sip_get_socket_error_string());
return NULL;
}
belle_sip_address_remove_v4_mapping((struct sockaddr*)&localaddr,(struct sockaddr*)&localaddr,&local_len);
belle_sip_address_remove_v4_mapping(remote_addr,remote_addr,&slen);
obj=belle_sip_object_new(belle_sip_stream_channel_t);
belle_sip_channel_init_with_addr((belle_sip_channel_t*)obj,stack,remote_addr,slen);
belle_sip_socket_set_nonblocking(sock);
belle_sip_channel_set_socket((belle_sip_channel_t*)obj,sock,(belle_sip_source_func_t)stream_channel_process_data);
belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
belle_sip_channel_set_ready((belle_sip_channel_t*)obj,(struct sockaddr*)&localaddr,local_len);
belle_sip_main_loop_add_source(stack->ml,(belle_sip_source_t*)obj);
return (belle_sip_channel_t*)obj;
}
......@@ -27,6 +27,9 @@ struct belle_sip_stream_channel{
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_stream_channel_t,belle_sip_channel_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_channel_t * belle_sip_stream_channel_new_client(belle_sip_stack_t *stack, const char *bindip, int localport,const char *name, int port);
belle_sip_channel_t * belle_sip_stream_channel_new_child(belle_sip_stack_t *stack, belle_sip_socket_t sock, struct sockaddr *remote_addr, socklen_t slen);
void stream_channel_close(belle_sip_channel_t *obj);
int stream_channel_connect(belle_sip_channel_t *obj, const struct addrinfo *ai);
/*return 0 if succeed*/
......
......@@ -17,19 +17,36 @@
*/
#include "belle_sip_internal.h"
static int on_new_connection(void *userdata, unsigned int events);
struct belle_sip_stream_listening_point{
belle_sip_listening_point_t base;
belle_sip_socket_t server_sock;
belle_sip_source_t *source;
};
static void destroy_server_socket(belle_sip_stream_listening_point_t *lp){
if (lp->server_sock!=(belle_sip_socket_t)-1){
close_socket(lp->server_sock);
lp->server_sock=-1;
}
if (lp->source){
belle_sip_main_loop_remove_source(lp->base.stack->ml,lp->source);
belle_sip_object_unref(lp->source);
lp->source=NULL;
}
}
static void belle_sip_stream_listening_point_uninit(belle_sip_stream_listening_point_t *lp){
destroy_server_socket(lp);
}
static belle_sip_channel_t *stream_create_channel(belle_sip_listening_point_t *lp, const char *dest_ip, int port){
belle_sip_channel_t *chan=belle_sip_channel_new_tcp(lp->stack
,belle_sip_uri_get_host(lp->listening_uri)
,belle_sip_uri_get_port(lp->listening_uri)
,dest_ip,port);
belle_sip_channel_t *chan=belle_sip_stream_channel_new_client(lp->stack
,belle_sip_uri_get_host(lp->listening_uri)
,belle_sip_uri_get_port(lp->listening_uri)
,dest_ip,port);
return chan;
}
......@@ -47,10 +64,93 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_stream_listening_point_t)={
}
};
static belle_sip_socket_t create_server_socket(const char *addr, int port, int *family){
struct addrinfo hints={0};
struct addrinfo *res=NULL;
int err;
belle_sip_socket_t sock;
char portnum[10];
int optval=1;
snprintf(portnum,sizeof(portnum),"%i",port);
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;
hints.ai_protocol=IPPROTO_TCP;
hints.ai_flags=AI_NUMERICSERV;
err=getaddrinfo(addr,portnum,&hints,&res);
if (err!=0){
belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,port,gai_strerror(err));
return -1;
}
*family=res->ai_family;
sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
if (sock==-1){
belle_sip_error("Cannot create UDP socket: %s",belle_sip_get_socket_error_string());
freeaddrinfo(res);
return -1;
}
err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char*)&optval, sizeof (optval));
if (err == -1){
belle_sip_warning ("Fail to set SIP/UDP address reusable: %s.", belle_sip_get_socket_error_string());
}
err=bind(sock,res->ai_addr,res->ai_addrlen);
if (err==-1){
belle_sip_error("TCP bind() failed for %s port %i: %s",addr,port,belle_sip_get_socket_error_string());
close_socket(sock);
freeaddrinfo(res);
return -1;
}
freeaddrinfo(res);
err=listen(sock,64);
if (err==-1){
belle_sip_error("TCP listen() failed for %s port %i: %s",addr,port,belle_sip_get_socket_error_string());
close_socket(sock);
}
return sock;
}
static void setup_server_socket(belle_sip_stream_listening_point_t *obj){
obj->server_sock=create_server_socket(belle_sip_uri_get_host(obj->base.listening_uri),
belle_sip_uri_get_port(obj->base.listening_uri),&obj->base.ai_family);
if (obj->server_sock==(belle_sip_socket_t)-1) return;
obj->source=belle_sip_socket_source_new(on_new_connection,obj,obj->server_sock,BELLE_SIP_EVENT_READ,-1);
belle_sip_main_loop_add_source(obj->base.stack->ml,obj->source);
}
static int on_new_connection(void *userdata, unsigned int events){
belle_sip_socket_t child;
struct sockaddr_storage addr;
socklen_t slen=sizeof(addr);
belle_sip_stream_listening_point_t *lp=(belle_sip_stream_listening_point_t*)userdata;
belle_sip_channel_t *chan;
child=accept(lp->server_sock,(struct sockaddr*)&addr,&slen);
if (child==(belle_sip_socket_t)-1){
belle_sip_error("Listening point [%p] accept() failed on TCP server socket: %s",lp,belle_sip_get_socket_error_string());
destroy_server_socket(lp);
setup_server_socket(lp);
return BELLE_SIP_STOP;
}
belle_sip_message("New connection arriving !");
chan=belle_sip_stream_channel_new_child(lp->base.stack,child,(struct sockaddr*)&addr,slen);
if (chan) belle_sip_listening_point_add_channel((belle_sip_listening_point_t*)lp,chan);
return BELLE_SIP_CONTINUE;
}
void belle_sip_stream_listening_point_init(belle_sip_stream_listening_point_t *obj, belle_sip_stack_t *s, const char *ipaddress, int port){
belle_sip_listening_point_init((belle_sip_listening_point_t*)obj,s,ipaddress,port);
setup_server_socket(obj);
}
belle_sip_listening_point_t * belle_sip_stream_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port){
belle_sip_stream_listening_point_t *lp=belle_sip_object_new(belle_sip_stream_listening_point_t);
belle_sip_listening_point_init((belle_sip_listening_point_t*)lp,s,ipaddress,port);
belle_sip_stream_listening_point_init(lp,s,ipaddress,port);
if (lp->server_sock==(belle_sip_socket_t)-1){
belle_sip_object_unref(lp);
return NULL;
}
return BELLE_SIP_LISTENING_POINT(lp);
}
......@@ -85,8 +85,7 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int port, int *fam
}
err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char*)&optval, sizeof (optval));
if (err ==-1)
{
if (err == -1){
belle_sip_warning ("Fail to set SIP/UDP address reusable: %s.", belle_sip_get_socket_error_string());
}
......
......@@ -59,6 +59,7 @@ typedef struct endpoint {
int rport;
unsigned char unreconizable_contact;
int connection_family;
int register_count;
} endpoint_t;
......@@ -288,6 +289,7 @@ static endpoint_t* create_endpoint(const char *ip, int port,const char* transpor
belle_sip_provider_add_sip_listener(endpoint->provider,(endpoint->listener=belle_sip_listener_create_from_callbacks(endpoint->listener_callbacks,endpoint)));
sprintf(endpoint->nonce,"%p",endpoint); /*initial nonce*/
endpoint->nonce_count=1;
endpoint->register_count=3;
return endpoint;
}
......@@ -363,13 +365,13 @@ static void register_base(endpoint_t* client,endpoint_t *server) {
belle_sip_refresher_set_listener(refresher,belle_sip_refresher_listener,client);
begin = belle_sip_time_ms();
CU_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,3,4000));
CU_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,client->register_count,client->register_count*1000 + 1000));
end = belle_sip_time_ms();
CU_ASSERT_TRUE(end-begin>=3000);
CU_ASSERT_TRUE(end-begin<5000);
CU_ASSERT_TRUE(end-begin>=client->register_count*1000);
CU_ASSERT_TRUE(end-begin<(client->register_count*1000 + 2000));
/*unregister*/
belle_sip_refresher_refresh(refresher,0);
CU_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,4,1000));
CU_ASSERT_TRUE(wait_for(server->stack,client->stack,&client->stat.refreshOk,client->register_count+1,1000));
belle_sip_refresher_stop(refresher);
belle_sip_object_unref(refresher);
}
......@@ -514,6 +516,7 @@ static int register_test_with_interfaces(const char *transport, const char *clie
server_callbacks.process_request_event=server_process_request_event;
client = create_endpoint(client_ip,3452,transport,&client_callbacks);
client->connection_family=connection_family;
client->register_count=1;
server = create_endpoint(server_ip,6788,transport,&server_callbacks);
server->expire_in_contact=client->expire_in_contact=0;
......@@ -544,6 +547,23 @@ static void register_test_ipv6_to_ipv6_with_ipv6(void){
register_test_with_interfaces("udp","::0","::0",AF_INET6);
}
static void register_tcp_test_ipv6_to_ipv4(void){
register_test_with_interfaces("tcp","::0","0.0.0.0",AF_INET);
}
static void register_tcp_test_ipv4_to_ipv6(void){
register_test_with_interfaces("tcp","0.0.0.0","::0",AF_INET);
}
static void register_tcp_test_ipv6_to_ipv6_with_ipv4(void){
register_test_with_interfaces("tcp","::0","::0",AF_INET);
}
static void register_tcp_test_ipv6_to_ipv6_with_ipv6(void){
register_test_with_interfaces("tcp","::0","::0",AF_INET6);
}
test_t refresher_tests[] = {
{ "REGISTER Expires header", register_expires_header },
......@@ -555,7 +575,11 @@ test_t refresher_tests[] = {
{ "REGISTER UDP from ipv6 to ipv4", register_test_ipv6_to_ipv4 },
{ "REGISTER UDP from ipv4 to ipv6", register_test_ipv4_to_ipv6 },
{ "REGISTER UDP from ipv6 to ipv6 with ipv4", register_test_ipv6_to_ipv6_with_ipv4 },
{ "REGISTER UDP from ipv6 to ipv6 with ipv6", register_test_ipv6_to_ipv6_with_ipv6 }
{ "REGISTER UDP from ipv6 to ipv6 with ipv6", register_test_ipv6_to_ipv6_with_ipv6 },
{ "REGISTER TCP from ipv6 to ipv4", register_tcp_test_ipv6_to_ipv4 },
{ "REGISTER TCP from ipv4 to ipv6", register_tcp_test_ipv4_to_ipv6 },
{ "REGISTER TCP from ipv6 to ipv6 with ipv4", register_tcp_test_ipv6_to_ipv6_with_ipv4 },
{ "REGISTER TCP from ipv6 to ipv6 with ipv6", register_tcp_test_ipv6_to_ipv6_with_ipv6 }
};
test_suite_t refresher_test_suite = {
......
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