Example #1
0
File: net.c Project: libbtc/libbtc
void btc_node_send_version(btc_node *node)
{
    if (!node)
        return;

    /* get new string buffer */
    cstring *version_msg_cstr = cstr_new_sz(256);

    /* copy socket_addr to p2p addr */
    btc_p2p_address fromAddr;
    btc_p2p_address_init(&fromAddr);
    btc_p2p_address toAddr;
    btc_p2p_address_init(&toAddr);
    btc_addr_to_p2paddr(&node->addr, &toAddr);

    /* create a version message struct */
    btc_p2p_version_msg version_msg;
    memset(&version_msg, 0, sizeof(version_msg));

    /* create a serialized version message */
    btc_p2p_msg_version_init(&version_msg, &fromAddr, &toAddr, node->nodegroup->clientstr);
    btc_p2p_msg_version_ser(&version_msg, version_msg_cstr);

    /* create p2p message */
    cstring *p2p_msg = btc_p2p_message_new(node->nodegroup->chainparams->netmagic, BTC_MSG_VERSION, version_msg_cstr->str, version_msg_cstr->len);

    /* send message */
    btc_node_send(node, p2p_msg);

    /* cleanup */
    cstr_free(version_msg_cstr, true);
    cstr_free(p2p_msg, true);
}
Example #2
0
File: net.c Project: libbtc/libbtc
void node_periodical_timer(int fd, short event, void *ctx) {
    UNUSED(fd);
    UNUSED(event);
    btc_node *node = (btc_node *)ctx;
    uint64_t now = time(NULL);

    /* pass data to the callback and give it a chance to cancle the call */
    if (node->nodegroup->periodic_timer_cb)
        if (!node->nodegroup->periodic_timer_cb(node, &now))
            return;

    if (node->time_started_con+BTC_CONNECT_TIMEOUT_S < now && ((node->state & NODE_CONNECTING) == NODE_CONNECTING))
    {
        node->state = 0;
        node->time_started_con = 0;
        node->state |= NODE_ERRORED;
        node->state |= NODE_TIMEOUT;
        btc_node_connection_state_changed(node);
    }

    if ( ((node->state & NODE_CONNECTED) == NODE_CONNECTED) && node->lastping + BTC_PING_INTERVAL_S < now)
    {
        //time for a ping
        uint64_t nonce;
        btc_cheap_random_bytes((uint8_t *)&nonce, sizeof(nonce));
        cstring *pingmsg = btc_p2p_message_new(node->nodegroup->chainparams->netmagic, BTC_MSG_PING, &nonce, sizeof(nonce));
        btc_node_send(node, pingmsg);
        cstr_free(pingmsg, true);
        node->lastping = now;
    }
}
Example #3
0
File: net.c Project: libbtc/libbtc
int btc_node_parse_message(btc_node *node, btc_p2p_msg_hdr *hdr, struct const_buffer *buf)
{
    node->nodegroup->log_write_cb("received command from node %d: %s\n",  node->nodeid, hdr->command);
    if (memcmp(hdr->netmagic, node->nodegroup->chainparams->netmagic, sizeof(node->nodegroup->chainparams->netmagic)) != 0)
        return 0;

    /* send the header and buffer to the possible callback */
    /* callback can decide to run the internal base message logic */
    if (!node->nodegroup->parse_cmd_cb || node->nodegroup->parse_cmd_cb(node, hdr, buf))
    {
        if (strcmp(hdr->command, BTC_MSG_VERSION) == 0)
        {
            /* confirm version for verack */
            cstring *verack = btc_p2p_message_new(node->nodegroup->chainparams->netmagic, BTC_MSG_VERACK, NULL, 0);
            btc_node_send(node, verack);
            cstr_free(verack, true);
        }
        else if (strcmp(hdr->command, BTC_MSG_VERACK) == 0)
        {
            /* complete handshake if verack has been received */
            node->version_handshake = true;

            /* execute callback and inform that the node is ready for custom message logic */
            if (node->nodegroup->handshake_done_cb)
                node->nodegroup->handshake_done_cb(node);
        }
        else if (strcmp(hdr->command, BTC_MSG_PING) == 0)
        {
            /* response pings */
            uint64_t nonce = 0;
            deser_u64(&nonce, buf);
            cstring *pongmsg = btc_p2p_message_new(node->nodegroup->chainparams->netmagic, BTC_MSG_PONG, &nonce, 8);
            btc_node_send(node, pongmsg);
            cstr_free(pongmsg, true);
        }
    }

    /* pass data to the "post command" callback */
    if (node->nodegroup->postcmd_cb)
        node->nodegroup->postcmd_cb(node, hdr, buf);

    return true;
}
Example #4
0
void test_protocol()
{
    /* get new string buffer */
    cstring *version_msg_cstr = cstr_new_sz(256);
    cstring *inv_msg_cstr = cstr_new_sz(256);

    struct sockaddr_in test_sa, test_sa_check;
    memset(&test_sa, 0, sizeof(test_sa));
    memset(&test_sa_check, 0, sizeof(test_sa_check));
    test_sa.sin_family = AF_INET;
    struct sockaddr_in6 test_sa6, test_sa6_check;
    test_sa6.sin6_family = AF_INET6;
    test_sa6.sin6_port = htons(1024);
    evutil_inet_pton(AF_INET, "10.0.0.1", &test_sa.sin_addr); // store IP in antelope

    char i6buf[1024];
    memset(&i6buf, 0, 1024);

    evutil_inet_pton(AF_INET6, "::1", &test_sa6.sin6_addr);
    btc_p2p_address ipv6Test;
    btc_p2p_address_init(&ipv6Test);
    btc_addr_to_p2paddr((struct sockaddr *)&test_sa6, &ipv6Test);
    btc_p2paddr_to_addr(&ipv6Test, (struct sockaddr *)&test_sa6_check);
    memset(&i6buf, 0, 1024);
    u_assert_int_eq(test_sa6.sin6_port, test_sa6_check.sin6_port);

    /* copy socket_addr to p2p addr */
    btc_p2p_address fromAddr;
    btc_p2p_address_init(&fromAddr);
    btc_p2p_address toAddr;
    btc_p2p_address_init(&toAddr);
    btc_addr_to_p2paddr((struct sockaddr *)&test_sa, &toAddr);
    btc_p2paddr_to_addr(&toAddr, (struct sockaddr *)&test_sa_check);
    u_assert_int_eq(test_sa.sin_port, test_sa_check.sin_port);
    evutil_inet_ntop(AF_INET, &test_sa_check.sin_addr, i6buf, 1024);
    u_assert_str_eq(i6buf, "10.0.0.1");

    /* create a inv message struct */
    btc_p2p_inv_msg inv_msg, inv_msg_check;
    memset(&inv_msg, 0, sizeof(inv_msg));

    uint256 hash = {0};

    btc_p2p_msg_inv_init(&inv_msg, 1, hash);
    btc_p2p_msg_inv_ser(&inv_msg, inv_msg_cstr);

    struct const_buffer buf_inv = {inv_msg_cstr->str, inv_msg_cstr->len};
    u_assert_int_eq(btc_p2p_msg_inv_deser(&inv_msg_check, &buf_inv), true);
    u_assert_int_eq(inv_msg_check.type, 1);
    u_assert_mem_eq(inv_msg_check.hash, inv_msg.hash, sizeof(inv_msg.hash));
    cstr_free(inv_msg_cstr, true);

    /* create a version message struct */
    btc_p2p_version_msg version_msg;
    memset(&version_msg, 0, sizeof(version_msg));

    /* create a serialized version message */
    btc_p2p_msg_version_init(&version_msg, &fromAddr, &toAddr, "client", false);
    btc_p2p_msg_version_ser(&version_msg, version_msg_cstr);

    /* create p2p message */
    cstring *p2p_msg = btc_p2p_message_new((unsigned const char *)&btc_chainparams_main.netmagic, BTC_MSG_VERSION, version_msg_cstr->str, version_msg_cstr->len);

    struct const_buffer buf = {p2p_msg->str, p2p_msg->len};
    btc_p2p_msg_hdr hdr;
    btc_p2p_deser_msghdr(&hdr, &buf);

    u_assert_mem_eq(hdr.netmagic, &btc_chainparams_main.netmagic, 4);
    u_assert_str_eq(hdr.command, BTC_MSG_VERSION);
    u_assert_int_eq(hdr.data_len, version_msg_cstr->len);
    u_assert_int_eq(buf.len, hdr.data_len);
    u_assert_int_eq(buf.len, hdr.data_len);
    u_assert_mem_eq(buf.p, version_msg_cstr->str, hdr.data_len);

    btc_p2p_version_msg v_msg_check;
    u_assert_int_eq(btc_p2p_msg_version_deser(&v_msg_check, &buf), true);

    u_assert_int_eq(v_msg_check.version, BTC_PROTOCOL_VERSION);
    u_assert_str_eq(v_msg_check.useragent, "client");
    u_assert_int_eq(v_msg_check.start_height, 0);

    cstr_free(p2p_msg, true);
    cstr_free(version_msg_cstr, true);

    /* getheaders */
    uint256 genesis_hash = {0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd6, 0x68, 0x9c, 0x08, 0x5a, 0xe1, 0x65, 0x83, 0x1e, 0x93, 0x4f, 0xf7, 0x63, 0xae, 0x46, 0xa2, 0xa6, 0xc1, 0x72, 0xb3, 0xf1, 0xb6, 0x0a, 0x8c, 0xe2, 0x6f};
    vector *blocklocators = vector_new(1, NULL);
    vector_add(blocklocators, genesis_hash);
    cstring *getheader_msg = cstr_new_sz(256);
    btc_p2p_msg_getheaders(blocklocators, NULL, getheader_msg);
    p2p_msg = btc_p2p_message_new((unsigned const char *)&btc_chainparams_main.netmagic, BTC_MSG_GETHEADERS, getheader_msg->str, getheader_msg->len);


    buf.p = p2p_msg->str;
    buf.len = p2p_msg->len;
    btc_p2p_deser_msghdr(&hdr, &buf);
    u_assert_str_eq(hdr.command, BTC_MSG_GETHEADERS);
    u_assert_int_eq(hdr.data_len, getheader_msg->len);


    uint256 hashstop_check;
    vector *blocklocators_check = vector_new(1, free);
    btc_p2p_deser_msg_getheaders(blocklocators_check, hashstop_check, &buf);
    u_assert_mem_eq(NULLHASH, hashstop_check, sizeof(hashstop_check));
    uint8_t *hash_loc_0 = vector_idx(blocklocators_check, 0);
    u_assert_mem_eq(genesis_hash, hash_loc_0, sizeof(genesis_hash));


    /* cleanup */
    cstr_free(getheader_msg, true);
    vector_free(blocklocators, true);
    vector_free(blocklocators_check, true);
    cstr_free(p2p_msg, true);
}