aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/geniza-net.rs
blob: 38dc50770095300b5d58dba659b3543c9efd9400 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Free Software under GPL-3.0, see LICENSE
// Copyright 2017 Bryan Newbold

extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate error_chain;
extern crate geniza;

// TODO: more careful import
use geniza::*;
use std::path::Path;
use clap::{App, SubCommand, Arg};

fn parse_dat_key(raw_key: &str) -> Result<Vec<u8>> {

    if raw_key.len() != 32 * 2 {
        bail!("dat key not correct length");
    }
    let mut key_bytes = vec![];
    for i in 0..32 {
        let r = u8::from_str_radix(&raw_key[2 * i..2 * i + 2], 16);
        match r {
            Ok(b) => key_bytes.push(b),
            Err(e) => bail!("Problem with hex: {}", e),
        };
    }
    Ok(key_bytes)
}

fn run() -> Result<()> {
    env_logger::init().unwrap();

    let matches = App::new("geniza-net")
        .version(env!("CARGO_PKG_VERSION"))
        .subcommand(
            SubCommand::with_name("connect")
                .about("Connects to a peer and exchanges handshake")
                .arg_from_usage("<host_port> 'peer host:port to connect to'")
                .arg_from_usage("<dat_key> 'dat key (public key) to register with'"),
        )
        .subcommand(
            SubCommand::with_name("receive-all")
                .about("Connects to a peer, pulls all metadata and content")
                .arg_from_usage("<host_port> 'peer host:port to connect to'")
                .arg_from_usage("<dat_key> 'dat key (public key) to register with'"),
        )
        .subcommand(
            SubCommand::with_name("discovery-key")
                .about("Prints (in hex) the discovery key for a dat archive")
                .arg_from_usage("<dat_key> 'dat key (public key) to convert (in hex)'"),
        )
        .subcommand(
            SubCommand::with_name("discovery-dns-name")
                .about("Prints the DNS name to query (mDNS or centrally) for peers")
                .arg_from_usage("<dat_key> 'dat key (public key) to convert (in hex)'"),
        )
        .get_matches();


    match matches.subcommand() {
        ("connect", Some(subm)) => {
            let host_port = subm.value_of("host_port").unwrap();
            let dat_key = subm.value_of("dat_key").unwrap();
            if dat_key.len() != 32 * 2 {
                bail!("dat key not correct length");
            }
            let mut key_bytes = vec![];
            for i in 0..32 {
                let r = u8::from_str_radix(&dat_key[2 * i..2 * i + 2], 16);
                match r {
                    Ok(b) => key_bytes.push(b),
                    Err(e) => bail!("Problem with hex: {}", e),
                };
            }
            DatConnection::connect(host_port, &key_bytes, false)?;
            println!("Done!");
        }
        ("receive-all", Some(subm)) => {
            let host_port = subm.value_of("host_port").unwrap();
            let dat_key = subm.value_of("dat_key").unwrap();
            if dat_key.len() != 32 * 2 {
                bail!("dat key not correct length");
            }
            let key_bytes = parse_dat_key(&dat_key)?;
            let mut dc = DatConnection::connect(host_port, &key_bytes, false)?;
            // XXX: number here totally arbitrary
            dc.receive_all(false, 10)?;
            dc.receive_all(true, 10)?;
            println!("Done!");
        }
        ("discovery-key", Some(subm)) => {
            let dat_key = subm.value_of("dat_key").unwrap();
            if dat_key.len() != 32 * 2 {
                bail!("dat key not correct length");
            }
            let key_bytes = parse_dat_key(&dat_key)?;
            let disc_key = make_discovery_key(&key_bytes);
            for b in disc_key {
                print!("{:02x}", b);
            }
            println!("");
        }
        ("discovery-dns-name", Some(subm)) => {
            let dat_key = subm.value_of("dat_key").unwrap();
            if dat_key.len() != 32 * 2 {
                bail!("dat key not correct length");
            }
            let key_bytes = parse_dat_key(&dat_key)?;
            let disc_key = make_discovery_key(&key_bytes);
            for b in 0..20 {
                print!("{:02x}", disc_key[b]);
            }
            println!(".dat.local");
        }
        _ => {
            println!("Missing or unimplemented command!");
            println!("{}", matches.usage());
            ::std::process::exit(-1);
        }
    }
    Ok(())
}

quick_main!(run);