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); }
/* 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); }