Skip to content

Commit 01efefb

Browse files
author
Roman Proskuryakov
authored
Merge pull request #367 from tox-rs/friends
Friends connection
2 parents 7840f8f + de5e84d commit 01efefb

File tree

12 files changed

+2051
-250
lines changed

12 files changed

+2051
-250
lines changed

examples/echo.rs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
// an example of echo server with current code
2+
//
3+
#[macro_use]
4+
extern crate log;
5+
6+
use futures::*;
7+
use futures::sync::mpsc;
8+
use hex::FromHex;
9+
use tokio::net::UdpSocket;
10+
use failure::{err_msg, Error};
11+
12+
use std::net::SocketAddr;
13+
14+
use tox::toxcore::binary_io::*;
15+
use tox::toxcore::dht::server::Server;
16+
use tox::toxcore::dht::server_ext::ServerExt;
17+
use tox::toxcore::dht::packed_node::PackedNode;
18+
use tox::toxcore::dht::lan_discovery::LanDiscoverySender;
19+
use tox::toxcore::crypto_core::*;
20+
use tox::toxcore::friend_connection::FriendConnections;
21+
use tox::toxcore::friend_connection::packet::*;
22+
use tox::toxcore::net_crypto::{NetCrypto, NetCryptoNewArgs};
23+
use tox::toxcore::onion::client::OnionClient;
24+
use tox::toxcore::tcp::client::Connections;
25+
use tox::toxcore::stats::Stats;
26+
27+
const BOOTSTRAP_NODES: [(&str, &str); 9] = [
28+
// Impyy
29+
("1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F", "198.98.51.198:33445"),
30+
// nurupo
31+
("F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67", "67.215.253.85:33445"),
32+
// Manolis
33+
("461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F", "130.133.110.14:33445"),
34+
// Busindre
35+
("A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702", "205.185.116.116:33445"),
36+
// ray65536
37+
("8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832", "85.172.30.117:33445"),
38+
// fluke571
39+
("3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B", "194.249.212.109:33445"),
40+
// MAH69K
41+
("DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43", "185.25.116.107:33445"),
42+
// clearmartin
43+
("CD133B521159541FB1D326DE9850F5E56A6C724B5B8E5EB5CD8D950408E95707", "46.101.197.175:443"),
44+
// tastytea
45+
("2B2137E094F743AC8BD44652C55F41DFACC502F125E99E4FE24D40537489E32F", "5.189.176.217:5190"),
46+
];
47+
48+
const SELF_SK: &str = "1A5EC1D6C3F1FA720A313C01F432B6AE0D4649A5121964C9992DDF32871E8DFD";
49+
50+
const FRIEND_PK: &str = "3E6A06DA48D1AB98549AD76890770B704AE9116D8654FBCD35C9BF2DB9233E21";
51+
52+
/// Bind a UDP listener to the socket address.
53+
fn bind_socket(addr: SocketAddr) -> UdpSocket {
54+
let socket = UdpSocket::bind(&addr).expect("Failed to bind UDP socket");
55+
socket.set_broadcast(true).expect("set_broadcast call failed");
56+
if addr.is_ipv6() {
57+
socket.set_multicast_loop_v6(true).expect("set_multicast_loop_v6 call failed");
58+
}
59+
socket
60+
}
61+
62+
fn main() {
63+
env_logger::init();
64+
65+
let (dht_pk, dht_sk) = gen_keypair();
66+
67+
let real_sk_bytes: [u8; 32] = FromHex::from_hex(SELF_SK).unwrap();
68+
let real_sk = SecretKey::from_slice(&real_sk_bytes).unwrap();
69+
let real_pk = real_sk.public_key();
70+
71+
// Create a channel for server to communicate with network
72+
let (tx, rx) = mpsc::channel(32);
73+
74+
let local_addr: SocketAddr = "0.0.0.0:33447".parse().unwrap(); // 0.0.0.0 for IPv4
75+
// let local_addr: SocketAddr = "[::]:33445".parse().unwrap(); // [::] for IPv6
76+
77+
let socket = bind_socket(local_addr);
78+
let stats = Stats::new();
79+
80+
let lan_discovery_sender = LanDiscoverySender::new(tx.clone(), dht_pk, local_addr.is_ipv6());
81+
82+
let (tcp_incoming_tx, _tcp_incoming_rx) = mpsc::unbounded();
83+
84+
let mut dht_server = Server::new(tx.clone(), dht_pk, dht_sk.clone());
85+
dht_server.enable_lan_discovery(true);
86+
dht_server.enable_ipv6_mode(local_addr.is_ipv6());
87+
88+
let tcp_connections = Connections::new(dht_pk, dht_sk.clone(), tcp_incoming_tx);
89+
let onion_client = OnionClient::new(dht_server.clone(), tcp_connections.clone(), real_sk.clone(), real_pk);
90+
91+
let (lossless_tx, lossless_rx) = mpsc::unbounded();
92+
let (lossy_tx, lossy_rx) = mpsc::unbounded();
93+
94+
let net_crypto = NetCrypto::new(NetCryptoNewArgs {
95+
udp_tx: tx,
96+
lossless_tx,
97+
lossy_tx,
98+
dht_pk,
99+
dht_sk,
100+
real_pk,
101+
real_sk: real_sk.clone(),
102+
precomputed_keys: dht_server.get_precomputed_keys(),
103+
});
104+
105+
dht_server.set_net_crypto(net_crypto.clone());
106+
dht_server.set_onion_client(onion_client.clone());
107+
108+
let friend_connections = FriendConnections::new(
109+
real_sk,
110+
real_pk,
111+
dht_server.clone(),
112+
tcp_connections.clone(),
113+
onion_client.clone(),
114+
net_crypto.clone(),
115+
);
116+
117+
let friend_pk_bytes: [u8; 32] = FromHex::from_hex(FRIEND_PK).unwrap();
118+
let friend_pk = PublicKey::from_slice(&friend_pk_bytes).unwrap();
119+
120+
friend_connections.add_friend(friend_pk);
121+
122+
// Bootstrap from nodes
123+
for &(pk, saddr) in &BOOTSTRAP_NODES {
124+
// get PK bytes of the bootstrap node
125+
let bootstrap_pk_bytes: [u8; 32] = FromHex::from_hex(pk).unwrap();
126+
// create PK from bytes
127+
let bootstrap_pk = PublicKey::from_slice(&bootstrap_pk_bytes).unwrap();
128+
129+
let node = PackedNode::new(saddr.parse().unwrap(), &bootstrap_pk);
130+
131+
dht_server.add_initial_bootstrap(node);
132+
onion_client.add_path_node(node);
133+
}
134+
135+
let net_crypto_c = net_crypto.clone();
136+
let friend_connections_c = friend_connections.clone();
137+
let lossless_future = lossless_rx
138+
.map_err(|()| unreachable!("rx can't fail"))
139+
.for_each(move |(pk, packet)| {
140+
match packet[0] {
141+
PACKET_ID_ALIVE => {
142+
friend_connections_c.handle_ping(pk);
143+
Box::new(future::ok(())) as Box<Future<Item = _, Error = _> + Send>
144+
},
145+
PACKET_ID_SHARE_RELAYS => {
146+
match ShareRelays::from_bytes(&packet) {
147+
IResult::Done(_, share_relays) =>
148+
Box::new(friend_connections_c.handle_share_relays(pk, share_relays)
149+
.map_err(Error::from))
150+
as Box<Future<Item = _, Error = _> + Send>,
151+
_ => Box::new(future::err(err_msg("Failed to parse ShareRelays")))
152+
}
153+
},
154+
0x18 => { // PACKET_ID_ONLINE
155+
let online_future = net_crypto_c.send_lossless(pk, vec![0x18]);
156+
let name_future = net_crypto_c.send_lossless(pk, b"\x30tox-rs".to_vec());
157+
Box::new(online_future.join(name_future).map(|_| ()).map_err(Error::from))
158+
},
159+
0x40 => { // PACKET_ID_CHAT_MESSAGE
160+
Box::new(net_crypto_c.send_lossless(pk, packet).map_err(Error::from))
161+
},
162+
_ => Box::new(future::ok(())),
163+
}
164+
});
165+
166+
let lossy_future = lossy_rx
167+
.map_err(|()| unreachable!("rx can't fail"))
168+
.for_each(|_| future::ok(()));
169+
170+
let futures = vec![
171+
Box::new(dht_server.run_socket(socket, rx, stats).map_err(Error::from)) as Box<Future<Item = _, Error = _> + Send>,
172+
Box::new(lan_discovery_sender.run().map_err(Error::from)),
173+
Box::new(tcp_connections.run().map_err(Error::from)),
174+
Box::new(onion_client.run().map_err(Error::from)),
175+
Box::new(net_crypto.run().map_err(Error::from)),
176+
Box::new(friend_connections.run().map_err(Error::from)),
177+
Box::new(lossless_future),
178+
Box::new(lossy_future),
179+
];
180+
181+
let future = future::select_all(futures)
182+
.map(|_| ())
183+
.map_err(|(e, _, _)| error!("Processing ended with error: {:?}", e));
184+
185+
info!("Running echo server on {}", local_addr);
186+
187+
tokio::run(future);
188+
}

examples/onion_client.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ fn main() {
7676

7777
let dht_server = Server::new(tx.clone(), dht_pk, dht_sk.clone());
7878
let tcp_connections = Connections::new(dht_pk, dht_sk, tcp_incoming_tx);
79-
let onion_client = OnionClient::new(dht_server, tcp_connections, dht_pk_tx, real_sk, real_pk);
79+
let onion_client = OnionClient::new(dht_server, tcp_connections, real_sk, real_pk);
80+
81+
onion_client.set_dht_pk_sink(dht_pk_tx);
8082

8183
for &(pk, saddr) in &BOOTSTRAP_NODES {
8284
// get PK bytes of the bootstrap node

src/toxcore/dht/server/errors.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ error_kind! {
2525
#[doc = "Error indicates that sending response packet error."]
2626
#[fail(display = "Sending response error")]
2727
SendTo,
28-
#[doc = "Error indicates that received packet is not handled here."]
29-
#[fail(display = "This packet kind is not handled here error")]
30-
NotHandled,
3128
#[doc = "Error indicates that received packet's ping_id is zero."]
3229
#[fail(display = "Zero ping id error")]
3330
ZeroPingId,
@@ -40,9 +37,15 @@ error_kind! {
4037
#[doc = "Error indicates that NetCrypto is not initialized."]
4138
#[fail(display = "NetCrypto is not initialized error")]
4239
NetCrypto,
40+
#[doc = "Error indicates that OnionClient is not initialized."]
41+
#[fail(display = "OnionClient is not initialized error")]
42+
OnionClient,
4343
#[doc = "Error indicates that handling NetCrypto packet made an error."]
4444
#[fail(display = "Handling NetCrypto packet failed")]
4545
HandleNetCrypto,
46+
#[doc = "Error indicates that handling OnionClient packet made an error."]
47+
#[fail(display = "Handling OnionClient packet failed")]
48+
HandleOnionClient,
4649
#[doc = "Error indicates that onion or net crypto processing fails."]
4750
#[doc = "## This enum entry is temporary for onion or net crypto module's transition to failure"]
4851
#[fail(display = "Onion or NetCrypto related error")]

0 commit comments

Comments
 (0)