Commit b7e6f282 authored by jehan's avatar jehan

Fix for duplicated sent message in case of ewouldblock

parent a8797583
......@@ -600,7 +600,7 @@ BELLESIP_EXPORT belle_sip_server_transaction_t * belle_sip_provider_find_matchin
void belle_sip_provider_remove_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t);
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t);
void *belle_sip_transaction_get_application_data_internal(const belle_sip_transaction_t *t);
belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, const belle_sip_hop_t *hop);
BELLESIP_EXPORT belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, const belle_sip_hop_t *hop);
void belle_sip_provider_add_dialog(belle_sip_provider_t *prov, belle_sip_dialog_t *dialog);
void belle_sip_provider_remove_dialog(belle_sip_provider_t *prov, belle_sip_dialog_t *dialog);
void belle_sip_provider_release_channel(belle_sip_provider_t *p, belle_sip_channel_t *chan);
......@@ -1106,7 +1106,10 @@ void belle_sip_multipart_body_handler_progress_cb(belle_sip_body_handler_t *obj,
belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_type);
typedef struct authorization_context authorization_context_t;
BELLESIP_EXPORT void belle_sip_authorization_destroy(authorization_context_t* object);
typedef authorization_context_t belle_sip_authorization_t;
BELLESIP_EXPORT void belle_sip_authorization_destroy(belle_sip_authorization_t* object);
BELLESIP_EXPORT const char *belle_sip_authorization_get_algorithm(const belle_sip_authorization_t* object);
/**
* Generate a random unsigned int
......
......@@ -1274,6 +1274,9 @@ static void _send_message(belle_sip_channel_t *obj){
obj->ewouldblock_offset+=sendret;
if (obj->ewouldblock_offset==obj->ewouldblock_size){
free_ewouldblock_buffer(obj);
if (obj->out_state==OUTPUT_STREAM_SENDING_HEADERS)
goto done; //to avoid message to be sent twice
/*else continue body sending*/
}
/* continue to expedite the ewouldblock error until we it is completed or get a new ewouldblock*/
}else if (belle_sip_error_code_is_would_block(-sendret)) {
......@@ -1413,7 +1416,7 @@ static void channel_process_queue(belle_sip_channel_t *obj){
_send_message(obj);
}
while (obj->state==BELLE_SIP_CHANNEL_READY && obj->out_state==OUTPUT_STREAM_IDLE && ((msg = channel_pop_outgoing(obj)) != NULL)) {
while (obj->state == BELLE_SIP_CHANNEL_READY && obj->out_state == OUTPUT_STREAM_IDLE && (msg = channel_pop_outgoing(obj)) != NULL) {
send_message(obj, msg);
belle_sip_object_unref(msg);
}
......
......@@ -116,7 +116,7 @@ static BELLESIP_INLINE int get_socket_error(void){
return WSAGetLastError();
}
const char *belle_sip_get_socket_error_string();
BELLESIP_EXPORT const char *belle_sip_get_socket_error_string();
const char *belle_sip_get_socket_error_string_from_code(int code);
/*
......
......@@ -44,6 +44,7 @@ GET_SET_STRING(authorization_context,opaque)
GET_SET_STRING(authorization_context,user_id)
GET_SET_STRING(authorization_context,algorithm)
GET_SET_INT(authorization_context,nonce_count,int)
static authorization_context_t* belle_sip_authorization_create(belle_sip_header_call_id_t* call_id) {
authorization_context_t* result = malloc(sizeof(authorization_context_t));
memset(result,0,sizeof(authorization_context_t));
......@@ -51,6 +52,7 @@ static authorization_context_t* belle_sip_authorization_create(belle_sip_header_
belle_sip_object_ref(result->callid);
return result;
}
void belle_sip_authorization_destroy(authorization_context_t* object) {
DESTROY_STRING(object,scheme);
DESTROY_STRING(object,realm);
......@@ -63,6 +65,10 @@ void belle_sip_authorization_destroy(authorization_context_t* object) {
belle_sip_free(object);
}
const char *belle_sip_authorization_get_algorithm(const belle_sip_authorization_t* object) {
return authorization_context_get_algorithm(object);
}
static void finalize_transaction(belle_sip_transaction_t *tr){
belle_sip_transaction_state_t state=belle_sip_transaction_get_state(tr);
if (state!=BELLE_SIP_TRANSACTION_TERMINATED){
......
......@@ -79,6 +79,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set_target_properties(belle_sip_tester_runtime PROPERTIES LIBRARY_OUTPUT_NAME "BelledonneCommunications.BelleSip.Tester")
set_target_properties(belle_sip_tester_runtime PROPERTIES LINK_FLAGS "/WINMDFILE:BelledonneCommunications.BelleSip.Tester.winmd")
set_target_properties(belle_sip_tester_runtime PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
set_target_properties(belle_sip_tester_runtime PROPERTIES C_STANDARD 99)
install(TARGETS belle_sip_tester_runtime
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
......@@ -102,6 +104,7 @@ else()
add_executable(belle_sip_tester ${USE_BUNDLE} ${SOURCE_FILES_C} ${SOURCE_FILES_OBJC})
set_target_properties(belle_sip_tester PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(belle_sip_tester PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
set_target_properties(belle_sip_tester PROPERTIES C_STANDARD 99)
if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
set_target_properties(belle_sip_tester PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}")
......
......@@ -251,7 +251,7 @@ static void https_post_long_body(void){
http_counters_t counters={0};
belle_sip_user_body_handler_t *bh;
char *content_type;
const char *url="https://www.linphone.org:444/upload.php";
const char *url="https://www.linphone.org:444/lft.php";
if (url_supported(url)==-1) {
return;
}
......
......@@ -24,11 +24,11 @@
const int RANDOM_PORT = -1;
const char *test_domain="sip2.linphone.org";
const char *auth_domain="sip.linphone.org";
#define AUTH_DOMAIN "sip.example.org"
const char *test_domain="sipopen.example.org";
const char *auth_domain=AUTH_DOMAIN;
const char *client_auth_domain="client.example.org";
const char *client_auth_outbound_proxy="sips:sip2.linphone.org:5063";
const char *client_auth_outbound_proxy="sips:sip.example.org:5063";
const char *no_server_running_here="sip:test.linphone.org:3;transport=tcp";
const char *no_response_here="sip:78.220.48.77:3;transport=%s";
const char *test_domain_tls_to_tcp="sip:sip2.linphone.org:5060;transport=tls";
......@@ -895,12 +895,12 @@ static belle_sip_request_t* send_message_to(belle_sip_request_t *initial_request
is_register_ok = 0;
message_request=belle_sip_request_create(
belle_sip_uri_parse("sip:sip.linphone.org;transport=tcp")
belle_sip_uri_parse("sip:"AUTH_DOMAIN";transport=tcp")
,"MESSAGE"
,belle_sip_provider_create_call_id(prov)
,belle_sip_header_cseq_create(22,"MESSAGE")
,belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(initial_request), belle_sip_header_from_t)
,belle_sip_header_to_parse("To: sip:marie@sip.linphone.org")
,belle_sip_header_to_parse("To: sip:marie@"AUTH_DOMAIN)
,belle_sip_header_via_new()
,70);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(message_request),BELLE_SIP_HEADER(belle_sip_header_expires_create(600)));
......@@ -921,7 +921,6 @@ static belle_sip_request_t* send_message_to(belle_sip_request_t *initial_request
static void reuse_nonce_base(const char* outbound) {
belle_sip_request_t *register_request;
size_t initial_auth_context_count=0;/*belle_sip_list_size(prov->auth_contexts);*/
char outbound_uri[256];
/*reset auth context*/
prov->auth_contexts = belle_sip_list_free_with_data(prov->auth_contexts,(void(*)(void*))belle_sip_authorization_destroy);
......@@ -929,7 +928,7 @@ static void reuse_nonce_base(const char* outbound) {
if (outbound)
snprintf(outbound_uri, sizeof(outbound_uri),"sip:%s",outbound);
register_request=register_user_at_domain(stack, prov, "tcp",1,"marie",outbound,NULL);
register_request=register_user_at_domain(stack, prov, "tcp",1,"marie",auth_domain, outbound);
if (register_request) {
belle_sip_header_authorization_t * h = NULL;
......@@ -948,9 +947,24 @@ static void reuse_nonce_base(const char* outbound) {
belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(reuse_nonce_listener));
/*currently only one nonce should have been used (the one for the REGISTER)*/
BC_ASSERT_EQUAL((unsigned int)belle_sip_list_size(prov->auth_contexts), (unsigned int)initial_auth_context_count+1,unsigned int,"%u");
unsigned int number_of_md5_auth_context = 0;
unsigned int number_of_sha256_auth_context = 0;
for (belle_sip_list_t *it = prov->auth_contexts ;it!=NULL ; it=it->next) {
belle_sip_authorization_t *auth_context=(authorization_context_t*)it->data;
if (!belle_sip_authorization_get_algorithm(auth_context) || strcasecmp(belle_sip_authorization_get_algorithm(auth_context),"MD5"))
number_of_md5_auth_context++;
else if (strcasecmp(belle_sip_authorization_get_algorithm(auth_context),"SHA256"))
number_of_sha256_auth_context++;
else
belle_sip_error("This test does not support algo [%s]",belle_sip_authorization_get_algorithm(auth_context) );
}
/*currently only one nonce by algo should have been used (the one for the REGISTER)*/
BC_ASSERT_LOWER(number_of_md5_auth_context, 1 ,unsigned int,"%u");
BC_ASSERT_LOWER(number_of_sha256_auth_context, 1 ,unsigned int,"%u");
BC_ASSERT_GREATER((number_of_sha256_auth_context + number_of_md5_auth_context), 1 ,unsigned int,"%u");
/*this should reuse previous nonce*/
message_request=send_message_to(register_request, auth_domain,outbound?belle_sip_uri_parse(outbound_uri):NULL);
BC_ASSERT_EQUAL(is_register_ok, 404,int,"%d");
......@@ -1008,7 +1022,7 @@ static void reuse_nonce_base(const char* outbound) {
}
}
static void reuse_nonce(void) {
reuse_nonce_base("sip.linphone.org");
reuse_nonce_base(auth_domain);
}
#define NONCE_SIZE 32
void register_process_request_event(char *nonce, const belle_sip_request_event_t *event) {
......@@ -1049,8 +1063,8 @@ void register_process_request_event(char *nonce, const belle_sip_request_event_t
belle_sip_header_www_authenticate_t *www_authenticate = 401?belle_sip_header_www_authenticate_new():BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_header_proxy_authenticate_new());
belle_sip_header_www_authenticate_set_realm(www_authenticate, "sip.linphone.org");
belle_sip_header_www_authenticate_set_domain(www_authenticate, "sip:sip.linphone.org");
belle_sip_header_www_authenticate_set_realm(www_authenticate, AUTH_DOMAIN);
belle_sip_header_www_authenticate_set_domain(www_authenticate, "sip:"AUTH_DOMAIN);
belle_sip_header_www_authenticate_set_scheme(www_authenticate, "Digest");
belle_sip_header_www_authenticate_set_nonce(www_authenticate,nonce);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response_msg), BELLE_SIP_HEADER(www_authenticate));
......@@ -1089,6 +1103,87 @@ static void test_register_with_next_nonce(void) {
belle_sip_provider_remove_listening_point(prov, server_lp);
}
static void test_channel_load_process_response_event(void* user_ctx, const belle_sip_response_event_t *event){
if (!BC_ASSERT_PTR_NOT_NULL(belle_sip_response_event_get_response(event))) {
return;
}
belle_sip_message("process_response_event [%i] [%s] number [%i]"
,belle_sip_response_get_status_code(belle_sip_response_event_get_response(event))
,belle_sip_response_get_reason_phrase(belle_sip_response_event_get_response(event))
,*(int*)user_ctx);
(*(int*)user_ctx) ++;
return;
}
#define NUMBER_OF_TRANS 20
static void test_channel_load(void){
belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(prov,"TCP");
BC_ASSERT_PTR_NOT_NULL(lp);
if (lp) {
belle_sip_request_t *req;
belle_sip_client_transaction_t *tr[NUMBER_OF_TRANS];
char identity[128];
char uri[128];
snprintf(identity,sizeof(identity),"Tester <sip:%s@%s>","bellesip",auth_domain);
snprintf(uri,sizeof(uri),"sip:%s;transport=tcp",auth_domain);
belle_sip_listener_callbacks_t listener_callbacks;
listener_callbacks.process_dialog_terminated = NULL;
listener_callbacks.process_io_error = NULL;
listener_callbacks.process_request_event = NULL;
listener_callbacks.process_response_event = test_channel_load_process_response_event;
listener_callbacks.process_timeout = NULL;
listener_callbacks.process_transaction_terminated = NULL;
listener_callbacks.process_auth_requested = NULL;
listener_callbacks.listener_destroyed = NULL;
int number_of_response=0;
int i;
belle_sip_listener_t *listener = belle_sip_listener_create_from_callbacks(&listener_callbacks, (void *)&number_of_response);
belle_sip_provider_add_sip_listener(prov,listener);
for (i = 0; i <NUMBER_OF_TRANS; i++ ) {
req = belle_sip_request_create(
belle_sip_uri_parse(uri),
"REGISTER",
belle_sip_provider_create_call_id(prov),
belle_sip_header_cseq_create(20,"REGISTER"),
belle_sip_header_from_create2(identity,BELLE_SIP_RANDOM_TAG),
belle_sip_header_to_create2(identity,NULL),
belle_sip_header_via_new(),
70);
tr[i] = belle_sip_provider_create_client_transaction(prov, req);
belle_sip_object_ref(tr[i]);
}
belle_sip_client_transaction_send_request(tr[0]);
for (int j=0; j < 10 && number_of_response < 1; j++) {
belle_sip_stack_sleep(stack, 500);
}
belle_sip_channel_t *chan = belle_sip_provider_get_channel(prov,tr[0]->next_hop);
belle_sip_socket_t sock = belle_sip_source_get_socket((belle_sip_source_t*)chan);
size_t sendbuff = 50;
int err = bctbx_setsockopt((bctbx_socket_t)sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));
if (err != 0){
belle_sip_error("bctbx_setsockopt SOL_SOCKET failed: [%s]",belle_sip_get_socket_error_string());
}
for (i = 1; i <NUMBER_OF_TRANS; i++ ) {
belle_sip_client_transaction_send_request(tr[i]);
belle_sip_object_ref(tr[i]);
}
for (int j=0; j < 10 && number_of_response < NUMBER_OF_TRANS; j++) {
belle_sip_stack_sleep(stack, 500);
}
BC_ASSERT_EQUAL(number_of_response,NUMBER_OF_TRANS,int,"%d");
}
}
test_t register_tests[] = {
TEST_NO_TAG("Stateful UDP", stateful_register_udp),
TEST_NO_TAG("Stateful UDP with keep-alive", stateful_register_udp_with_keep_alive),
......@@ -1118,7 +1213,8 @@ test_t register_tests[] = {
TEST_NO_TAG("Register with DNS SRV failover TLS with http proxy", register_dns_srv_tls_with_http_proxy),
TEST_NO_TAG("Register with DNS load-balancing", register_dns_load_balancing),
TEST_NO_TAG("Nonce reutilization", reuse_nonce),
TEST_NO_TAG("Next Nonce", test_register_with_next_nonce)
TEST_NO_TAG("Next Nonce", test_register_with_next_nonce),
TEST_NO_TAG("Channel load", test_channel_load)
};
test_suite_t register_test_suite = {"Register", register_before_all, register_after_all, NULL,
......
127.0.0.1 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org sipv4.example.org conf.example.org subscribe.example.org lime.wildcard1.linphone.org http-proxy.example.org cn.example.org
::1 lime.wildcard1.linphone.org sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org cn.example.org
188.165.46.90 tunnel.wildcard2.linphone.org
64:ff9b::94.23.19.176 sipv4-nat64.example.org
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