diff --git a/src/channel.c b/src/channel.c index 43c5e6d322b6c7b482c70b40bbb210adcd740ee9..fb818ea10a32769b350d6bf4ad784bd68eee8b8e 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1570,7 +1570,7 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr char name[NI_MAXHOST]; char serv[NI_MAXSERV]; - if (obj->local_ip == NULL) { + if (obj->local_ip == NULL || obj->local_port <= 0) { struct sockaddr_storage saddr; socklen_t slen2 = sizeof(saddr); int err; @@ -1582,7 +1582,7 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr if (err != 0) { belle_sip_error("belle_sip_channel_set_ready(): getnameinfo() failed: %s", gai_strerror(err)); } else { - obj->local_ip = belle_sip_strdup(name); + if (obj->local_ip == NULL) obj->local_ip = belle_sip_strdup(name); obj->local_port = atoi(serv); belle_sip_message("Channel has local address %s:%s", name, serv); } diff --git a/src/message.cc b/src/message.cc index 1d09d0b954c4faf386a857c99c62b3fc4b7f0235..8d0bee09fbcba8d3b94a7656dc9bdb3b2486b228 100644 --- a/src/message.cc +++ b/src/message.cc @@ -905,6 +905,9 @@ belle_sip_response_t *belle_sip_response_create_from_request(belle_sip_request_t if (h) { belle_sip_message_add_header((belle_sip_message_t *)resp, h); } + belle_sip_message_set_channel_bank_identifier( + (belle_sip_message_t *)resp, belle_sip_message_get_channel_bank_identifier((belle_sip_message_t *)req)); + return resp; } /* diff --git a/src/transaction.c b/src/transaction.c index c071317c76925287fbeb48d2987412831ee547f6..31d3a83dd490f7208eda4f54186d1a883accf401 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -369,9 +369,6 @@ void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t * belle_sip_object_ref(resp); if (!base->last_response || !base->channel) { belle_sip_hop_t *hop; - belle_sip_message_set_channel_bank_identifier( - (belle_sip_message_t *)resp, - belle_sip_message_get_channel_bank_identifier((belle_sip_message_t *)base->request)); hop = belle_sip_response_get_return_hop(resp); base->channel = belle_sip_provider_get_channel(base->provider, hop); belle_sip_object_unref(hop); diff --git a/tester/belle_sip_refresher_tester.c b/tester/belle_sip_refresher_tester.c index fea69ca678c5d45b74886aabad345b62c25e853f..09223eb84ec54d41e136d1444a0d6217fb426406 100644 --- a/tester/belle_sip_refresher_tester.c +++ b/tester/belle_sip_refresher_tester.c @@ -88,6 +88,7 @@ typedef struct endpoint { unsigned char unreconizable_contact; unsigned char bad_next_nonce; unsigned char expect_failed_auth; + void *test_data; } endpoint_t; static unsigned int wait_for(belle_sip_stack_t *s1, belle_sip_stack_t *s2, int *counter, int value, int timeout) { @@ -499,13 +500,13 @@ static void destroy_endpoint(endpoint_t *endpoint) { } static endpoint_t *create_udp_endpoint(int port, belle_sip_listener_callbacks_t *listener_callbacks) { - endpoint_t *endpoint = create_endpoint("0.0.0.0", port, "udp", listener_callbacks); + endpoint_t *endpoint = create_endpoint("127.0.0.1", port, "udp", listener_callbacks); BC_ASSERT_PTR_NOT_NULL(endpoint->lp); return endpoint; } static endpoint_t *create_tcp_endpoint(int port, belle_sip_listener_callbacks_t *listener_callbacks) { - endpoint_t *endpoint = create_endpoint("0.0.0.0", port, "tcp", listener_callbacks); + endpoint_t *endpoint = create_endpoint("127.0.0.1", port, "tcp", listener_callbacks); BC_ASSERT_PTR_NOT_NULL(endpoint->lp); return endpoint; } @@ -1469,6 +1470,148 @@ static void register_digest_auth_with_bad_next_nonce(void) { destroy_endpoint(server); } +typedef struct channel_bank_test_data { + belle_sip_server_transaction_t *server_transaction; + int request_count; +} channel_bank_test_data_t; + +static void channel_bank_test_server_process_request(void *user_data, const belle_sip_request_event_t *ev) { + endpoint_t *endpoint = (endpoint_t *)user_data; + belle_sip_response_t *resp; + belle_sip_server_transaction_t *tr; + channel_bank_test_data_t *test_data = (channel_bank_test_data_t *)endpoint->test_data; + test_data->request_count++; + tr = belle_sip_provider_create_server_transaction(endpoint->provider, belle_sip_request_event_get_request(ev)); + resp = belle_sip_response_create_from_request(belle_sip_request_event_get_request(ev), 200); + test_data->server_transaction = (belle_sip_server_transaction_t *)belle_sip_object_ref(tr); + belle_sip_server_transaction_send_response(tr, resp); +} + +static void channel_bank_test(void) { + belle_sip_listener_callbacks_t client_callbacks; + belle_sip_listener_callbacks_t server_callbacks; + endpoint_t *client, *server; + belle_sip_request_t *req; + belle_sip_client_transaction_t *client_transaction1, *client_transaction2; + belle_sip_server_transaction_t *server_transaction1, *server_transaction2; + channel_bank_test_data_t server_data = {0}; + channel_bank_test_data_t client_data = {0}; + belle_sip_uri_t *dest_uri; + int client_port1; + int client_port2; + + memset(&client_callbacks, 0, sizeof(belle_sip_listener_callbacks_t)); + memset(&server_callbacks, 0, sizeof(belle_sip_listener_callbacks_t)); + client_callbacks.process_response_event = NULL; + ; + client_callbacks.process_request_event = channel_bank_test_server_process_request; + client_callbacks.process_auth_requested = NULL; + ; + server_callbacks.process_request_event = channel_bank_test_server_process_request; + client = create_udp_endpoint(BELLE_SIP_LISTENING_POINT_DONT_BIND, &client_callbacks); + client->test_data = &client_data; + server = create_udp_endpoint(6788, &server_callbacks); + server->test_data = &server_data; + + /* send a first request */ + req = belle_sip_request_create( + belle_sip_uri_parse("sip:example.org"), "OPTIONS", belle_sip_provider_create_call_id(client->provider), + belle_sip_header_cseq_create(20, "OPTIONS"), + belle_sip_header_from_create2("sip:bob@example.org", BELLE_SIP_RANDOM_TAG), + belle_sip_header_to_create2("sip:alice@example.org", NULL), belle_sip_header_via_new(), 70); + belle_sip_message_set_channel_bank_identifier(BELLE_SIP_MESSAGE(req), "xxx"); + + client_transaction1 = belle_sip_provider_create_client_transaction(client->provider, req); + belle_sip_client_transaction_send_request_to(client_transaction1, server->lp->listening_uri); + belle_sip_object_ref(client_transaction1); + BC_ASSERT_TRUE(wait_for(client->stack, server->stack, &server_data.request_count, 1, 1000)); + server_transaction1 = server_data.server_transaction; + + /* send a second request with different channel bank identifier*/ + req = belle_sip_request_create( + belle_sip_uri_parse("sip:example.org"), "OPTIONS", belle_sip_provider_create_call_id(client->provider), + belle_sip_header_cseq_create(20, "OPTIONS"), + belle_sip_header_from_create2("sip:bob@example.org", BELLE_SIP_RANDOM_TAG), + belle_sip_header_to_create2("sip:alice@example.org", NULL), belle_sip_header_via_new(), 70); + belle_sip_message_set_channel_bank_identifier(BELLE_SIP_MESSAGE(req), "yyy"); + + client_transaction2 = belle_sip_provider_create_client_transaction(client->provider, req); + belle_sip_client_transaction_send_request_to(client_transaction2, server->lp->listening_uri); + belle_sip_object_ref(client_transaction2); + BC_ASSERT_TRUE(wait_for(client->stack, server->stack, &server_data.request_count, 2, 1000)); + server_transaction2 = server_data.server_transaction; + + /* Assert that all channels used so first and second transactions were different */ + BC_ASSERT_PTR_NOT_NULL(server_transaction1->base.channel); + BC_ASSERT_PTR_NOT_NULL(server_transaction2->base.channel); + BC_ASSERT_PTR_NOT_NULL(client_transaction1->base.channel); + BC_ASSERT_PTR_NOT_NULL(client_transaction2->base.channel); + + BC_ASSERT_TRUE(server_transaction1->base.channel != server_transaction2->base.channel); + BC_ASSERT_TRUE(client_transaction1->base.channel != client_transaction2->base.channel); + + client_port1 = client_transaction1->base.channel->local_port; + client_port2 = client_transaction2->base.channel->local_port; + + BC_ASSERT_TRUE(client_port1 != client_port2); + + belle_sip_object_unref(client_transaction1); + belle_sip_object_unref(client_transaction2); + belle_sip_object_unref(server_transaction1); + belle_sip_object_unref(server_transaction2); + + wait_for(client->stack, server->stack, NULL, 0, 1000); + + /* now the server sends a request back to the client, through the first channel */ + req = belle_sip_request_create( + belle_sip_uri_parse("sip:bob@example.org"), "OPTIONS", belle_sip_provider_create_call_id(client->provider), + belle_sip_header_cseq_create(20, "OPTIONS"), + belle_sip_header_from_create2("sip:alice@example.org", BELLE_SIP_RANDOM_TAG), + belle_sip_header_to_create2("sip:bob@example.org", NULL), belle_sip_header_via_new(), 70); + /* no channel bank identifier is given. */ + dest_uri = belle_sip_uri_parse("sip:127.0.0.1"); + belle_sip_uri_set_port(dest_uri, client_port1); + client_transaction1 = belle_sip_provider_create_client_transaction(server->provider, req); + belle_sip_client_transaction_send_request_to(client_transaction1, dest_uri); + belle_sip_object_ref(client_transaction1); + BC_ASSERT_TRUE(wait_for(client->stack, server->stack, &client_data.request_count, 1, 1000)); + server_transaction1 = client_data.server_transaction; + + /* server sends a request back to the client, through the second channel */ + req = belle_sip_request_create( + belle_sip_uri_parse("sip:bob@example.org"), "OPTIONS", belle_sip_provider_create_call_id(client->provider), + belle_sip_header_cseq_create(20, "OPTIONS"), + belle_sip_header_from_create2("sip:alice@example.org", BELLE_SIP_RANDOM_TAG), + belle_sip_header_to_create2("sip:bob@example.org", NULL), belle_sip_header_via_new(), 70); + /* no channel bank identifier is given. */ + dest_uri = belle_sip_uri_parse("sip:127.0.0.1"); + belle_sip_uri_set_port(dest_uri, client_port2); + client_transaction2 = belle_sip_provider_create_client_transaction(server->provider, req); + belle_sip_client_transaction_send_request_to(client_transaction2, dest_uri); + belle_sip_object_ref(client_transaction2); + BC_ASSERT_TRUE(wait_for(client->stack, server->stack, &client_data.request_count, 2, 1000)); + server_transaction2 = client_data.server_transaction; + + /* Assert that all channels used so first and second transactions were different */ + BC_ASSERT_PTR_NOT_NULL(server_transaction1->base.channel); + BC_ASSERT_PTR_NOT_NULL(server_transaction2->base.channel); + BC_ASSERT_PTR_NOT_NULL(client_transaction1->base.channel); + BC_ASSERT_PTR_NOT_NULL(client_transaction2->base.channel); + + BC_ASSERT_TRUE(server_transaction1->base.channel != server_transaction2->base.channel); + BC_ASSERT_TRUE(client_transaction1->base.channel != client_transaction2->base.channel); + + belle_sip_object_unref(client_transaction1); + belle_sip_object_unref(client_transaction2); + belle_sip_object_unref(server_transaction1); + belle_sip_object_unref(server_transaction2); + + belle_sip_message("Done."); + + destroy_endpoint(client); + destroy_endpoint(server); +} + static test_t refresher_tests[] = { TEST_NO_TAG("REGISTER Expires header", register_expires_header), TEST_NO_TAG("REGISTER Expires in Contact", register_expires_in_contact), @@ -1516,7 +1659,8 @@ static test_t refresher_tests[] = { register_with_pingpong_without_pingpong_verification), TEST_NO_TAG("REGISTER with RFC5626 ping pong not supported server-side", register_with_pingpong_not_supported), TEST_NO_TAG("REGISTER with RFC5626 ping pong erroneously supported server-side", - register_with_pingpong_not_supported_2)}; + register_with_pingpong_not_supported_2), + TEST_NO_TAG("Transactions using different channel banks", channel_bank_test)}; test_suite_t refresher_test_suite = {"Refresher", NULL,