Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/*
 * 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);
	}
}