/* * Obtain a socket to talk to this guy. * Not entirely trivial - this can be both an established * (incoming) connection, or one that we should establish. * * Note, we do not support transmission on the incoming * connection yet. */ static isns_socket_t * isns_scn_get_socket(isns_scn_t *scn) { isns_scn_funnel_t *f, *best = NULL; isns_socket_t *sock; unsigned int worst = 0, loops = 0, nfunnels; /* Keep it simple for now */ if ((f = scn->scn_current_funnel) != NULL && f->scn_socket) { if (!f->scn_bad) return f->scn_socket; /* Oops, we've seen timeouts on this socket. */ isns_socket_free(f->scn_socket); f->scn_socket = NULL; } again: nfunnels = 0; for (f = scn->scn_funnels; f; f = f->scn_next) { unsigned int badness = f->scn_bad; if (!best || badness < best->scn_bad) best = f; if (badness > worst) worst = badness; nfunnels++; } if (!best) return NULL; sock = isns_connect_to_portal(&best->scn_portal); if (sock == NULL) { /* Make sure we try each funnel exactly once */ best->scn_bad = worst + 1; if (++loops < nfunnels) goto again; return NULL; } /* Set the security context */ isns_socket_set_security_ctx(sock, isns_default_security_context(1)); isns_debug_scn("SCN: %s using portal %s\n", scn->scn_name, isns_portal_string(&best->scn_portal)); scn->scn_current_funnel = best; best->scn_socket = sock; return sock; }
/* * Server main loop */ void run_server(isns_server_t *server, isns_db_t *db) { isns_socket_t *sock; isns_security_t *ctx = NULL; isns_message_t *msg, *resp; int status; if (isns_config.ic_security) { const char *ksname; isns_keystore_t *ks; ctx = isns_default_security_context(1); if (!(ksname = isns_config.ic_client_keystore)) isns_fatal("config problem: no key store specified\n"); if (!strcasecmp(ksname, "db:")) ks = isns_create_db_keystore(db); else ks = isns_create_keystore(ksname); if (ks == NULL) isns_fatal("Unable to create keystore %s\n", ksname); isns_security_set_keystore(ctx, ks); } status = isns_dd_load_all(db); if (status != ISNS_SUCCESS) isns_fatal("Problem loading Discovery Domains from database\n"); if (isns_config.ic_control_socket) { sock = isns_create_server_socket(isns_config.ic_control_socket, NULL, AF_UNSPEC, SOCK_STREAM); if (sock == NULL) isns_fatal("Unable to create control socket\n"); /* isns_socket_set_security_ctx(sock, ctx); */ } sock = isns_create_server_socket(isns_config.ic_bind_address, "isns", opt_af, SOCK_STREAM); if (sock == NULL) isns_fatal("Unable to create server socket\n"); isns_socket_set_security_ctx(sock, ctx); if (isns_config.ic_slp_register) { slp_url = isns_slp_build_url(0); isns_slp_register(slp_url); atexit(slp_cleanup); } isns_esi_init(server); isns_scn_init(server); while (1) { struct timeval timeout = { 0, 0 }; time_t now, then, next_timeout = time(NULL) + 3600; /* Expire entities that haven't seen any activity * for a while. */ if (isns_config.ic_registration_period) { then = isns_db_expire(db); if (then && then < next_timeout) next_timeout = then; } /* Run any timers (eg for ESI) */ then = isns_run_timers(); if (then && then < next_timeout) next_timeout = then; /* There may be pending SCNs, push them out now */ then = isns_scn_transmit_all(); if (then && then < next_timeout) next_timeout = then; /* Purge any objects that have been marked for removal * from the DB (deleting them, or moving them to limbo * state). */ isns_db_purge(db); /* Determine how long we can sleep before working * the ESI queues and DB expiry again. */ now = time(NULL); if (next_timeout <= now) continue; timeout.tv_sec = next_timeout - now; if ((msg = isns_recv_message(&timeout)) == NULL) continue; if ((resp = isns_process_message(server, msg)) != NULL) { isns_socket_t *sock = isns_message_socket(msg); isns_socket_send(sock, resp); isns_message_release(resp); } isns_message_release(msg); } }