Ejemplo n.º 1
0
int aeron_driver_receiver_add_pending_setup(
    aeron_driver_receiver_t *receiver,
    aeron_receive_channel_endpoint_t *endpoint,
    int32_t session_id,
    int32_t stream_id,
    struct sockaddr_storage *control_addr)
{
    int ensure_capacity_result = 0;
    AERON_ARRAY_ENSURE_CAPACITY(
        ensure_capacity_result, receiver->pending_setups, aeron_driver_receiver_pending_setup_entry_t);

    if (ensure_capacity_result < 0)
    {
        int errcode = errno;

        aeron_set_err(errcode, "receiver add_pending_setup: %s", strerror(errcode));
        return ensure_capacity_result;
    }

    aeron_driver_receiver_pending_setup_entry_t *entry =
        &receiver->pending_setups.array[receiver->pending_setups.length++];

    entry->endpoint = endpoint;
    entry->session_id = session_id;
    entry->stream_id = stream_id;
    entry->time_of_status_message_ns = receiver->context->nano_clock();
    entry->is_periodic = false;
    if (NULL != control_addr)
    {
        memcpy(&entry->control_addr, control_addr, sizeof(entry->control_addr));
        entry->is_periodic = true;
    }

    return ensure_capacity_result;
}
Ejemplo n.º 2
0
int aeron_distinct_error_log_init(
    aeron_distinct_error_log_t *log,
    uint8_t *buffer,
    size_t buffer_size,
    aeron_clock_func_t clock,
    aeron_resource_linger_func_t linger,
    void *clientd)
{
    if (NULL == log || NULL == clock || NULL == linger)
    {
        aeron_set_err(EINVAL, "%s", "invalid argument");
        return -1;
    }

    if (aeron_alloc((void **)&log->observations_pimpl, sizeof(aeron_distinct_error_log_observations_pimpl_t)) < 0)
    {
        return -1;
    }

    log->buffer = buffer;
    log->buffer_capacity = buffer_size;
    log->clock = clock;
    log->linger_resource = linger;
    log->linger_resource_clientd = clientd;
    log->next_offset = 0;
    atomic_store(&log->observations_pimpl->num_observations, 0);
    atomic_store(&log->observations_pimpl->observations, NULL);
    pthread_mutex_init(&log->mutex, NULL);

    return 0;
}
Ejemplo n.º 3
0
int aeron_counters_manager_init(
    volatile aeron_counters_manager_t *manager,
    uint8_t *metadata_buffer,
    size_t metadata_length,
    uint8_t *values_buffer,
    size_t values_length,
    aeron_counters_manager_clock_func_t clock_func,
    int64_t free_to_reuse_timeout_ms)
{
    int result = -1;

    if (AERON_COUNTERS_MANAGER_IS_VALID_BUFFER_SIZES(metadata_length, values_length))
    {
        manager->metadata = metadata_buffer;
        manager->metadata_length = metadata_length;
        manager->values = values_buffer;
        manager->values_length = values_length;
        manager->id_high_water_mark = -1;
        manager->free_list_index = -1;
        manager->free_list_length = 2;
        manager->clock_func = clock_func;
        manager->free_to_reuse_timeout_ms = free_to_reuse_timeout_ms;
        result = aeron_alloc((void **)&manager->free_list, sizeof(int32_t) * manager->free_list_length);
    }
    else
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
    }

    return result;
}
Ejemplo n.º 4
0
int aeron_udp_transport_poller_add(aeron_udp_transport_poller_t *poller, aeron_udp_channel_transport_t *transport)
{
    int ensure_capacity_result = 0;
    size_t old_capacity = poller->transports.capacity, index = poller->transports.length;

    AERON_ARRAY_ENSURE_CAPACITY(ensure_capacity_result, poller->transports, aeron_udp_channel_transport_entry_t);
    if (ensure_capacity_result < 0)
    {
        return -1;
    }

    poller->transports.array[index].transport = transport;

#if defined(HAVE_EPOLL)
    size_t new_capacity = poller->transports.capacity;

    if (new_capacity > old_capacity)
    {
        if (aeron_array_ensure_capacity((uint8_t **)&poller->epoll_events, sizeof(struct epoll_event), old_capacity, new_capacity) < 0)
        {
            return -1;
        }
    }

    struct epoll_event event;

    event.data.fd = transport->fd;
    event.data.ptr = transport;
    event.events = EPOLLIN;
    int result = epoll_ctl(poller->epoll_fd, EPOLL_CTL_ADD, transport->fd, &event);
    if (result < 0)
    {
        aeron_set_err(errno, "epoll_ctl(EPOLL_CTL_ADD): %s", strerror(errno));
        return -1;
    }

#elif defined(HAVE_POLL)
    size_t new_capacity = poller->transports.capacity;

    if (new_capacity > old_capacity)
    {
        if (aeron_array_ensure_capacity((uint8_t **)&poller->pollfds, sizeof(struct pollfd), old_capacity, new_capacity) < 0)
        {
            return -1;
        }
    }

    poller->pollfds[index].fd = transport->fd;
    poller->pollfds[index].events = POLLIN;
    poller->pollfds[index].revents = 0;
#endif

    poller->transports.length++;

    return 0;
}
Ejemplo n.º 5
0
int aeron_driver_receiver_init(
    aeron_driver_receiver_t *receiver,
    aeron_driver_context_t *context,
    aeron_system_counters_t *system_counters,
    aeron_distinct_error_log_t *error_log)
{
    if (aeron_udp_transport_poller_init(&receiver->poller) < 0)
    {
        return -1;
    }

    for (size_t i = 0; i < AERON_DRIVER_RECEIVER_NUM_RECV_BUFFERS; i++)
    {
        size_t offset = 0;
        if (aeron_alloc_aligned(
            (void **)&receiver->recv_buffers.buffers[i],
            &offset,
            AERON_DRIVER_RECEIVER_MAX_UDP_PACKET_LENGTH,
            AERON_CACHE_LINE_LENGTH * 2) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "%s:%d: %s", __FILE__, __LINE__, strerror(errcode));
            return -1;
        }

        receiver->recv_buffers.iov[i].iov_base = receiver->recv_buffers.buffers[i] + offset;
        receiver->recv_buffers.iov[i].iov_len = AERON_DRIVER_RECEIVER_MAX_UDP_PACKET_LENGTH;
    }

    receiver->images.array = NULL;
    receiver->images.length = 0;
    receiver->images.capacity = 0;

    receiver->pending_setups.array = NULL;
    receiver->pending_setups.length = 0;
    receiver->pending_setups.capacity = 0;

    receiver->context = context;
    receiver->error_log = error_log;

    receiver->receiver_proxy.command_queue = &context->receiver_command_queue;
    receiver->receiver_proxy.fail_counter = aeron_system_counter_addr(
        system_counters, AERON_SYSTEM_COUNTER_RECEIVER_PROXY_FAILS);
    receiver->receiver_proxy.threading_mode = context->threading_mode;
    receiver->receiver_proxy.receiver = receiver;

    receiver->errors_counter = aeron_system_counter_addr(system_counters, AERON_SYSTEM_COUNTER_ERRORS);
    receiver->invalid_frames_counter = aeron_system_counter_addr(system_counters, AERON_SYSTEM_COUNTER_INVALID_PACKETS);
    receiver->total_bytes_received_counter =  aeron_system_counter_addr(
        system_counters, AERON_SYSTEM_COUNTER_BYTES_RECEIVED);

    return 0;
}
Ejemplo n.º 6
0
int aeron_udp_transport_poller_remove(aeron_udp_transport_poller_t *poller, aeron_udp_channel_transport_t *transport)
{
    int index = -1, last_index = (int)poller->transports.length - 1;

    for (int i = last_index; i >= 0; i--)
    {
        if (poller->transports.array[i].transport == transport)
        {
            index = i;
            break;
        }
    }

    if (index >= 0)
    {
        aeron_array_fast_unordered_remove(
            (uint8_t *)poller->transports.array,
            sizeof(aeron_udp_channel_transport_entry_t),
            (size_t)index,
            (size_t)last_index);

#if defined(HAVE_EPOLL)
        aeron_array_fast_unordered_remove(
            (uint8_t *)poller->epoll_events,
            sizeof(struct epoll_event),
            (size_t)index,
            (size_t)last_index);

        struct epoll_event event;

        event.data.fd = transport->fd;
        event.data.ptr = transport;
        event.events = EPOLLIN;
        int result = epoll_ctl(poller->epoll_fd, EPOLL_CTL_DEL, transport->fd, &event);
        if (result < 0)
        {
            aeron_set_err(errno, "epoll_ctl(EPOLL_CTL_DEL): %s", strerror(errno));
            return -1;
        }

#elif defined(HAVE_POLL)
        aeron_array_fast_unordered_remove(
            (uint8_t *)poller->pollfds,
            sizeof(struct pollfd),
            (size_t)index,
            (size_t)last_index);
#endif
        poller->transports.length--;
    }

    return 0;
}
Ejemplo n.º 7
0
int aeron_udp_channel_transport_sendmsg(
    aeron_udp_channel_transport_t *transport,
    struct msghdr *message)
{
    ssize_t sendmsg_result = sendmsg(transport->fd, message, 0);
    if (sendmsg_result < 0)
    {
        aeron_set_err(errno, "sendmsg: %s", strerror(errno));
        return -1;
    }

    return (int)sendmsg_result;
}
Ejemplo n.º 8
0
int32_t aeron_counters_manager_allocate(
    volatile aeron_counters_manager_t *manager,
    int32_t type_id,
    const uint8_t *key,
    size_t key_length,
    const char *label,
    size_t label_length)
{
    const int32_t counter_id = aeron_counters_manager_next_counter_id(manager);

    if ((counter_id * AERON_COUNTERS_MANAGER_VALUE_LENGTH) + AERON_COUNTERS_MANAGER_VALUE_LENGTH > manager->values_length)
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
        return -1;
    }

    if ((counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH) + AERON_COUNTERS_MANAGER_METADATA_LENGTH > manager->metadata_length)
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
        return -1;
    }

    aeron_counter_metadata_descriptor_t *metadata =
        (aeron_counter_metadata_descriptor_t *)(manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    metadata->type_id = type_id;
    metadata->free_to_reuse_deadline = AERON_COUNTER_NOT_FREE_TO_REUSE;

    if (NULL != key && key_length > 0)
    {
        memcpy(metadata->key, key, fmin(sizeof(metadata->key), key_length));
    }

    memcpy(metadata->label, label, fmin(sizeof(metadata->label), label_length));
    metadata->label_length = (int32_t)label_length;
    AERON_PUT_ORDERED(metadata->state, AERON_COUNTER_RECORD_ALLOCATED);

    return counter_id;
}
Ejemplo n.º 9
0
aeron_congestion_control_strategy_supplier_func_t aeron_congestion_control_strategy_supplier_load(
    const char *strategy_name)
{
    aeron_congestion_control_strategy_supplier_func_t func = NULL;

    if ((func = (aeron_congestion_control_strategy_supplier_func_t)dlsym(RTLD_DEFAULT, strategy_name)) == NULL)
    {
        aeron_set_err(EINVAL, "could not find congestion control strategy %s: dlsym - %s", strategy_name, dlerror());
        return NULL;
    }

    return func;
}
Ejemplo n.º 10
0
int aeron_udp_channel_transport_get_so_rcvbuf(aeron_udp_channel_transport_t *transport, size_t *so_rcvbuf)
{
    socklen_t len = sizeof(size_t);

    if (getsockopt(transport->fd, SOL_SOCKET, SO_RCVBUF, so_rcvbuf, &len) < 0)
    {
        int errcode = errno;

        aeron_set_err(errcode, "getsockopt(SO_RCVBUF) %s:%d: %s", __FILE__, __LINE__, strerror(errcode));
        return -1;
    }

    return 0;
}
Ejemplo n.º 11
0
aeron_flow_control_strategy_supplier_func_t aeron_flow_control_strategy_supplier_load(const char *strategy_name)
{
    aeron_flow_control_strategy_supplier_func_t func = NULL;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
    if ((func = (aeron_flow_control_strategy_supplier_func_t)aeron_dlsym(RTLD_DEFAULT, strategy_name)) == NULL)
    {
        aeron_set_err(EINVAL, "could not find flow control strategy %s: dlsym - %s", strategy_name, aeron_dlerror());
        return NULL;
    }
#pragma GCC diagnostic pop

    return func;
}
Ejemplo n.º 12
0
int aeron_multicast_control_address(struct sockaddr_storage *data_addr, struct sockaddr_storage *control_addr)
{
    if (AF_INET6 == data_addr->ss_family)
    {
        return aeron_ipv6_multicast_control_address(
            (struct sockaddr_in6 *)data_addr, (struct sockaddr_in6 *)control_addr);
    }
    else if (AF_INET == data_addr->ss_family)
    {
        return aeron_ipv4_multicast_control_address(
            (struct sockaddr_in *)data_addr, (struct sockaddr_in *)control_addr);
    }

    aeron_set_err(EINVAL, "unknown address family: %d", data_addr->ss_family);
    return -1;
}
Ejemplo n.º 13
0
int aeron_distinct_error_log_record(
    aeron_distinct_error_log_t *log, int error_code, const char *description, const char *message)
{
    int64_t timestamp = 0;
    aeron_distinct_observation_t *observation = NULL;

    if (NULL == log)
    {
        aeron_set_err(EINVAL, "%s", "invalid argument");
        return -1;
    }

    timestamp = log->clock();
    size_t num_observations = atomic_load(&log->observations_pimpl->num_observations);
    aeron_distinct_observation_t *observations = atomic_load(&log->observations_pimpl->observations);
    if ((observation = aeron_distinct_error_log_find_observation(
        observations, num_observations, error_code, description)) == NULL)
    {
        pthread_mutex_lock(&log->mutex);

        observation = aeron_distinct_error_log_new_observation(
            log, num_observations, timestamp, error_code, description, message);

        pthread_mutex_unlock(&log->mutex);

        if (NULL == observation)
        {
            char buffer[AERON_MAX_PATH];

            aeron_format_date(buffer, sizeof(buffer), timestamp);
            fprintf(stderr, "%s - unrecordable error %d: %s %s\n", buffer, error_code, description, message);
            errno = ENOMEM;
            return -1;
        }
    }

    aeron_error_log_entry_t *entry = (aeron_error_log_entry_t *)(log->buffer + observation->offset);

    int32_t dest;

    AERON_GET_AND_ADD_INT32(dest, entry->observation_count, 1);
    AERON_PUT_ORDERED(entry->last_observation_timestamp, timestamp);

    return 0;
}
Ejemplo n.º 14
0
int aeron_uri_linger_timeout_param(aeron_uri_params_t *uri_params, aeron_uri_publication_params_t *params)
{
    const char *value_str;

    if ((value_str = aeron_uri_find_param_value(uri_params, AERON_URI_LINGER_TIMEOUT_KEY)) != NULL)
    {
        uint64_t value;

        if (-1 == aeron_parse_duration_ns(value_str, &value))
        {
            aeron_set_err(EINVAL, "could not parse %s in URI", AERON_URI_LINGER_TIMEOUT_KEY);
            return -1;
        }

        params->linger_timeout_ns = value;
    }

    return 0;
}
Ejemplo n.º 15
0
int aeron_uri_parse(size_t uri_length, const char *uri, aeron_uri_t *params)
{
    size_t copy_length = sizeof(params->mutable_uri) - 1;
    copy_length = uri_length < copy_length ? uri_length : copy_length;

    memcpy(params->mutable_uri, uri, copy_length);
    params->mutable_uri[copy_length] = '\0';

    char *ptr = params->mutable_uri;
    params->type = AERON_URI_UNKNOWN;

    if (strncmp(ptr, AERON_URI_SCHEME, strlen(AERON_URI_SCHEME)) == 0)
    {
        ptr += strlen(AERON_URI_SCHEME);

        if (strncmp(ptr, AERON_URI_UDP_TRANSPORT, strlen(AERON_URI_UDP_TRANSPORT)) == 0)
        {
            ptr += strlen(AERON_URI_UDP_TRANSPORT);

            if (*ptr++ == '?')
            {
                params->type = AERON_URI_UDP;
                return aeron_udp_uri_parse(ptr, &params->params.udp);
            }
        }
        else if (strncmp(ptr, AERON_URI_IPC_TRANSPORT, strlen(AERON_URI_IPC_TRANSPORT)) == 0)
        {
            ptr += strlen(AERON_URI_IPC_TRANSPORT);

            if (*ptr == '?')
            {
                ptr++;
            }

            params->type = AERON_URI_IPC;
            return aeron_ipc_uri_parse(ptr, &params->params.ipc);
        }
    }

    aeron_set_err(EINVAL, "invalid URI scheme or transport: %s", uri);

    return -1;
}
Ejemplo n.º 16
0
int aeron_udp_transport_poller_init(aeron_udp_transport_poller_t *poller)
{
    poller->transports.array = NULL;
    poller->transports.length = 0;
    poller->transports.capacity = 0;

#if defined(HAVE_EPOLL)
    if ((poller->epoll_fd = epoll_create1(0)) < 0)
    {
        aeron_set_err(errno, "epoll_create1: %s", strerror(errno));
        return -1;
    }
    poller->epoll_events = NULL;
#elif defined(HAVE_POLL)
    poller->pollfds = NULL;
#endif

    return 0;
}
Ejemplo n.º 17
0
int aeron_ipv6_multicast_control_address(struct sockaddr_in6 *data_addr, struct sockaddr_in6 *control_addr)
{
    uint8_t bytes[sizeof(struct in6_addr)];
    size_t addr_len = sizeof(struct in6_addr);
    size_t last_byte_index = addr_len - 1;

    memcpy(bytes, &(data_addr->sin6_addr), addr_len);

    if ((bytes[last_byte_index] & 0x1) == 0)
    {
        aeron_set_err(EINVAL, "%s", "Multicast data address must be odd");
        return -1;
    }

    bytes[last_byte_index]++;
    control_addr->sin6_family = data_addr->sin6_family;
    memcpy(&(control_addr->sin6_addr), bytes, addr_len);
    control_addr->sin6_port = data_addr->sin6_port;

    return 0;
}
Ejemplo n.º 18
0
int aeron_parse_get_line(char *str, size_t max_length, const char *buffer)
{
    size_t i;

    for (i = 0; i < max_length - 1; i++)
    {
        str[i] = buffer[i];
        if ('\0' == buffer[i])
        {
            return 0;
        }

        if ('\n' == buffer[i])
        {
            str[i + 1] = '\0';
            return i + 1;
        }
    }

    aeron_set_err(EINVAL, "line too long: %" PRIu64 "/%" PRIu64, (uint64_t)i, (uint64_t)max_length);
    return -1;
}
Ejemplo n.º 19
0
int aeron_uri_get_mtu_length_param(aeron_uri_params_t *uri_params, aeron_uri_publication_params_t *params)
{
    const char *value_str;

    if ((value_str = aeron_uri_find_param_value(uri_params, AERON_URI_MTU_LENGTH_KEY)) != NULL)
    {
        uint64_t value;

        if (-1 == aeron_parse_size64(value_str, &value))
        {
            aeron_set_err(EINVAL, "could not parse %s in URI", AERON_URI_MTU_LENGTH_KEY);
            return -1;
        }

        if (aeron_driver_context_validate_mtu_length(value) < 0)
        {
            return -1;
        }

        params->mtu_length = value;
    }

    return 0;
}
Ejemplo n.º 20
0
aeron_driver_termination_validator_func_t aeron_driver_termination_validator_load(const char *validator_name)
{
    aeron_driver_termination_validator_func_t func = NULL;

    if (strncmp(validator_name, "allow", sizeof("allow")) == 0)
    {
        return aeron_driver_termination_validator_load("aeron_driver_termination_validator_default_allow");
    }
    else if (strncmp(validator_name, "deny", sizeof("deny")) == 0)
    {
        return aeron_driver_termination_validator_load("aeron_driver_termination_validator_default_deny");
    }
    else
    {
        if ((func = (aeron_driver_termination_validator_func_t) aeron_dlsym(RTLD_DEFAULT, validator_name)) == NULL)
        {
            aeron_set_err(
                EINVAL, "could not find termination validator %s: dlsym - %s", validator_name, aeron_dlerror());
            return NULL;
        }
    }

    return func;
}
Ejemplo n.º 21
0
int aeron_uri_get_term_length_param(aeron_uri_params_t *uri_params, aeron_uri_publication_params_t *params)
{
    const char *value_str;

    if ((value_str = aeron_uri_find_param_value(uri_params, AERON_URI_TERM_LENGTH_KEY)) != NULL)
    {
        uint64_t value;

        if (-1 == aeron_parse_size64(value_str, &value))
        {
            aeron_set_err(EINVAL, "could not parse %s in URI", AERON_URI_TERM_LENGTH_KEY);
            return -1;
        }

        if (aeron_logbuffer_check_term_length(value) < 0)
        {
            return -1;
        }

        params->term_length = value;
    }

    return 0;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
int aeron_udp_transport_poller_poll(
    aeron_udp_transport_poller_t *poller,
    struct mmsghdr *msgvec,
    size_t vlen,
    aeron_udp_transport_recv_func_t recv_func,
    void *clientd)
{
    int work_count = 0;

    if (poller->transports.length <= AERON_UDP_TRANSPORT_POLLER_ITERATION_THRESHOLD)
    {
        for (size_t i = 0, length = poller->transports.length; i < length; i++)
        {
            int recv_result = aeron_udp_channel_transport_recvmmsg(
                poller->transports.array[i].transport, msgvec, vlen, recv_func, clientd);
            if (recv_result < 0)
            {
                return recv_result;
            }

            work_count += recv_result;
        }
    }
    else
    {
#if defined(HAVE_EPOLL)
        int result = epoll_wait(poller->epoll_fd, poller->epoll_events, (int)poller->transports.length, 0);

        if (result < 0)
        {
            int err = errno;

            if (EINTR == err || EAGAIN == err)
            {
                return 0;
            }

            aeron_set_err(err, "epoll_wait: %s", strerror(err));
            return -1;
        }
        else if (0 == result)
        {
            return 0;
        }
        else
        {
            for (size_t i = 0, length = result; i < length; i++)
            {
                if (poller->epoll_events[i].events & EPOLLIN)
                {
                    int recv_result = aeron_udp_channel_transport_recvmmsg(
                        poller->epoll_events[i].data.ptr, msgvec, vlen, recv_func, clientd);

                    if (recv_result < 0)
                    {
                        return recv_result;
                    }

                    work_count += recv_result;
                }

                poller->epoll_events[i].events = 0;
            }
        }

#elif defined(HAVE_POLL)
        int result = poll(poller->pollfds, (nfds_t)poller->transports.length, 0);

        if (result < 0)
        {
            int err = errno;

            if (EINTR == err || EAGAIN == err)
            {
                return 0;
            }

            aeron_set_err(err, "poll: %s", strerror(err));
            return -1;
        }
        else if (0 == result)
        {
            return 0;
        }
        else
        {
            for (size_t i = 0, length = poller->transports.length; i < length; i++)
            {
                if (poller->pollfds[i].revents & POLLIN)
                {
                    int recv_result = aeron_udp_channel_transport_recvmmsg(
                        poller->transports.array[i].transport, msgvec, vlen, recv_func, clientd);

                    if (recv_result < 0)
                    {
                        return recv_result;
                    }

                    work_count += recv_result;
                }

                poller->pollfds[i].revents = 0;
            }
        }
#endif
    }

    return work_count;
}
Ejemplo n.º 24
0
int aeron_interface_split(const char *interface_str, aeron_parsed_interface_t *parsed_interface)
{
    if (NULL == interface_str || '\0' == *interface_str)
    {
        aeron_set_err(EINVAL, "no interface value");
        return -1;
    }

    int percent_index = -1;
    int colon_index = -1;
    int l_brace_index = -1;
    int r_brace_index = -1;
    int slash_index = -1;

    int i = 0;
    char c = *interface_str;
    while ('\0' != c)
    {
        if (':' == c)
        {
            colon_index = i;
        }
        else if ('[' == c)
        {
            l_brace_index = i;
        }
        else if (']' == c)
        {
            r_brace_index = i;
        }
        else if ('/'  == c)
        {
            slash_index = i;
        }
        else if ('%'  == c)
        {
            percent_index = i;
        }

        ++i;
        c = *(interface_str + i);
    }

    bool is_ipv6 = false;
    if (l_brace_index > 0 || r_brace_index > 0)
    {
        if (l_brace_index < 0 || r_brace_index < 0 || r_brace_index < l_brace_index)
        {
            aeron_set_err(EINVAL, "host address invalid: %s", interface_str);
            return -1;
        }

        is_ipv6 = true;
        parsed_interface->ip_version_hint = 6;
    }
    else
    {
        parsed_interface->ip_version_hint = 4;
    }

    *parsed_interface->prefix = '\0';
    if (slash_index >= 0)
    {
        int length = i - slash_index;
        if (length <= 0)
        {
            aeron_set_err(EINVAL, "subnet prefix invalid: %s", interface_str);
            return -1;
        }

        if (length >= AERON_MAX_PREFIX_LENGTH)
        {
            aeron_set_err(EINVAL, "subnet prefix invalid: %s", interface_str);
            return -1;
        }

        strncpy(parsed_interface->prefix, interface_str + slash_index + 1, (size_t)length);
        *(parsed_interface->prefix + length) = '\0';
    }

    *parsed_interface->port = '\0';
    if (colon_index >= 0 && r_brace_index < colon_index)
    {
        if (i - 1 == colon_index)
        {
            aeron_set_err(EINVAL, "port invalid: %s", interface_str);
            return -1;
        }

        int port_begin = colon_index + 1;
        int length = slash_index > 0 ? slash_index - port_begin : i - port_begin;

        if (length >= AERON_MAX_PORT_LENGTH)
        {
            aeron_set_err(EINVAL, "port invalid: %s", interface_str);
            return -1;
        }

        strncpy(parsed_interface->port, interface_str + port_begin, (size_t)length);
        *(parsed_interface->port + length) = '\0';
    }

    int length = i;

    if (slash_index >= 0)
    {
        length = slash_index;
    }

    if (colon_index >= 0 && colon_index > r_brace_index)
    {
        length = colon_index;
    }

    bool is_scoped = false;
    if (percent_index >= 0 && percent_index < r_brace_index)
    {
        length = percent_index;
        is_scoped = true;
    }

    const char *host = is_ipv6 ? interface_str + 1 : interface_str;
    if (is_ipv6)
    {
        length =  is_scoped ? length -1 : length - 2;
    }

    if (length >= AERON_MAX_HOST_LENGTH)
    {
        aeron_set_err(EINVAL, "host address invalid: %s", interface_str);
        return -1;
    }

    strncpy(parsed_interface->host, host, (size_t)length);
    *(parsed_interface->host + length) = '\0';

    return 0;
}
Ejemplo n.º 25
0
int aeron_address_split(const char *address_str, aeron_parsed_address_t *parsed_address)
{
    if (NULL == address_str || '\0' == *address_str)
    {
        aeron_set_err(EINVAL, "no address value");
        return -1;
    }

    int percent_index = -1;
    int colon_index = -1;
    int l_brace_index = -1;
    int r_brace_index = -1;

    int i = 0;
    char c = *address_str;
    while ('\0' != c)
    {
        if (':' == c)
        {
            colon_index = i;
        }
        else if ('[' == c)
        {
            l_brace_index = i;
        }
        else if (']' == c)
        {
            r_brace_index = i;
        }
        else if ('%'  == c)
        {
            percent_index = i;
        }

        ++i;
        c = *(address_str + i);
    }

    bool is_ipv6 = false;
    if (l_brace_index > 0 || r_brace_index > 0)
    {
        if (l_brace_index < 0 || r_brace_index < 0 || r_brace_index < l_brace_index)
        {
            aeron_set_err(EINVAL, "host address invalid: %s", address_str);
            return -1;
        }

        is_ipv6 = true;
        parsed_address->ip_version_hint = 6;
    }
    else
    {
        parsed_address->ip_version_hint = 4;
    }

    *parsed_address->port = '\0';
    if (colon_index >= 0 && r_brace_index < colon_index)
    {
        if (i - 1 == colon_index)
        {
            aeron_set_err(EINVAL, "port invalid: %s", address_str);
            return -1;
        }

        int port_begin = colon_index + 1;
        int length = i - port_begin;

        if (length >= AERON_MAX_PORT_LENGTH)
        {
            aeron_set_err(EINVAL, "port invalid: %s", address_str);
            return -1;
        }

        strncpy(parsed_address->port, address_str + port_begin, (size_t)length);
        *(parsed_address->port + length) = '\0';
    }

    int length = i;

    if (colon_index >= 0 && colon_index > r_brace_index)
    {
        length = colon_index;
    }

    bool is_scoped = false;
    if (percent_index >= 0 && percent_index < r_brace_index)
    {
        is_scoped = true;
        length = percent_index;
    }

    const char *host = is_ipv6 ? address_str + 1 : address_str;
    if (is_ipv6)
    {
        length =  is_scoped ? length -1 : length - 2;
    }

    if (length >= AERON_MAX_HOST_LENGTH)
    {
        aeron_set_err(EINVAL, "host address invalid: %s", address_str);
        return -1;
    }

    strncpy(parsed_address->host, host, (size_t)length);
    *(parsed_address->host + length) = '\0';

    return 0;
}
Ejemplo n.º 26
0
int aeron_uri_publication_params(
    aeron_uri_t *uri,
    aeron_uri_publication_params_t *params,
    aeron_driver_context_t *context,
    bool is_exclusive)
{
    params->linger_timeout_ns = context->publication_linger_timeout_ns;
    params->term_length = AERON_URI_IPC == uri->type ? context->ipc_term_buffer_length : context->term_buffer_length;
    params->mtu_length = AERON_URI_IPC == uri->type ? context->ipc_mtu_length : context->mtu_length;
    params->initial_term_id = 0;
    params->term_offset = 0;
    params->term_id = 0;
    params->is_replay = false;
    params->is_sparse = context->term_buffer_sparse_file;
    aeron_uri_params_t *uri_params = AERON_URI_IPC == uri->type ?
        &uri->params.ipc.additional_params : &uri->params.udp.additional_params;

    if (aeron_uri_linger_timeout_param(uri_params, params) < 0)
    {
        return -1;
    }

    if (aeron_uri_get_term_length_param(uri_params, params) < 0)
    {
        return -1;
    }

    if (aeron_uri_get_mtu_length_param(uri_params, params) < 0)
    {
        return -1;
    }

    if (is_exclusive)
    {
        const char *initial_term_id_str = NULL;
        const char *term_id_str = NULL;
        const char *term_offset_str = NULL;
        int count = 0;

        initial_term_id_str = aeron_uri_find_param_value(uri_params, AERON_URI_INITIAL_TERM_ID_KEY);
        count += initial_term_id_str ? 1 : 0;

        term_id_str = aeron_uri_find_param_value(uri_params, AERON_URI_TERM_ID_KEY);
        count += term_id_str ? 1 : 0;

        term_offset_str = aeron_uri_find_param_value(uri_params, AERON_URI_TERM_OFFSET_KEY);
        count += term_offset_str ? 1 : 0;

        if (count > 0)
        {
            char *end_ptr = NULL;

            if (count < 3)
            {
                aeron_set_err(EINVAL, "params must be used as a complete set: %s %s %s",
                    AERON_URI_INITIAL_TERM_ID_KEY, AERON_URI_TERM_ID_KEY, AERON_URI_TERM_OFFSET_KEY);
                return -1;
            }

            errno = 0;
            end_ptr = NULL;
            if (((params->initial_term_id = strtoll(initial_term_id_str, &end_ptr, 0)) == 0 && 0 != errno) ||
                end_ptr == initial_term_id_str)
            {
                aeron_set_err(EINVAL, "could not parse %s in URI", AERON_URI_INITIAL_TERM_ID_KEY);
                return -1;
            }

            errno = 0;
            end_ptr = NULL;
            if (((params->term_id = strtoll(term_id_str, &end_ptr, 0)) == 0 && 0 != errno) ||
                end_ptr == term_id_str)
            {
                aeron_set_err(EINVAL, "could not parse %s in URI", AERON_URI_TERM_ID_KEY);
                return -1;
            }

            errno = 0;
            end_ptr = NULL;
            if (((params->term_offset = strtoull(term_offset_str, &end_ptr, 0)) == 0 && 0 != errno) ||
                end_ptr == term_offset_str)
            {
                aeron_set_err(EINVAL, "could not parse %s in URI", AERON_URI_TERM_OFFSET_KEY);
                return -1;
            }

            if (params->initial_term_id < INT32_MIN || params->initial_term_id > INT32_MAX)
            {
                aeron_set_err(
                    EINVAL,
                    "Params %s=%" PRId64 " out of range", AERON_URI_INITIAL_TERM_ID_KEY, params->initial_term_id);
                return -1;
            }

            if (params->term_id < INT32_MIN || params->term_id > INT32_MAX)
            {
                aeron_set_err(EINVAL, "Params %s=%" PRId64 " out of range", AERON_URI_TERM_ID_KEY, params->term_id);
                return -1;
            }

            if (((int32_t)params->term_id - (int32_t)params->initial_term_id) < 0)
            {
                aeron_set_err(
                    EINVAL,
                    "Param difference greater than 2^31 - 1: %s=%" PRId64 " %s=%" PRId64,
                    AERON_URI_INITIAL_TERM_ID_KEY,
                    params->initial_term_id,
                    AERON_URI_TERM_OFFSET_KEY,
                    params->term_id);
                return -1;
            }

            if (params->term_offset > params->term_length)
            {
                aeron_set_err(
                    EINVAL,
                    "Param %s=%" PRIu64 " > %s=%" PRIu64,
                    AERON_URI_TERM_OFFSET_KEY,
                    params->term_offset,
                    AERON_URI_TERM_LENGTH_KEY,
                    params->term_length);
                return -1;
            }

            if ((params->term_offset & (AERON_LOGBUFFER_FRAME_ALIGNMENT - 1)) != 0)
            {
                aeron_set_err(
                    EINVAL,
                    "Param %s=%" PRIu64 " must be multiple of FRAME_ALIGNMENT",
                    AERON_URI_TERM_OFFSET_KEY,
                    params->term_offset);
                return -1;
            }

            params->is_replay = true;
        }
    }

    const char *value_str;

    if ((value_str = aeron_uri_find_param_value(uri_params, AERON_URI_SPARSE_TERM_KEY)) != NULL)
    {
        if (strncmp("true", value_str, strlen("true")) == 0)
        {
            params->is_sparse = true;
        }
    }

    return 0;
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
0
int aeron_udp_channel_transport_recvmmsg(
    aeron_udp_channel_transport_t *transport,
    struct mmsghdr *msgvec,
    size_t vlen,
    aeron_udp_transport_recv_func_t recv_func,
    void *clientd)
{
#if defined(HAVE_RECVMMSG)
    struct timespec tv = {.tv_nsec = 0, .tv_sec = 0};

    int result = recvmmsg(transport->fd, msgvec, vlen, 0, &tv);
    if (result < 0)
    {
        int err = errno;

        if (EINTR == err || EAGAIN == err)
        {
            return 0;
        }

        aeron_set_err(err, "recvmmsg: %s", strerror(err));
        return -1;
    }
    else if (0 == result)
    {
        return 0;
    }
    else
    {
        for (size_t i = 0, length = result; i < length; i++)
        {
            recv_func(
                clientd,
                transport->dispatch_clientd,
                msgvec[i].msg_hdr.msg_iov[0].iov_base,
                msgvec[i].msg_len,
                msgvec[i].msg_hdr.msg_name);
        }

        return result;
    }
#else
    int work_count = 0;

    for (size_t i = 0, length = vlen; i < length; i++)
    {
        ssize_t result = recvmsg(transport->fd, &msgvec[i].msg_hdr, 0);

        if (result < 0)
        {
            int err = errno;

            if (EINTR == err || EAGAIN == err)
            {
                break;
            }

            aeron_set_err(err, "recvmsg: %s", strerror(err));
            return -1;
        }
        if (0 == result)
        {
            break;
        }

        msgvec[i].msg_len = (unsigned int)result;
        recv_func(
            clientd,
            transport->dispatch_clientd,
            msgvec[i].msg_hdr.msg_iov[0].iov_base,
            msgvec[i].msg_len,
            msgvec[i].msg_hdr.msg_name);
        work_count++;
    }

    return work_count;
#endif
}

int aeron_udp_channel_transport_sendmmsg(
    aeron_udp_channel_transport_t *transport,
    struct mmsghdr *msgvec,
    size_t vlen)
{
#if defined(HAVE_RECVMMSG)
    int sendmmsg_result = sendmmsg(transport->fd, msgvec, vlen, 0);
    if (sendmmsg_result < 0)
    {
        aeron_set_err(errno, "sendmmsg: %s", strerror(errno));
        return -1;
    }

    return sendmmsg_result;
#else
    int result = 0;

    for (size_t i = 0, length = vlen; i < length; i++)
    {
        ssize_t sendmsg_result = sendmsg(transport->fd, &msgvec[i].msg_hdr, 0);
        if (sendmsg_result < 0)
        {
            aeron_set_err(errno, "sendmsg: %s", strerror(errno));
            return -1;
        }

        msgvec[i].msg_len = (unsigned int)sendmsg_result;

        if (0 == sendmsg_result)
        {
            break;
        }

        result++;
    }

    return result;
#endif
}
Ejemplo n.º 29
0
int aeron_udp_channel_transport_init(
    aeron_udp_channel_transport_t *transport,
    struct sockaddr_storage *bind_addr,
    struct sockaddr_storage *multicast_if_addr,
    unsigned int multicast_if_index,
    uint8_t ttl,
    size_t socket_rcvbuf,
    size_t socket_sndbuf)
{
    bool is_ipv6, is_multicast;
    struct sockaddr_in *in4 = (struct sockaddr_in *)bind_addr;
    struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)bind_addr;

    transport->fd = -1;
    if ((transport->fd = socket(bind_addr->ss_family, SOCK_DGRAM, 0)) < 0)
    {
        goto error;
    }

    is_ipv6 = (AF_INET6 == bind_addr->ss_family);
    is_multicast = aeron_is_addr_multicast(bind_addr);
    socklen_t bind_addr_len = is_ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);

    if (!is_multicast)
    {
        if (bind(transport->fd, (struct sockaddr *)bind_addr, bind_addr_len) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "unicast bind: %s", strerror(errcode));
            goto error;
        }
    }
    else
    {
        int reuse = 1;

#if defined(SO_REUSEADDR)
        if (setsockopt(transport->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "setsockopt(SO_REUSEADDR): %s", strerror(errcode));
            goto error;
        }
#endif

#if defined(SO_REUSEPORT)
        if (setsockopt(transport->fd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(reuse)) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "setsockopt(SO_REUSEPORT): %s", strerror(errcode));
            goto error;
        }
#endif

        if (bind(transport->fd, (struct sockaddr *) bind_addr, bind_addr_len) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "multicast bind: %s", strerror(errcode));
            goto error;
        }

        if (is_ipv6)
        {
            struct ipv6_mreq mreq;

            memcpy(&mreq.ipv6mr_multiaddr, &in6->sin6_addr, sizeof(in6->sin6_addr));
            mreq.ipv6mr_interface = multicast_if_index;

            if (setsockopt(transport->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
            {
                int errcode = errno;

                aeron_set_err(errcode, "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errcode));
                goto error;
            }

            if (setsockopt(
                transport->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if_index, sizeof(multicast_if_index)) < 0)
            {
                int errcode = errno;

                aeron_set_err(errcode, "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errcode));
                goto error;
            }

            if (ttl > 0)
            {
                if (setsockopt(transport->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0)
                {
                    int errcode = errno;

                    aeron_set_err(errcode, "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errcode));
                    goto error;
                }
            }
        }
        else
        {
            struct ip_mreq mreq;
            struct sockaddr_in *interface_addr = (struct sockaddr_in *) &multicast_if_addr;

            mreq.imr_multiaddr.s_addr = in4->sin_addr.s_addr;
            mreq.imr_interface.s_addr = interface_addr->sin_addr.s_addr;

            if (setsockopt(transport->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
            {
                int errcode = errno;

                aeron_set_err(errcode, "setsockopt(IP_ADD_MEMBERSHIP): %s", strerror(errcode));
                goto error;
            }

            if (setsockopt(transport->fd, IPPROTO_IP, IP_MULTICAST_IF, interface_addr, sizeof(struct in_addr)) < 0)
            {
                int errcode = errno;

                aeron_set_err(errcode, "setsockopt(IP_MULTICAST_IF): %s", strerror(errcode));
                goto error;
            }

            if (ttl > 0)
            {
                if (setsockopt(transport->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
                {
                    int errcode = errno;

                    aeron_set_err(errcode, "setsockopt(IP_MULTICAST_TTL): %s", strerror(errcode));
                    goto error;
                }
            }
        }
    }

    if (socket_rcvbuf > 0)
    {
        if (setsockopt(transport->fd, SOL_SOCKET, SO_RCVBUF, &socket_rcvbuf, sizeof(socket_rcvbuf)) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "setsockopt(SO_RCVBUF): %s", strerror(errcode));
            goto error;
        }
    }

    if (socket_sndbuf > 0)
    {
        if (setsockopt(transport->fd, SOL_SOCKET, SO_SNDBUF, &socket_sndbuf, sizeof(socket_sndbuf)) < 0)
        {
            int errcode = errno;

            aeron_set_err(errcode, "setsockopt(SO_SNDBUF): %s", strerror(errcode));
            goto error;
        }
    }

    int flags;

    if ((flags = fcntl(transport->fd, F_GETFL, 0)) < 0)
    {
        int errcode = errno;

        aeron_set_err(errcode, "fcntl(F_GETFL): %s", strerror(errcode));
        goto error;
    }

    flags |= O_NONBLOCK;
    if (fcntl(transport->fd, F_SETFL, flags) < 0)
    {
        int errcode = errno;

        aeron_set_err(errcode, "fcntl(F_SETFL): %s", strerror(errcode));
        goto error;
    }

    return 0;

    error:
        close(transport->fd);
        transport->fd = -1;
        return -1;
}