static int manager_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { Manager *m = userdata; int r; assert(q); assert(m); assert(m->current_server_name); m->resolve_query = sd_resolve_query_unref(m->resolve_query); if (ret != 0) { log_debug("Failed to resolve %s: %s", m->current_server_name->string, gai_strerror(ret)); /* Try next host */ return manager_connect(m); } for (; ai; ai = ai->ai_next) { _cleanup_free_ char *pretty = NULL; ServerAddress *a; assert(ai->ai_addr); assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data)); if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) { log_warning("Unsuitable address protocol for %s", m->current_server_name->string); continue; } r = server_address_new(m->current_server_name, &a, (const union sockaddr_union*) ai->ai_addr, ai->ai_addrlen); if (r < 0) { log_error("Failed to add server address: %s", strerror(-r)); return r; } server_address_pretty(a, &pretty); log_debug("Resolved address %s for %s.", pretty, m->current_server_name->string); } if (!m->current_server_name->addresses) { log_error("Failed to find suitable address for host %s.", m->current_server_name->string); /* Try next host */ return manager_connect(m); } manager_set_server_address(m, m->current_server_name->addresses); return manager_begin(m); }
static void connection_free(Connection *c) { assert(c); if (c->context) set_remove(c->context->connections, c); sd_event_source_unref(c->server_event_source); sd_event_source_unref(c->client_event_source); safe_close(c->server_fd); safe_close(c->client_fd); safe_close_pair(c->server_to_client_buffer); safe_close_pair(c->client_to_server_buffer); sd_resolve_query_unref(c->resolve_query); free(c); }
static int resolve_cb(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { Connection *c = userdata; assert(q); assert(c); if (ret != 0) { log_error("Failed to resolve host: %s", gai_strerror(ret)); goto fail; } c->resolve_query = sd_resolve_query_unref(c->resolve_query); return connection_start(c, ai->ai_addr, ai->ai_addrlen); fail: connection_free(c); return 0; /* ignore errors, continue serving */ }
int manager_connect(Manager *m) { int r; assert(m); manager_disconnect(m); m->event_retry = sd_event_source_unref(m->event_retry); if (!ratelimit_test(&m->ratelimit)) { log_debug("Slowing down attempts to contact servers."); r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m); if (r < 0) { log_error("Failed to create retry timer: %s", strerror(-r)); return r; } return 0; } /* If we already are operating on some address, switch to the * next one. */ if (m->current_server_address && m->current_server_address->addresses_next) manager_set_server_address(m, m->current_server_address->addresses_next); else { struct addrinfo hints = { .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG, .ai_socktype = SOCK_DGRAM, }; /* Hmm, we are through all addresses, let's look for the next host instead */ if (m->current_server_name && m->current_server_name->names_next) manager_set_server_name(m, m->current_server_name->names_next); else { ServerName *f; /* Our current server name list is exhausted, * let's find the next one to iterate. First * we try the system list, then the link list. * After having processed the link list we * jump back to the system list. However, if * both lists are empty, we change to the * fallback list. */ if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) { f = m->system_servers; if (!f) f = m->link_servers; } else { f = m->link_servers; if (!f) f = m->system_servers; } if (!f) f = m->fallback_servers; if (!f) { manager_set_server_name(m, NULL); log_debug("No server found."); return 0; } manager_set_server_name(m, f); } /* Tell the resolver to reread /etc/resolv.conf, in * case it changed. */ res_init(); /* Flush out any previously resolved addresses */ server_name_flush_addresses(m->current_server_name); log_debug("Resolving %s...", m->current_server_name->string); r = sd_resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, m); if (r < 0) { log_error("Failed to create resolver: %s", strerror(-r)); return r; } return 1; } r = manager_begin(m); if (r < 0) return r; return 1; } void manager_disconnect(Manager *m) { assert(m); m->resolve_query = sd_resolve_query_unref(m->resolve_query); m->event_timer = sd_event_source_unref(m->event_timer); m->event_receive = sd_event_source_unref(m->event_receive); m->server_socket = safe_close(m->server_socket); m->event_clock_watch = sd_event_source_unref(m->event_clock_watch); m->clock_watch_fd = safe_close(m->clock_watch_fd); m->event_timeout = sd_event_source_unref(m->event_timeout); sd_notifyf(false, "STATUS=Idle."); }