Crate tox [] [src]

Rust implementation of the Tox protocol.

Repo: https://github.com/zetok/tox

C API: https://github.com/ze-tox/tox-capi

Current API allows one to e.g. find info about DHT nodes from bootstrap nodes by sending GetNodes or request Ping response.

To request a ping response:

// for networking
extern crate tokio_core;
use tokio_core::reactor::Core;

// to get bytes from PK in hex and to make PK from them
extern crate rustc_serialize;
use rustc_serialize::hex::FromHex;

extern crate tox;
use tox::toxcore::binary_io::*;
use tox::toxcore::crypto_core::*;
use tox::toxcore::dht::*;
use tox::toxcore::network::*;
use tox::toxcore::packet_kind::PacketKind;

fn main() {
    let mut reactor = Core::new().unwrap();
    let handle = reactor.handle();
    // get PK bytes from some "random" bootstrap node (Impyy's)
    let bootstrap_pk_bytes = FromHex::from_hex("6FC41E2BD381D37E9748FC0E0328CE086AF9598BECC8FEB7DDF2E440475F300E").unwrap();
    // create PK from bytes
    let bootstrap_pk = PublicKey::from_slice(&bootstrap_pk_bytes).unwrap();

    // generate own PublicKey, SecretKey keypair
    let (pk, sk) = gen_keypair();

    // and to encrypt data there precomputed symmetric key is needed, created
    // from PK of the peer you want to send data to, and your own secret key.
    let precomp = precompute(&bootstrap_pk, &sk);

    // also generate nonce that will be needed to make the encryption happen
    let nonce = gen_nonce();

    // now create Ping request
    let ping = &PingReq::new();

    // with Ping packet create DhtPacket, and serialize it to bytes
    let dhtpacket = DhtPacket::new(&precomp, &pk, &nonce, ping).to_bytes();

    // and since packet is ready, prepare the network part;
    // bind to given address and port in given range
    // `0.0.0.0` is used instead of `::` to appease windows' rage
    let socket = bind_udp("0.0.0.0".parse().unwrap(), 33445..33546, &handle)
        .expect("Failed to bind to socket!");

    // send DhtPacket via socket to the node (Imppy's)
    let sent_bytes = socket.send_dgram(&dhtpacket,
                 "51.15.37.145:33445".parse().unwrap());
    let (socket, _) = reactor.run(sent_bytes)
        .expect("Failed to send bytes!");

    // since data was sent, now receive response – for that, first prepare
    // buffer to receive data into
    let mut buf = [0; MAX_UDP_PACKET_SIZE];

    // and wait for the answer
    let future_data = socket.recv_dgram(&mut buf[..]);

    let (_socket, buf, n_bytes, _sender) = reactor.run(future_data)
        .expect("Failed to receive data");

    // try to deserialize received bytes as `DhtPacket`
    let recv_packet = match DhtPacket::from_bytes(&buf[..n_bytes]) {
        Some(p) => p,
        // if parsing fails ↓
        None => panic!("Received packet could not have been parsed!\n{:?}",
                        &buf[..n_bytes]),
    };

    // decrypt payload of the received packet
    let payload: PingResp = recv_packet.get_payload(&sk)
        .expect("Failed to decrypt payload!");

    assert_eq!(PacketKind::PingResp, payload.kind());
    assert_eq!(ping.id(), payload.id());
    println!("And contents of payload:\n{:?}", payload);
}

Modules

toxcore

Core Tox module. Provides an API on top of which other modules and applications may be build.

toxencryptsave

Tox Encrypt Save (a.k.a. TES) module. Can be used to ecrypt / decrypt data that will be stored on persistent storage. E.g.