bool deser_msg_vinv(struct msg_vinv *mv, struct const_buffer *buf) { msg_vinv_free(mv); uint32_t vlen; if (!deser_varlen(&vlen, buf)) return false; mv->invs = parr_new(vlen, free); unsigned int i; for (i = 0; i < vlen; i++) { struct bp_inv *inv; inv = calloc(1, sizeof(*inv)); if (!deser_bp_inv(inv, buf)) { free(inv); goto err_out; } parr_add(mv->invs, inv); } return true; err_out: msg_vinv_free(mv); return false; }
static bool nc_msg_inv(struct nc_conn *conn) { struct const_buffer buf = { conn->msg.data, conn->msg.hdr.data_len }; struct msg_vinv mv, mv_out; bool rc = false; msg_vinv_init(&mv); msg_vinv_init(&mv_out); if (!deser_msg_vinv(&mv, &buf)) goto out; if (log_state->debug && mv.invs && mv.invs->len == 1) { struct bp_inv *inv = parr_idx(mv.invs, 0); char hexstr[BU256_STRSZ]; bu256_hex(hexstr, &inv->hash); char typestr[32]; switch (inv->type) { case MSG_TX: strcpy(typestr, "tx"); break; case MSG_BLOCK: strcpy(typestr, "block"); break; default: sprintf(typestr, "unknown 0x%x", inv->type); break; } log_debug("net: %s inv %s %s", conn->addr_str, typestr, hexstr); } else if (mv.invs) { log_debug("net: %s inv (%zu sz)", conn->addr_str, mv.invs->len); } if (!mv.invs || !mv.invs->len) goto out_ok; /* scan incoming inv's for interesting material */ unsigned int i; for (i = 0; i < mv.invs->len; i++) { struct bp_inv *inv = parr_idx(mv.invs, i); switch (inv->type) { case MSG_BLOCK: if (conn->nci->inv_block_process(&inv->hash)) msg_vinv_push(&mv_out, MSG_BLOCK, &inv->hash); break; case MSG_TX: default: break; } } /* send getdata, if they have anything we want */ if (mv_out.invs && mv_out.invs->len) { cstring *s = ser_msg_vinv(&mv_out); rc = nc_conn_send(conn, "getdata", s->str, s->len); cstr_free(s, true); } out_ok: rc = true; out: msg_vinv_free(&mv); msg_vinv_free(&mv_out); return rc; }
/* * struct msg_vinv { parr *invs; array of bp_inv }; struct bp_inv { uint32_t type; bu256_t hash; }; * * */ static bool nc_msg_inv(struct nc_conn *conn) { struct const_buffer buf = { conn->msg.data, conn->msg.hdr.data_len }; struct msg_vinv mv, mv_out; bool rc = false; unsigned int i=0; int msg_tx, msg_block, msg_other; msg_tx = msg_block = msg_other = 0; msg_vinv_init(&mv);//memset msg_vinv_init(&mv_out);//memset if (!deser_msg_vinv(&mv, &buf)) goto out; if (mv.invs){ //LOG("Peer [%s] gave %d inventory vectors",conn->addr_str, mv.invs->len); for (i = 0;i < mv.invs->len; i++){ struct bp_inv *inv = parr_idx(mv.invs, 0); switch (inv->type){ case MSG_TX: msg_tx++; break; case MSG_BLOCK: msg_block++; break; default: msg_other++; } } if (mv.invs->len > 0){ LOG("Inventory vectors: msg[%d], block[%d], other[%d]", msg_tx, msg_block, msg_other); } } if (debugging && mv.invs && mv.invs->len == 1) { struct bp_inv *inv = parr_idx(mv.invs, 0); char hexstr[BU256_STRSZ]; bu256_hex(hexstr, &inv->hash); char typestr[32]; switch (inv->type) { case MSG_TX: strcpy(typestr, "tx"); break; case MSG_BLOCK: strcpy(typestr, "block"); break; default: sprintf(typestr, "unknown 0x%x", inv->type); break; } fprintf(plog, "net: %s inv %s %s\n", conn->addr_str, typestr, hexstr); } else if (debugging && mv.invs) { fprintf(plog, "net: %s inv (%zu sz)\n", conn->addr_str, mv.invs->len); } if (!mv.invs || !mv.invs->len) goto out_ok; /* scan incoming inv's for interesting material */ /*declared at beginnning of function--> unsigned int i;*/ for (i = 0; i < mv.invs->len; i++) { struct bp_inv *inv = parr_idx(mv.invs, i); switch (inv->type) { case MSG_BLOCK: if (!blkdb_lookup(&db, &inv->hash) && !have_orphan(&inv->hash)) msg_vinv_push(&mv_out, MSG_BLOCK, &inv->hash); break; case MSG_TX: default: break; } } /* send getdata, if they have anything we want */ if (mv_out.invs && mv_out.invs->len) { cstring *s = ser_msg_vinv(&mv_out); rc = nc_conn_send(conn, "getdata", s->str, s->len); cstr_free(s, true); } out_ok: rc = true; out: msg_vinv_free(&mv); msg_vinv_free(&mv_out); return rc; }