Esempio n. 1
0
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()));
     }
 }
Esempio n. 3
0
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);
}
Esempio n. 4
0
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);
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
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);
}
Esempio n. 16
0
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;
}