int aeron_udp_destination_tracker_sendmsg( aeron_udp_destination_tracker_t *tracker, aeron_udp_channel_transport_t *transport, struct msghdr *msghdr) { int64_t now_ns = tracker->nano_clock(); int min_bytes_sent = (int)msghdr->msg_iov->iov_len; for (int last_index = (int)tracker->destinations.length - 1, i = last_index; i >= 0; i--) { aeron_udp_destination_entry_t *entry = &tracker->destinations.array[i]; if (now_ns > (entry->time_of_last_activity_ns + tracker->destination_timeout_ns)) { aeron_array_fast_unordered_remove( (uint8_t *)tracker->destinations.array, sizeof(aeron_udp_destination_entry_t), (size_t)i, (size_t)last_index); last_index--; tracker->destinations.length--; } else { msghdr->msg_name = &entry->addr; msghdr->msg_namelen = AERON_ADDR_LEN(&entry->addr); const int sendmsg_result = aeron_udp_channel_transport_sendmsg(transport, msghdr); min_bytes_sent = sendmsg_result < min_bytes_sent ? sendmsg_result : min_bytes_sent; } } return min_bytes_sent; }
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; }