Exemple #1
0
static void nc_conn_write_evt(int fd, short events, void *priv)
{
	struct nc_conn *conn = priv;
	struct iovec *iov = NULL;
	unsigned int iov_len = 0;

	/* build list of outgoing data buffers */
	nc_conn_build_iov(conn->write_q, conn->write_partial, &iov, &iov_len);

	/* send data to network */
	ssize_t wrc = writev(conn->fd, iov, iov_len);

	free(iov);

	if (wrc < 0) {
		if (errno != EAGAIN && errno != EWOULDBLOCK)
			goto err_out;
		return;
	}

	/* handle partially and fully completed buffers */
	nc_conn_written(conn, wrc);

	/* thaw read, if write fully drained */
	if (!conn->write_q) {
		nc_conn_write_disable(conn);
		nc_conn_read_enable(conn);
	}

	return;

err_out:
	nc_conn_kill(conn);
}
Exemple #2
0
/*  connection begins */
static void nc_conn_evt_connected(int fd, short events, void *priv)
{
	struct nc_conn *conn = priv;

	if ((events & EV_WRITE) == 0) {
		fprintf(plog, "net: %s connection timeout\n", conn->addr_str);
		goto err_out;
	}

	int err = 0;
	socklen_t len = sizeof(err);

	/* check success of connect(2) */
	if ((getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) ||
	    (err != 0)) {
		fprintf(plog, "net: connect %s failed: %s\n",
			conn->addr_str, strerror(err));
		goto err_out;
	}

	if (debugging)
		fprintf(plog, "net: connected to %s\n", conn->addr_str);

	conn->connected = true;

	/* clear event used for watching connect(2) */
	event_free(conn->ev);
	conn->ev = NULL;

	/* build and send "version" message */

	cstring *msg_data = nc_version_build(conn);
	bool rc = nc_conn_send(conn, "version", msg_data->str, msg_data->len);
	cstr_free(msg_data, true);

	if (!rc) {
		fprintf(plog, "net: %s !conn_send\n", conn->addr_str);
		goto err_out;
	}

	/* switch to read-header state */
	conn->msg_p = conn->hdrbuf;
	/* from message.c #define P2P_HDR_SZ	(4 + 12 + 4 + 4)*/
	conn->expected = P2P_HDR_SZ;
	conn->reading_hdr = true;

	if (!nc_conn_read_enable(conn)) {
		fprintf(plog, "net: %s read not enabled\n", conn->addr_str);
		goto err_out;
	}

	return;

err_out:
	nc_conn_kill(conn);
}
Exemple #3
0
static void nc_conn_read_evt(int fd, short events, void *priv)
{
	struct nc_conn *conn = priv;

	ssize_t rrc = read(fd, conn->msg_p, conn->expected);
	if (rrc <= 0) {
		if (rrc < 0)
			fprintf(plog, "llnet: %s read: %s\n",
				conn->addr_str,
				strerror(errno));
		else
			fprintf(plog, "llnet: %s read EOF\n", conn->addr_str);

		goto err_out;
	}

	conn->msg_p += rrc;
	conn->expected -= rrc;

	/* execute our state machine at most twice */
	unsigned int i;
	for (i = 0; i < 2; i++) {
		if (conn->expected == 0) {
			if (conn->reading_hdr) {
				if (!nc_conn_got_header(conn))
					goto err_out;
			} else {
				if (!nc_conn_got_msg(conn))
					goto err_out;
			}
		}
	}

	return;

err_out:
	nc_conn_kill(conn);
}
Exemple #4
0
static void nc_conns_open(struct net_child_info *nci)
{
	log_debug("net: open connections (have %zu, want %zu more)",
		nci->conns->len,
		NC_MAX_CONN - nci->conns->len);

	while ((bp_hashtab_size(nci->peers->map_addr) > 0) &&
	       (nci->conns->len < NC_MAX_CONN)) {

		/* delete peer from front of address list.  it will be
		 * re-added before writing peer file, if successful
		 */
		struct peer *peer = peerman_pop(nci->peers);

		struct nc_conn *conn = nc_conn_new(peer);
		conn->nci = nci;
		peer_free(peer);
		free(peer);

		log_debug("net: connecting to %s",
			conn->addr_str);

		/* are we already connected to this IP? */
		if (nc_conn_ip_active(nci, conn->peer.addr.ip)) {
			log_info("net: already connected to %s",
				conn->addr_str);
			goto err_loop;
		}

		/* are we already connected to this network group? */
		if (nc_conn_group_active(nci, &conn->peer)) {
			log_info("net: already grouped to %s",
				conn->addr_str);
			goto err_loop;
		}

		/* initiate non-blocking connect(2) */
		if (!nc_conn_start(conn)) {
			log_info("net: failed to start connection to %s",
				conn->addr_str);
			goto err_loop;
		}

		/* add to our list of monitored event sources */
		conn->ev = event_new(nci->eb, conn->fd, EV_WRITE,
				     nc_conn_evt_connected, conn);
		if (!conn->ev) {
			log_info("net: event_new failed on %s",
				conn->addr_str);
			goto err_loop;
		}

		struct timeval timeout = { conn->nci->net_conn_timeout, };
		if (event_add(conn->ev, &timeout) != 0) {
			log_info("net: event_add failed on %s",
				conn->addr_str);
			goto err_loop;
		}

		/* add to our list of active connections */
		parr_add(nci->conns, conn);

		continue;

err_loop:
		nc_conn_kill(conn);
	}
}