Skip to content

Commit e257fce

Browse files
committed
WIP RESET
did not copy tests/js/udx_js/ which was js copy of udx-native also tests/js/node_modules_for_tests which as a copy of node modules I was using temporarily fyor tests
1 parent debcc3b commit e257fce

File tree

5 files changed

+209
-21
lines changed

5 files changed

+209
-21
lines changed

.rustfmt.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# groups 'use' statements by crate
2+
imports_granularity = "crate"
3+
# formats code within doc tests
4+
# requires: cargo +nightly fmt (otherwise rustfmt will warn, but pass)
5+
#format_code_in_doc_comments = true

src/crypto/handshake.rs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ pub mod handshake_constants {
2525
/// [`HandshakePattern`] used by the hypercore-protocol crate.
2626
pub const PROTOCOL_PATTERN: HandshakePattern = HandshakePattern::XX;
2727
/// Noise protocol name used in hypercore-protocol crate.
28-
pub const PROTOCOL_NAME: &str = "Noise_XX_Ed25519_ChaChaPoly_BLAKE2b";
28+
pub const PROTOCOL_NAME: &str =
29+
"NNoise_XX_Ed25519_ChaChaPoly_BLAKE2boise_XX_Ed25519_ChaChaPoly_BLAKE2b";
2930

3031
/// Get a Noise protocol name from a handshake pattern
3132
pub fn name_from_pattern(pattern: &HandshakePattern) -> Result<&'static str, snow::Error> {
@@ -52,6 +53,8 @@ const REPLICATE_RESPONDER: [u8; 32] = [
5253
];
5354

5455
#[derive(Debug, Clone, Default)]
56+
/// The thing created by [`Handshake`] which is used to encrypt and decrypt. NB while it is created
57+
/// at the beginning of the handshake, it is not "ready" until the handshake completes.
5558
pub struct HandshakeResult {
5659
pub(crate) is_initiator: bool,
5760
pub(crate) local_pubkey: Vec<u8>,
@@ -100,11 +103,13 @@ impl HandshakeResult {
100103
}
101104
}
102105

103-
/// Noise handshake for establishing secure connections
106+
/// Object for holding the data needed Noise handshake protocol. The resulting object can be used
107+
/// for encryption.
104108
#[derive(Debug)]
105109
pub struct Handshake {
106110
result: HandshakeResult,
107-
state: HandshakeState,
111+
/// Internal state of the handshake
112+
pub state: HandshakeState,
108113
payload: Vec<u8>,
109114
tx_buf: Vec<u8>,
110115
rx_buf: Vec<u8>,
@@ -114,8 +119,9 @@ pub struct Handshake {
114119

115120
impl Handshake {
116121
#[instrument]
117-
pub(crate) fn new(is_initiator: bool) -> Result<Self> {
118-
let (state, local_pubkey) = build_handshake_state(is_initiator).map_err(map_err)?;
122+
/// Build a [`Handshake`]
123+
pub fn new(is_initiator: bool, config: &HandshakeConfig) -> Result<Self> {
124+
let (state, local_pubkey) = new_handshake_state(is_initiator, config).map_err(map_err)?;
119125

120126
let payload = vec![];
121127
let result = HandshakeResult {
@@ -134,7 +140,13 @@ impl Handshake {
134140
})
135141
}
136142

137-
pub(crate) fn start_raw(&mut self) -> Result<Option<Vec<u8>>> {
143+
/// Set the payload for the next handshake message
144+
pub fn set_payload(&mut self, payload: Vec<u8>) {
145+
self.payload = payload;
146+
}
147+
148+
/// Start the handshake and return the initial message (for initiators)
149+
pub fn start_raw(&mut self) -> Result<Option<Vec<u8>>> {
138150
if self.is_initiator() {
139151
let tx_len = self.send()?;
140152
Ok(Some(self.tx_buf[..tx_len].to_vec()))
@@ -151,6 +163,7 @@ impl Handshake {
151163
self.result.is_initiator
152164
}
153165

166+
#[instrument(skip_all, err)]
154167
fn recv(&mut self, msg: &[u8]) -> Result<usize> {
155168
self.state
156169
.read_message(msg, &mut self.rx_buf)
@@ -162,8 +175,9 @@ impl Handshake {
162175
.map_err(map_err)
163176
}
164177

165-
#[instrument(skip_all, fields(is_initiator = %self.result.is_initiator))]
166-
pub(crate) fn read_raw(&mut self, msg: &[u8]) -> Result<Option<Vec<u8>>> {
178+
#[instrument(skip_all, fields(is_initiator = %self.result.is_initiator), err)]
179+
/// Read in a handshake message
180+
pub fn read_raw(&mut self, msg: &[u8]) -> Result<Option<Vec<u8>>> {
167181
// eprintln!("hs read len {}", msg.len());
168182
if self.complete() {
169183
return Err(Error::new(ErrorKind::Other, "Handshake read after finish"));
@@ -179,7 +193,9 @@ impl Handshake {
179193
return Ok(Some(wrapped));
180194
}
181195

182-
let tx_buf = if self.is_initiator() {
196+
let tx_buf = if self.is_initiator() && !self.state.is_handshake_finished()
197+
/* when IK pattern */
198+
{
183199
let tx_len = self.send()?;
184200
let wrapped = self.tx_buf[..tx_len].to_vec();
185201
Some(wrapped)
@@ -189,9 +205,11 @@ impl Handshake {
189205

190206
let split = self.state.dangerously_get_raw_split();
191207
if self.is_initiator() {
208+
dbg!();
192209
self.result.split_tx = split.0;
193210
self.result.split_rx = split.1;
194211
} else {
212+
dbg!();
195213
self.result.split_tx = split.1;
196214
self.result.split_rx = split.0;
197215
}
@@ -215,6 +233,7 @@ impl Handshake {
215233
}
216234

217235
/// Configuration for creating a handshake with specific parameters
236+
// TODO this should take a crate::crypto::Keypair
218237
#[derive(Debug, Clone)]
219238
pub struct HandshakeConfig {
220239
/// The noise handshake pattern to use (XX, IK, etc.)
@@ -246,13 +265,8 @@ impl Default for HandshakeConfig {
246265
}
247266
}
248267

249-
fn build_handshake_state(
250-
is_initiator: bool,
251-
) -> std::result::Result<(HandshakeState, Vec<u8>), SnowError> {
252-
build_handshake_state_with_config(is_initiator, &HandshakeConfig::default())
253-
}
254-
255-
fn build_handshake_state_with_config(
268+
// TODO make this infallible. It's currently
269+
fn new_handshake_state(
256270
is_initiator: bool,
257271
config: &HandshakeConfig,
258272
) -> std::result::Result<(HandshakeState, Vec<u8>), SnowError> {
@@ -292,7 +306,7 @@ fn build_handshake_state_with_config(
292306
}
293307

294308
// Set remote public key for IK pattern initiator
295-
if is_initiator && config.pattern == handshake_constants::PROTOCOL_PATTERN {
309+
if (is_initiator) && (config.pattern) == handshake_constants::DHT_PATTERN {
296310
if let Some(ref remote_key) = config.remote_public_key {
297311
builder = builder.remote_public_key(remote_key);
298312
} else {

src/noise.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ where
260260
first_message = true;
261261
assert!(!self.is_initiator);
262262
warn!(initiator = %self.is_initiator, "Encrypted state was reset");
263-
let mut handshake = Handshake::new(self.is_initiator)?;
263+
let mut handshake = Handshake::new(self.is_initiator, &Default::default())?;
264264
let _ = handshake.start_raw()?;
265265
self.step = Step::Handshake(Box::new(handshake));
266266
}
@@ -481,7 +481,7 @@ fn maybe_init(step: &mut Step, is_initiator: bool) -> Result<Option<Vec<u8>>> {
481481
return Ok(None);
482482
}
483483
trace!(initiator = %is_initiator, "Init, state {step:?}");
484-
let mut handshake = Handshake::new(is_initiator)?;
484+
let mut handshake = Handshake::new(is_initiator, &Default::default())?;
485485
let out = handshake.start_raw()?;
486486
*step = Step::Handshake(Box::new(handshake));
487487
Ok(out)

tests/js/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ pub fn cleanup() {
3030
}
3131

3232
pub fn install() {
33-
let status = Command::new("npm")
33+
let status = Command::new("cp")
3434
.current_dir("tests/js")
35-
.args(["install"])
35+
.args(["-r", "node_modules_for_tests", "node_modules"])
3636
.status()
3737
.expect("Unable to run npm install");
3838
assert_eq!(

tests/udx.rs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
pub mod _util;
2+
#[path = "../src/test_utils.rs"]
3+
mod test_utils;
4+
5+
#[cfg(feature = "tokio")]
6+
use async_compat::CompatExt;
7+
use async_udx::UdxSocket;
8+
use futures::SinkExt;
9+
use futures_lite::StreamExt as _;
10+
use hypercore_protocol::{encrypted_framed_message_channel, NoiseEvent};
11+
use rusty_nodejs_repl::{integration_utils::git_root, join_paths, Config, Error, Repl};
12+
use std::path::PathBuf;
13+
use tokio::join;
14+
15+
const PATH_TO_UDX_NODE_MODULES: &str = "./tests/js/udx_js/node_modules/";
16+
17+
fn lossy(x: &[u8]) -> String {
18+
String::from_utf8_lossy(x).to_string()
19+
}
20+
21+
fn udx_node_modules() -> Result<PathBuf, Error> {
22+
Ok(join_paths!(git_root()?, &PATH_TO_UDX_NODE_MODULES).into())
23+
}
24+
25+
async fn setup_repl() -> Result<Repl, Error> {
26+
let mut conf = Config::build().unwrap();
27+
conf.imports.push("UDX = require('udx-native');".into());
28+
conf.path_to_node_modules = Some(format!("{}", udx_node_modules()?.display()));
29+
conf.before.push(
30+
"
31+
write = process.stdout.write.bind(process.stdout);
32+
writeJson = x => process.stdout.write(JSON.stringify(x));
33+
"
34+
.into(),
35+
);
36+
conf.start().await
37+
}
38+
39+
#[tokio::test]
40+
async fn encrypted_over_udx() -> Result<(), Box<dyn std::error::Error>> {
41+
let a = UdxSocket::bind("127.0.0.1:0")?;
42+
let b = UdxSocket::bind("127.0.0.1:0")?;
43+
let audxstr = a.connect(b.local_addr()?, 1, 2)?;
44+
let budxstr = b.connect(a.local_addr()?, 2, 1)?;
45+
let mut astr = encrypted_framed_message_channel(false, audxstr.compat());
46+
let mut bstr = encrypted_framed_message_channel(true, budxstr.compat());
47+
let (_, _) = join!(astr.establish_encryption(), bstr.establish_encryption());
48+
49+
astr.send(b"a hello".to_vec()).await?;
50+
bstr.send(b"b hello".to_vec()).await?;
51+
52+
if let Some(NoiseEvent::Decrypted(m)) = astr.next().await {
53+
assert_eq!(m?, b"b hello");
54+
}
55+
if let Some(NoiseEvent::Decrypted(m)) = bstr.next().await {
56+
assert_eq!(m?, b"a hello");
57+
}
58+
Ok(())
59+
}
60+
61+
#[tokio::test]
62+
async fn rust_rust_socket() -> Result<(), Box<dyn std::error::Error>> {
63+
let a = UdxSocket::bind("127.0.0.1:0")?;
64+
let b = UdxSocket::bind("127.0.0.1:0")?;
65+
a.send(b.local_addr()?, b"hello");
66+
let (_from, msg) = b.recv().await?;
67+
assert_eq!(msg, b"hello");
68+
Ok(())
69+
}
70+
71+
#[tokio::test]
72+
async fn js_to_rs_socket() -> Result<(), Box<dyn std::error::Error>> {
73+
let mut repl = setup_repl().await?;
74+
75+
let a = UdxSocket::bind("127.0.0.1:0")?;
76+
let port = a.local_addr()?.port();
77+
let _res = repl
78+
.run(format!(
79+
"
80+
u = new UDX();
81+
socket = u.createSocket();
82+
socket.bind(0);
83+
84+
resolve = null
85+
reject = null
86+
result = new Promise((res, rej) => {{
87+
resolve = res;
88+
reject = rej;
89+
}});
90+
socket.send(Buffer.from('hello'), {port})
91+
",
92+
))
93+
.await?;
94+
let (_addr, res) = a.recv().await?;
95+
assert_eq!(&lossy(&res), "hello");
96+
Ok(())
97+
}
98+
99+
#[tokio::test]
100+
async fn rs_to_js_socket() -> Result<(), Box<dyn std::error::Error>> {
101+
let a = UdxSocket::bind("127.0.0.1:0")?;
102+
let mut repl = setup_repl().await?;
103+
104+
let port: usize = repl
105+
.json_run(
106+
"
107+
u = new UDX();
108+
socket = u.createSocket();
109+
socket.bind(0);
110+
111+
resolve = null
112+
reject = null
113+
result = new Promise((res, rej) => {
114+
resolve = res;
115+
reject = rej;
116+
});
117+
118+
socket.on('message', (msg) => {
119+
write(msg.toString());
120+
resolve()
121+
socket.close()
122+
})
123+
124+
writeJson(socket.address().port);
125+
",
126+
)
127+
.await?;
128+
let addr = format!("127.0.0.1:{port}");
129+
a.send(addr.parse()?, b"hello");
130+
let res = repl.run("await result;").await?;
131+
assert_eq!(&lossy(&res), "hello");
132+
Ok(())
133+
}
134+
135+
#[tokio::test]
136+
async fn js_to_js_socket() -> Result<(), Box<dyn std::error::Error>> {
137+
let mut repl = setup_repl().await?;
138+
139+
let res = repl
140+
.run(
141+
"
142+
u = new UDX()
143+
a = u.createSocket()
144+
b = u.createSocket()
145+
146+
resolve = null
147+
reject = null
148+
result = new Promise((res, rej) => {
149+
resolve = res;
150+
reject = rej;
151+
});
152+
153+
b.on('message', function (message) {
154+
write(message.toString())
155+
resolve()
156+
a.close()
157+
b.close()
158+
})
159+
160+
b.bind(0)
161+
a.send(Buffer.from('hello'), b.address().port)
162+
",
163+
)
164+
.await?;
165+
assert!(res.is_empty());
166+
let res = repl.run("await result").await?;
167+
assert_eq!(&lossy(&res), "hello");
168+
Ok(())
169+
}

0 commit comments

Comments
 (0)