void aeron_driver_receiver_on_add_endpoint(void *clientd, void *command) { aeron_driver_receiver_t *receiver = (aeron_driver_receiver_t *)clientd; aeron_command_base_t *cmd = (aeron_command_base_t *)command; aeron_receive_channel_endpoint_t *endpoint = (aeron_receive_channel_endpoint_t *)cmd->item; aeron_udp_channel_t *udp_channel = endpoint->conductor_fields.udp_channel; if (aeron_udp_transport_poller_add(&receiver->poller, &endpoint->transport) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_add_endpoint: %s", aeron_errmsg()); } if (udp_channel->explicit_control) { if (aeron_driver_receiver_add_pending_setup(receiver, endpoint, 0, 0, &udp_channel->local_control) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_add_endpoint: %s", aeron_errmsg()); } if (aeron_receive_channel_endpoint_send_sm( endpoint, &udp_channel->local_control, 0, 0, 0, 0, 0, AERON_STATUS_MESSAGE_HEADER_SEND_SETUP_FLAG) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_add_endpoint send SM: %s", aeron_errmsg()); } } aeron_driver_conductor_proxy_on_delete_cmd(receiver->context->conductor_proxy, command); }
DriverConfigurationTest() { if (aeron_driver_context_init(&m_context) < 0) { throw std::runtime_error("could not init context: " + std::string(aeron_errmsg())); } }
void aeron_driver_receiver_on_remove_endpoint(void *clientd, void *command) { aeron_driver_receiver_t *receiver = (aeron_driver_receiver_t *)clientd; aeron_command_base_t *cmd = (aeron_command_base_t *)command; aeron_receive_channel_endpoint_t *endpoint = (aeron_receive_channel_endpoint_t *)cmd->item; if (aeron_udp_transport_poller_remove(&receiver->poller, &endpoint->transport) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_remove_endpoint: %s", aeron_errmsg()); } for (int last_index = (int)receiver->pending_setups.length - 1, i = last_index; i >= 0; i--) { aeron_driver_receiver_pending_setup_entry_t *entry = &receiver->pending_setups.array[i]; if (entry->endpoint == endpoint) { aeron_array_fast_unordered_remove( (uint8_t *) receiver->pending_setups.array, sizeof(aeron_driver_receiver_pending_setup_entry_t), (size_t)i, (size_t)last_index); last_index--; receiver->pending_setups.length--; } } aeron_receive_channel_endpoint_receiver_release(endpoint); aeron_driver_conductor_proxy_on_delete_cmd(receiver->context->conductor_proxy, command); }
void aeron_driver_receiver_on_remove_cool_down(void *clientd, void *item) { aeron_driver_receiver_t *receiver = (aeron_driver_receiver_t *)clientd; aeron_command_remove_cool_down_t *cmd = (aeron_command_remove_cool_down_t *)item; aeron_receive_channel_endpoint_t *endpoint = (aeron_receive_channel_endpoint_t *)cmd->endpoint; if (aeron_receive_channel_endpoint_on_remove_cool_down(endpoint, cmd->session_id, cmd->stream_id) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_remove_cool_down: %s", aeron_errmsg()); } aeron_driver_conductor_proxy_on_delete_cmd(receiver->context->conductor_proxy, item); }
TEST_F(UdpChannelTest, shouldCanonicalizeIpv4ForUnicast) { ASSERT_EQ(parse_udp_channel("aeron:udp?endpoint=192.168.0.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-00000000-0-c0a80001-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.1|endpoint=192.168.0.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-0-c0a80001-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.1:40455|endpoint=192.168.0.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-40455-c0a80001-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=localhost|endpoint=localhost:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-0-7f000001-40456"); }
TEST_F(UdpChannelTest, shouldParseImpliedLocalAddressAndPortFormat) { ASSERT_EQ(parse_udp_channel("aeron:udp?endpoint=localhost:40124"), 0) << aeron_errmsg(); EXPECT_EQ(m_channel->local_data.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->local_data), "0.0.0.0"); EXPECT_EQ(port(&m_channel->local_data), 0); EXPECT_EQ(m_channel->local_control.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->local_control), "0.0.0.0"); EXPECT_EQ(port(&m_channel->local_control), 0); EXPECT_EQ(m_channel->remote_data.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->remote_data), "127.0.0.1"); EXPECT_EQ(port(&m_channel->remote_data), 40124); EXPECT_EQ(m_channel->remote_control.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->remote_control), "127.0.0.1"); EXPECT_EQ(port(&m_channel->remote_control), 40124); }
int aeron_driver_receiver_do_work(void *clientd) { struct mmsghdr mmsghdr[AERON_DRIVER_RECEIVER_NUM_RECV_BUFFERS]; aeron_driver_receiver_t *receiver = (aeron_driver_receiver_t *)clientd; int64_t bytes_received = 0; int work_count = 0; work_count += aeron_spsc_concurrent_array_queue_drain( receiver->receiver_proxy.command_queue, aeron_driver_receiver_on_command, receiver, 10); for (size_t i = 0; i < AERON_DRIVER_RECEIVER_NUM_RECV_BUFFERS; i++) { mmsghdr[i].msg_hdr.msg_name = &receiver->recv_buffers.addrs[i]; mmsghdr[i].msg_hdr.msg_namelen = sizeof(receiver->recv_buffers.addrs[i]); mmsghdr[i].msg_hdr.msg_iov = &receiver->recv_buffers.iov[i]; mmsghdr[i].msg_hdr.msg_iovlen = 1; mmsghdr[i].msg_hdr.msg_flags = 0; mmsghdr[i].msg_hdr.msg_control = NULL; mmsghdr[i].msg_hdr.msg_controllen = 0; mmsghdr[i].msg_len = 0; } int poll_result = aeron_udp_transport_poller_poll( &receiver->poller, mmsghdr, AERON_DRIVER_RECEIVER_NUM_RECV_BUFFERS, aeron_receive_channel_endpoint_dispatch, receiver); if (poll_result < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver poller_poll: %s", aeron_errmsg()); } for (int i = 0; i < poll_result; i++) { bytes_received += mmsghdr[i].msg_len; work_count++; } aeron_counter_add_ordered(receiver->total_bytes_received_counter, bytes_received); int64_t now_ns = receiver->context->nano_clock(); for (size_t i = 0, length = receiver->images.length; i < length; i++) { aeron_publication_image_t *image = receiver->images.array[i].image; int send_sm_result = aeron_publication_image_send_pending_status_message(image); if (send_sm_result < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver send SM: %s", aeron_errmsg()); } work_count += (send_sm_result < 0) ? 0 : send_sm_result; int send_nak_result = aeron_publication_image_send_pending_loss(image); if (send_nak_result < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver send NAK: %s", aeron_errmsg()); } work_count += (send_nak_result < 0) ? 0 : send_nak_result; int initiate_rttm_result = aeron_publication_image_initiate_rttm(image, now_ns); if (send_nak_result < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver send RTTM: %s", aeron_errmsg()); } work_count += (initiate_rttm_result < 0) ? 0 : initiate_rttm_result; } for (int last_index = (int)receiver->pending_setups.length - 1, i = last_index; i >= 0; i--) { aeron_driver_receiver_pending_setup_entry_t *entry = &receiver->pending_setups.array[i]; if (now_ns > (entry->time_of_status_message_ns + AERON_DRIVER_RECEIVER_PENDING_SETUP_TIMEOUT_NS)) { if (!entry->is_periodic) { if (aeron_receive_channel_endpoint_on_remove_pending_setup( entry->endpoint, entry->session_id, entry->stream_id) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver pending setups: %s", aeron_errmsg()); } aeron_array_fast_unordered_remove( (uint8_t *) receiver->pending_setups.array, sizeof(aeron_driver_receiver_pending_setup_entry_t), (size_t)i, (size_t)last_index); last_index--; receiver->pending_setups.length--; } else if (aeron_receive_channel_endpoint_should_elicit_setup_message(entry->endpoint)) { if (aeron_receive_channel_endpoint_send_sm( entry->endpoint, &entry->control_addr, entry->stream_id, entry->session_id, 0, 0, 0, AERON_STATUS_MESSAGE_HEADER_SEND_SETUP_FLAG) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver send periodic SM: %s", aeron_errmsg()); } entry->time_of_status_message_ns = now_ns; } } } return work_count; }
void aeron_driver_receiver_on_remove_publication_image(void *clientd, void *item) { aeron_driver_receiver_t *receiver = (aeron_driver_receiver_t *)clientd; aeron_command_publication_image_t *cmd = (aeron_command_publication_image_t *)item; aeron_receive_channel_endpoint_t *endpoint = (aeron_receive_channel_endpoint_t *)cmd->endpoint; if (NULL != endpoint && aeron_receive_channel_endpoint_on_remove_publication_image(endpoint, cmd->image) < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_remove_publication_image: %s", aeron_errmsg()); } for (size_t i = 0, size = receiver->images.length, last_index = size - 1; i < size; i++) { if (cmd->image == receiver->images.array[i].image) { aeron_array_fast_unordered_remove( (uint8_t *)receiver->images.array, sizeof(aeron_driver_receiver_image_entry_t), i, last_index); receiver->images.length--; break; } } aeron_driver_conductor_proxy_on_delete_cmd(receiver->context->conductor_proxy, item); }
void aeron_driver_receiver_on_add_publication_image(void *clientd, void *item) { aeron_driver_receiver_t *receiver = (aeron_driver_receiver_t *)clientd; aeron_command_publication_image_t *cmd = (aeron_command_publication_image_t *)item; aeron_receive_channel_endpoint_t *endpoint = (aeron_receive_channel_endpoint_t *)cmd->endpoint; int ensure_capacity_result = 0; AERON_ARRAY_ENSURE_CAPACITY(ensure_capacity_result, receiver->images, aeron_driver_receiver_image_entry_t); if (aeron_receive_channel_endpoint_on_add_publication_image(endpoint, cmd->image) < 0 || ensure_capacity_result < 0) { AERON_DRIVER_RECEIVER_ERROR(receiver, "receiver on_add_publication_image: %s", aeron_errmsg()); } receiver->images.array[receiver->images.length++].image = cmd->image; aeron_driver_conductor_proxy_on_delete_cmd(receiver->context->conductor_proxy, item); }
int aeron_publication_image_create( aeron_publication_image_t **image, aeron_receive_channel_endpoint_t *endpoint, aeron_driver_context_t *context, int64_t correlation_id, int32_t session_id, int32_t stream_id, int32_t initial_term_id, int32_t active_term_id, int32_t initial_term_offset, aeron_position_t *rcv_hwm_position, aeron_position_t *rcv_pos_position, aeron_congestion_control_strategy_t *congestion_control, struct sockaddr_storage *control_address, struct sockaddr_storage *source_address, int32_t term_buffer_length, int32_t sender_mtu_length, aeron_loss_reporter_t *loss_reporter, bool is_reliable, bool is_sparse, aeron_system_counters_t *system_counters) { char path[AERON_MAX_PATH]; int path_length = aeron_publication_image_location( path, sizeof(path), context->aeron_dir, endpoint->conductor_fields.udp_channel->canonical_form, session_id, stream_id, correlation_id); aeron_publication_image_t *_image = NULL; const uint64_t usable_fs_space = context->usable_fs_space_func(context->aeron_dir); const uint64_t log_length = aeron_logbuffer_compute_log_length((uint64_t)term_buffer_length, context->file_page_size); bool is_multicast = endpoint->conductor_fields.udp_channel->multicast; int64_t now_ns = context->nano_clock(); *image = NULL; if (usable_fs_space < log_length) { aeron_set_err( ENOSPC, "Insufficient usable storage for new log of length=%" PRId64 " in %s", log_length, context->aeron_dir); return -1; } if (aeron_alloc((void **)&_image, sizeof(aeron_publication_image_t)) < 0) { aeron_set_err(ENOMEM, "%s", "Could not allocate publication image"); return -1; } _image->log_file_name = NULL; if (aeron_alloc((void **)(&_image->log_file_name), (size_t)path_length + 1) < 0) { aeron_free(_image); aeron_set_err(ENOMEM, "%s", "Could not allocate publication image log_file_name"); return -1; } if (aeron_loss_detector_init( &_image->loss_detector, is_multicast, is_multicast ? aeron_loss_detector_nak_multicast_delay_generator : aeron_loss_detector_nak_unicast_delay_generator, aeron_publication_image_on_gap_detected, _image) < 0) { aeron_free(_image); aeron_set_err(ENOMEM, "%s", "Could not init publication image loss detector"); return -1; } if (context->map_raw_log_func( &_image->mapped_raw_log, path, is_sparse, (uint64_t)term_buffer_length, context->file_page_size) < 0) { aeron_free(_image->log_file_name); aeron_free(_image); aeron_set_err(aeron_errcode(), "error mapping network raw log %s: %s", path, aeron_errmsg()); return -1; } _image->map_raw_log_close_func = context->map_raw_log_close_func; strncpy(_image->log_file_name, path, (size_t)path_length); _image->log_file_name[path_length] = '\0'; _image->log_file_name_length = (size_t)path_length; _image->log_meta_data = (aeron_logbuffer_metadata_t *)(_image->mapped_raw_log.log_meta_data.addr); _image->log_meta_data->initial_term_id = initial_term_id; _image->log_meta_data->mtu_length = sender_mtu_length; _image->log_meta_data->term_length = term_buffer_length; _image->log_meta_data->page_size = (int32_t)context->file_page_size; _image->log_meta_data->correlation_id = correlation_id; _image->log_meta_data->is_connected = 0; _image->log_meta_data->end_of_stream_position = INT64_MAX; aeron_logbuffer_fill_default_header( _image->mapped_raw_log.log_meta_data.addr, session_id, stream_id, initial_term_id); _image->endpoint = endpoint; _image->congestion_control = congestion_control; _image->loss_reporter = loss_reporter; _image->loss_reporter_offset = -1; _image->nano_clock = context->nano_clock; _image->epoch_clock = context->epoch_clock; _image->conductor_fields.subscribable.array = NULL; _image->conductor_fields.subscribable.length = 0; _image->conductor_fields.subscribable.capacity = 0; _image->conductor_fields.subscribable.add_position_hook_func = aeron_driver_subscribable_null_hook; _image->conductor_fields.subscribable.remove_position_hook_func = aeron_driver_subscribable_null_hook; _image->conductor_fields.subscribable.clientd = NULL; _image->conductor_fields.managed_resource.registration_id = correlation_id; _image->conductor_fields.managed_resource.clientd = _image; _image->conductor_fields.managed_resource.incref = NULL; _image->conductor_fields.managed_resource.decref = NULL; _image->conductor_fields.is_reliable = is_reliable; _image->conductor_fields.status = AERON_PUBLICATION_IMAGE_STATUS_ACTIVE; _image->conductor_fields.liveness_timeout_ns = context->image_liveness_timeout_ns; _image->session_id = session_id; _image->stream_id = stream_id; _image->rcv_hwm_position.counter_id = rcv_hwm_position->counter_id; _image->rcv_hwm_position.value_addr = rcv_hwm_position->value_addr; _image->rcv_pos_position.counter_id = rcv_pos_position->counter_id; _image->rcv_pos_position.value_addr = rcv_pos_position->value_addr; _image->initial_term_id = initial_term_id; _image->term_length_mask = (int32_t)term_buffer_length - 1; _image->position_bits_to_shift = (size_t)aeron_number_of_trailing_zeroes((int32_t)term_buffer_length); _image->mtu_length = sender_mtu_length; _image->last_sm_change_number = -1; _image->last_loss_change_number = -1; _image->is_end_of_stream = false; memcpy(&_image->control_address, control_address, sizeof(_image->control_address)); memcpy(&_image->source_address, source_address, sizeof(_image->source_address)); _image->heartbeats_received_counter = aeron_system_counter_addr( system_counters, AERON_SYSTEM_COUNTER_HEARTBEATS_RECEIVED); _image->flow_control_under_runs_counter = aeron_system_counter_addr( system_counters, AERON_SYSTEM_COUNTER_FLOW_CONTROL_UNDER_RUNS); _image->flow_control_over_runs_counter = aeron_system_counter_addr( system_counters, AERON_SYSTEM_COUNTER_FLOW_CONTROL_OVER_RUNS); _image->status_messages_sent_counter = aeron_system_counter_addr( system_counters, AERON_SYSTEM_COUNTER_STATUS_MESSAGES_SENT); _image->nak_messages_sent_counter = aeron_system_counter_addr( system_counters, AERON_SYSTEM_COUNTER_NAK_MESSAGES_SENT); _image->loss_gap_fills_counter = aeron_system_counter_addr( system_counters, AERON_SYSTEM_COUNTER_LOSS_GAP_FILLS); const int64_t initial_position = aeron_logbuffer_compute_position( active_term_id, initial_term_offset, _image->position_bits_to_shift, initial_term_id); _image->begin_loss_change = -1; _image->end_loss_change = -1; _image->loss_term_id = active_term_id; _image->loss_term_offset = initial_term_offset; _image->loss_length = 0; _image->begin_sm_change = -1; _image->end_sm_change = -1; _image->next_sm_position = initial_position; _image->next_sm_receiver_window_length = _image->congestion_control->initial_window_length( _image->congestion_control->state); _image->last_sm_position = initial_position; _image->last_sm_position_window_limit = initial_position + _image->next_sm_receiver_window_length; _image->last_packet_timestamp_ns = now_ns; _image->last_status_message_timestamp = 0; _image->conductor_fields.clean_position = initial_position; _image->conductor_fields.time_of_last_status_change_ns = now_ns; aeron_counter_set_ordered(_image->rcv_hwm_position.value_addr, initial_position); aeron_counter_set_ordered(_image->rcv_pos_position.value_addr, initial_position); *image = _image; return 0; }
TEST_F(UdpChannelTest, shouldCanonicalizeForIpv6Multicast) { ASSERT_EQ(parse_udp_channel("aeron:udp?interface=[::1]|endpoint=[FF01::FD]:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-00000000000000000000000000000001-0-ff0100000000000000000000000000fd-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=[::1]:54321/64|endpoint=[FF01::FD]:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-00000000000000000000000000000001-54321-ff0100000000000000000000000000fd-40456"); }
TEST_F(UdpChannelTest, shouldCanonicalizeForIpv4Multicast) { ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.1:40455|endpoint=224.0.1.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-40455-e0000101-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.0:40455/24|endpoint=224.0.1.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-40455-e0000101-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=localhost|endpoint=224.0.1.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-0-e0000101-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.1|endpoint=224.0.1.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-0-e0000101-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=localhost/24|endpoint=224.0.1.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-0-e0000101-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.0/24|endpoint=224.0.1.1:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-0-e0000101-40456"); }
TEST_F(UdpChannelTest, shouldCanonicalizeIpv6ForUnicastWithMixedAddressTypes) { ASSERT_EQ(parse_udp_channel("aeron:udp?endpoint=192.168.0.1:40456|interface=[::1]"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-00000000000000000000000000000001-0-c0a80001-40456"); ASSERT_EQ(parse_udp_channel("aeron:udp?interface=127.0.0.1:40455|endpoint=[fe80::5246:5dff:fe73:df06]:40456"), 0) << aeron_errmsg(); EXPECT_STREQ(m_channel->canonical_form, "UDP-7f000001-40455-fe8000000000000052465dfffe73df06-40456"); }
TEST_F(UdpChannelTest, shouldParseIpv6AnyAddressAsInterfaceAddressForUnicast) { ASSERT_EQ(parse_udp_channel("aeron:udp?interface=[::]|endpoint=[::1]:40124"), 0) << aeron_errmsg(); EXPECT_EQ(m_channel->local_data.ss_family, AF_INET6); EXPECT_STREQ(inet_ntop(&m_channel->local_data), "::"); EXPECT_EQ(port(&m_channel->local_data), 0); EXPECT_EQ(m_channel->local_control.ss_family, AF_INET6); EXPECT_STREQ(inet_ntop(&m_channel->local_control), "::"); EXPECT_EQ(port(&m_channel->local_control), 0); EXPECT_EQ(m_channel->remote_data.ss_family, AF_INET6); EXPECT_STREQ(inet_ntop(&m_channel->remote_data), "::1"); EXPECT_EQ(port(&m_channel->remote_data), 40124); EXPECT_EQ(m_channel->remote_control.ss_family, AF_INET6); EXPECT_STREQ(inet_ntop(&m_channel->remote_control), "::1"); EXPECT_EQ(port(&m_channel->remote_control), 40124); }
TEST_F(UdpChannelTest, shouldParseValidMulticastAddress) { ASSERT_EQ(parse_udp_channel("aeron:udp?interface=localhost|endpoint=224.10.9.9:40124"), 0) << aeron_errmsg(); EXPECT_EQ(m_channel->local_data.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->local_data), "127.0.0.1"); EXPECT_EQ(port(&m_channel->local_data), 0); EXPECT_EQ(m_channel->local_control.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->local_control), "127.0.0.1"); EXPECT_EQ(port(&m_channel->local_control), 0); EXPECT_EQ(m_channel->remote_data.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->remote_data), "224.10.9.9"); EXPECT_EQ(port(&m_channel->remote_data), 40124); EXPECT_EQ(m_channel->remote_control.ss_family, AF_INET); EXPECT_STREQ(inet_ntop(&m_channel->remote_control), "224.10.9.10"); EXPECT_EQ(port(&m_channel->remote_control), 40124); }
int aeron_udp_channel_parse(const char *uri, size_t uri_length, aeron_udp_channel_t **channel) { aeron_udp_channel_t *_channel = NULL; struct sockaddr_storage endpoint_addr, explicit_control_addr, interface_addr; unsigned int interface_index = 0; memset(&endpoint_addr, 0, sizeof(endpoint_addr)); memset(&explicit_control_addr, 0, sizeof(explicit_control_addr)); memset(&interface_addr, 0, sizeof(interface_addr)); if (aeron_alloc((void **)&_channel, sizeof(aeron_udp_channel_t)) < 0) { aeron_set_err(ENOMEM, "%s", "could not allocate UDP channel"); return -1; } if (aeron_uri_parse(uri, &_channel->uri) < 0) { goto error_cleanup; } size_t copy_length = sizeof(_channel->original_uri) - 1; copy_length = uri_length < copy_length ? uri_length : copy_length; strncpy(_channel->original_uri, uri, copy_length); _channel->original_uri[copy_length] = '\0'; _channel->uri_length = copy_length; _channel->explicit_control = false; _channel->multicast = false; if (_channel->uri.type != AERON_URI_UDP) { aeron_set_err(EINVAL, "%s", "UDP channels must use UDP URIs"); goto error_cleanup; } if (NULL == _channel->uri.params.udp.endpoint_key && NULL == _channel->uri.params.udp.control_key) { aeron_set_err(EINVAL, "%s", "Aeron URIs for UDP must specify an endpoint address and/or a control address"); goto error_cleanup; } if (NULL != _channel->uri.params.udp.endpoint_key) { if (aeron_host_and_port_parse_and_resolve(_channel->uri.params.udp.endpoint_key, &endpoint_addr) < 0) { aeron_set_err( aeron_errcode(), "could not resolve endpoint address=(%s): %s", _channel->uri.params.udp.endpoint_key, aeron_errmsg()); goto error_cleanup; } } else { aeron_set_ipv4_wildcard_host_and_port(&endpoint_addr); } if (NULL != _channel->uri.params.udp.control_key) { if (aeron_host_and_port_parse_and_resolve(_channel->uri.params.udp.control_key, &explicit_control_addr) < 0) { aeron_set_err( aeron_errcode(), "could not resolve control address=(%s): %s", _channel->uri.params.udp.control_key, aeron_errmsg()); goto error_cleanup; } } if (aeron_is_addr_multicast(&endpoint_addr)) { memcpy(&_channel->remote_data, &endpoint_addr, AERON_ADDR_LEN(&endpoint_addr)); if (aeron_multicast_control_address(&endpoint_addr, &_channel->remote_control) < 0) { goto error_cleanup; } if (aeron_find_multicast_interface( endpoint_addr.ss_family, _channel->uri.params.udp.interface_key, &interface_addr, &interface_index) < 0) { aeron_set_err( aeron_errcode(), "could not find interface=(%s): %s", _channel->uri.params.udp.interface_key, aeron_errmsg()); goto error_cleanup; } _channel->interface_index = interface_index; _channel->multicast_ttl = aeron_uri_multicast_ttl(&_channel->uri); memcpy(&_channel->local_data, &interface_addr, AERON_ADDR_LEN(&interface_addr)); memcpy(&_channel->local_control, &interface_addr, AERON_ADDR_LEN(&interface_addr)); aeron_uri_udp_canonicalise( _channel->canonical_form, sizeof(_channel->canonical_form), &interface_addr, &endpoint_addr); _channel->canonical_length = strlen(_channel->canonical_form); _channel->multicast = true; } else if (NULL != _channel->uri.params.udp.control_key) { _channel->interface_index = 0; _channel->multicast_ttl = 0; memcpy(&_channel->remote_data, &endpoint_addr, AERON_ADDR_LEN(&endpoint_addr)); memcpy(&_channel->remote_control, &endpoint_addr, AERON_ADDR_LEN(&endpoint_addr)); memcpy(&_channel->local_data, &explicit_control_addr, AERON_ADDR_LEN(&explicit_control_addr)); memcpy(&_channel->local_control, &explicit_control_addr, AERON_ADDR_LEN(&explicit_control_addr)); aeron_uri_udp_canonicalise( _channel->canonical_form, sizeof(_channel->canonical_form), &explicit_control_addr, &endpoint_addr); _channel->canonical_length = strlen(_channel->canonical_form); _channel->explicit_control = true; } else { if (aeron_find_unicast_interface( endpoint_addr.ss_family, _channel->uri.params.udp.interface_key, &interface_addr, &interface_index) < 0) { goto error_cleanup; } _channel->interface_index = interface_index; _channel->multicast_ttl = 0; memcpy(&_channel->remote_data, &endpoint_addr, AERON_ADDR_LEN(&endpoint_addr)); memcpy(&_channel->remote_control, &endpoint_addr, AERON_ADDR_LEN(&endpoint_addr)); memcpy(&_channel->local_data, &interface_addr, AERON_ADDR_LEN(&interface_addr)); memcpy(&_channel->local_control, &interface_addr, AERON_ADDR_LEN(&interface_addr)); aeron_uri_udp_canonicalise( _channel->canonical_form, sizeof(_channel->canonical_form), &interface_addr, &endpoint_addr); _channel->canonical_length = strlen(_channel->canonical_form); } *channel = _channel; return 0; error_cleanup: *channel = NULL; if (NULL != _channel) { aeron_udp_channel_delete(_channel); } return -1; }