diff --git a/rust/examples/dhtnode.rs b/rust/examples/dhtnode.rs index 440d52f3cf256a29024c740f0e698fafef94be3e..191f17a1b3aa1127c4103f84a9ee76872250af18 100644 --- a/rust/examples/dhtnode.rs +++ b/rust/examples/dhtnode.rs @@ -1,5 +1,23 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + extern crate opendht; -use std::ffi::CString; +// TODO remove dead code warning use std::{thread, time}; use libc::c_void; diff --git a/rust/src/blob.rs b/rust/src/blob.rs new file mode 100644 index 0000000000000000000000000000000000000000..292549b5944e1d8a691709bac913340e7d533bd0 --- /dev/null +++ b/rust/src/blob.rs @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use crate::ffi::*; + +pub use crate::ffi::Blob; + +impl Blob { + pub fn data(&self) -> DataView { + unsafe { + dht_blob_get_data(self) + } + } +} + +impl Drop for Blob { + fn drop(&mut self) { + unsafe { + dht_blob_delete(&mut *self) + } + } +} \ No newline at end of file diff --git a/rust/src/crypto.rs b/rust/src/crypto.rs new file mode 100644 index 0000000000000000000000000000000000000000..e873d4e125b7f86cb9865f6d07743405f15e34b5 --- /dev/null +++ b/rust/src/crypto.rs @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use crate::ffi::*; +use std::ffi::CString; + +impl PublicKey { + pub fn new() -> Box<PublicKey> { + unsafe { + Box::from_raw(dht_publickey_new()) + } + } + + pub fn unpack(&mut self, data: Vec<u8>) -> i32 { + unsafe { + dht_publickey_unpack(&mut *self, data.as_ptr(), data.len()) + } + } + + pub fn pack(&mut self, data: &str) -> i32 { + let data = CString::new(data).unwrap(); + unsafe { + dht_publickey_pack(&mut *self, + data.as_ptr(), + data.as_bytes().len()) + } + } + + pub fn id(&self) -> InfoHash { + unsafe { + dht_publickey_get_id(self) + } + } + + pub fn long_id(&self) -> PkId { + unsafe { + dht_publickey_get_long_id(self) + } + } + + pub fn check_signature(&self, data: &str, signature: &str) -> bool { + let data = CString::new(data).unwrap(); + let signature = CString::new(signature).unwrap(); + unsafe { + dht_publickey_check_signature(self, + data.as_ptr(), data.as_bytes().len(), + signature.as_ptr(), signature.as_bytes().len()) + } + } + + pub fn encrypt(&self, data: &str) -> Box<Blob> { + let data = CString::new(data).unwrap(); + unsafe { + Box::from_raw(dht_publickey_encrypt(self, + data.as_ptr(), data.as_bytes().len())) + } + } +} + +impl Drop for PublicKey { + fn drop(&mut self) { + unsafe { + dht_publickey_delete(&mut *self) + } + } +} + +impl PrivateKey { + pub fn new(key_length_bits: u32) -> Box<PrivateKey> { + unsafe { + Box::from_raw(dht_privatekey_generate(key_length_bits)) + } + } + + pub fn import(data: &str, password: &str) -> Box<PrivateKey> { + let password = CString::new(password).unwrap(); + unsafe { + Box::from_raw(dht_privatekey_import(data.as_ptr(), + data.as_bytes().len(), password.as_ptr())) + } + } + + pub fn public_key(&self) -> Box<PublicKey> { + unsafe { + Box::from_raw(dht_privatekey_get_publickey(self)) + } + } + +} + +impl Drop for PrivateKey { + fn drop(&mut self) { + unsafe { + dht_privatekey_delete(&mut *self) + } + } +} \ No newline at end of file diff --git a/rust/src/dhtrunner.rs b/rust/src/dhtrunner.rs new file mode 100644 index 0000000000000000000000000000000000000000..61738ce2346d2364538bc4934704d4f661bba7e5 --- /dev/null +++ b/rust/src/dhtrunner.rs @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use crate::ffi::*; +use libc::c_void; +use std::ffi::CString; +use std::fmt; + +pub use crate::ffi::{ DhtRunner, OpToken, Value }; + +impl DhtRunner { + pub fn new() -> Box<DhtRunner> { + unsafe { + Box::from_raw(dht_runner_new()) + } + } + + pub fn run(&mut self, port: u16) { + unsafe { + dht_runner_run(&mut *self, port) + } + } + + pub fn bootstrap(&mut self, host: &str, service: u16) { + unsafe { + dht_runner_bootstrap(&mut *self, + CString::new(host).unwrap().as_ptr(), + CString::new(service.to_string()).unwrap().as_ptr()) + } + } + + pub fn get(&mut self, h: &InfoHash, + get_cb: extern fn(*mut Value, *mut c_void), + done_cb: extern fn(bool, *mut c_void), + cb_user_data: *mut c_void) { + + unsafe { + dht_runner_get(&mut *self, h, get_cb, done_cb, cb_user_data) + } + } + + pub fn put(&mut self, h: &InfoHash, v: Box<Value>, + done_cb: extern fn(bool, *mut c_void), + cb_user_data: *mut c_void) { + + unsafe { + dht_runner_put(&mut *self, h, &*v, done_cb, cb_user_data) + } + } + + pub fn listen(&mut self, h: &InfoHash, + cb: extern fn(*mut Value, bool, *mut c_void), + cb_user_data: *mut c_void) -> Box<OpToken> { + unsafe { + Box::from_raw(dht_runner_listen(&mut *self, h, cb, cb_user_data)) + } + } + + pub fn cancel_listen(&mut self, h: &InfoHash, token: Box<OpToken>) { + + unsafe { + dht_runner_cancel_listen(&mut *self, h, &*token) + } + } + + pub fn shutdown(&mut self, + done_cb: extern fn(bool, *mut c_void), + cb_user_data: *mut c_void) + { + unsafe { + dht_runner_shutdown(&mut *self, done_cb, cb_user_data) + } + } +} + +impl Drop for DhtRunner { + fn drop(&mut self) { + unsafe { + dht_runner_delete(&mut *self) + } + } +} + +impl Drop for OpToken { + fn drop(&mut self) { + unsafe { + dht_op_token_delete(&mut *self) + } + } +} \ No newline at end of file diff --git a/rust/src/ffi.rs b/rust/src/ffi.rs index a4ea6da0400f0f812472446ea62dc5df8ee7e38c..4f9522ef4fdb39b16c84f82663d19f707476e1cc 100644 --- a/rust/src/ffi.rs +++ b/rust/src/ffi.rs @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + use libc::{c_char, c_int, c_uint, c_void, in_port_t, size_t}; const HASH_LEN: usize = 20; diff --git a/rust/src/infohash.rs b/rust/src/infohash.rs new file mode 100644 index 0000000000000000000000000000000000000000..31966a212b0a3461bc269ef177c2e2de4b0414ff --- /dev/null +++ b/rust/src/infohash.rs @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use crate::ffi::*; +use std::ffi::CStr; +use std::ffi::CString; +use std::fmt; + +pub use crate::ffi::InfoHash; + +impl InfoHash { + pub fn new() -> InfoHash { + InfoHash { + d: [0; 20] + } + } + + pub fn random() -> InfoHash { + let mut h = InfoHash::new(); + unsafe { + dht_infohash_random(&mut h); + } + h + } + + pub fn get(data: &str) -> InfoHash { + let mut h = InfoHash::new(); + unsafe { + let c_str = CString::new(data).unwrap(); + dht_infohash_get(&mut h, c_str.as_ptr() as *mut u8, data.len()); + } + h + } + + pub fn is_zero(&self) -> bool { + unsafe { + dht_infohash_is_zero(self) + } + } +} + +impl fmt::Display for InfoHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + let self_str = CStr::from_ptr( + dht_infohash_print(self) + ).to_str().unwrap_or(""); + write!(f, "{}", self_str) + } + } +} \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 6892fe32f8caec64b5c31950f1ee0480878b3aed..7d8db4a0d70fd685c8947bf8a024e459fc8ccee2 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,286 +1,33 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + extern crate libc; +mod blob; +pub mod crypto; +mod dhtrunner; mod ffi; -use ffi::*; -pub use ffi::{ DhtRunner, InfoHash, Value }; - -use std::fmt; -use std::ffi::CStr; -use std::ffi::CString; -use std::str; -use std::slice; -use libc::c_void; - -// TODO separate into files - -impl InfoHash { - pub fn new() -> InfoHash { - InfoHash { - d: [0; 20] - } - } - - pub fn random() -> InfoHash { - let mut h = InfoHash::new(); - unsafe { - dht_infohash_random(&mut h); - } - h - } - - pub fn get(data: &str) -> InfoHash { - let mut h = InfoHash::new(); - unsafe { - let c_str = CString::new(data).unwrap(); - dht_infohash_get(&mut h, c_str.as_ptr() as *mut u8, data.len()); - } - h - } - - pub fn is_zero(&self) -> bool { - unsafe { - dht_infohash_is_zero(self) - } - } -} - -impl fmt::Display for InfoHash { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - unsafe { - let self_str = CStr::from_ptr( - dht_infohash_print(self) - ).to_str().unwrap_or(""); - write!(f, "{}", self_str) - } - } -} - -impl Blob { - pub fn data(&self) -> DataView { - unsafe { - dht_blob_get_data(self) - } - } -} - -impl Drop for Blob { - fn drop(&mut self) { - unsafe { - dht_blob_delete(&mut *self) - } - } -} - -impl fmt::Display for PkId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - unsafe { - let self_str = CStr::from_ptr( - dht_pkid_print(self) - ).to_str().unwrap_or(""); - write!(f, "{}", self_str) - } - } -} - - -impl DhtRunner { - pub fn new() -> Box<DhtRunner> { - unsafe { - Box::from_raw(dht_runner_new()) - } - } - - pub fn run(&mut self, port: u16) { - unsafe { - dht_runner_run(&mut *self, port) - } - } - - pub fn bootstrap(&mut self, host: &str, service: u16) { - unsafe { - dht_runner_bootstrap(&mut *self, - CString::new(host).unwrap().as_ptr(), - CString::new(service.to_string()).unwrap().as_ptr()) - } - } - - pub fn get(&mut self, h: &InfoHash, - get_cb: extern fn(*mut Value, *mut c_void), - done_cb: extern fn(bool, *mut c_void), - cb_user_data: *mut c_void) { - - unsafe { - dht_runner_get(&mut *self, h, get_cb, done_cb, cb_user_data) - } - } - - pub fn put(&mut self, h: &InfoHash, v: Box<Value>, - done_cb: extern fn(bool, *mut c_void), - cb_user_data: *mut c_void) { - - unsafe { - dht_runner_put(&mut *self, h, &*v, done_cb, cb_user_data) - } - } - - pub fn listen(&mut self, h: &InfoHash, - cb: extern fn(*mut Value, bool, *mut c_void), - cb_user_data: *mut c_void) -> Box<OpToken> { - unsafe { - Box::from_raw(dht_runner_listen(&mut *self, h, cb, cb_user_data)) - } - } - - pub fn cancel_listen(&mut self, h: &InfoHash, token: Box<OpToken>) { - - unsafe { - dht_runner_cancel_listen(&mut *self, h, &*token) - } - } - - pub fn shutdown(&mut self, - done_cb: extern fn(bool, *mut c_void), - cb_user_data: *mut c_void) - { - unsafe { - dht_runner_shutdown(&mut *self, done_cb, cb_user_data) - } - } -} - -impl Drop for DhtRunner { - fn drop(&mut self) { - unsafe { - dht_runner_delete(&mut *self) - } - } -} - -impl Value { - pub fn new(data: &str) -> Box<Value> { - unsafe { - Box::from_raw(dht_value_new(data.as_bytes().as_ptr(), - data.as_bytes().len())) - } - } - - fn dataview(&self) -> DataView { - unsafe { - dht_value_get_data(self) - } - } -} - -impl Drop for Value { - fn drop(&mut self) { - unsafe { - dht_value_unref(&mut *self) - } - } -} - -impl fmt::Display for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - unsafe { - let dataview = self.dataview(); - let slice = slice::from_raw_parts(dataview.data, dataview.size); - write!(f, "{}", str::from_utf8(slice).unwrap_or("")) - } - } -} - -impl Drop for OpToken { - fn drop(&mut self) { - unsafe { - dht_op_token_delete(&mut *self) - } - } -} - -impl PublicKey { - pub fn new() -> Box<PublicKey> { - unsafe { - Box::from_raw(dht_publickey_new()) - } - } - - pub fn unpack(&mut self, data: Vec<u8>) -> i32 { - unsafe { - dht_publickey_unpack(&mut *self, data.as_ptr(), data.len()) - } - } - - // TODO slice instead of CString - pub fn pack(&mut self, data: &CString) -> i32 { - unsafe { - dht_publickey_pack(&mut *self, - data.as_ptr(), - data.as_bytes().len()) - } - } - - pub fn id(&self) -> InfoHash { - unsafe { - dht_publickey_get_id(self) - } - } - - pub fn long_id(&self) -> PkId { - unsafe { - dht_publickey_get_long_id(self) - } - } - - pub fn check_signature(&self, data: &CString, signature: &CString) -> bool { - unsafe { - dht_publickey_check_signature(self, - data.as_ptr(), data.as_bytes().len(), - signature.as_ptr(), signature.as_bytes().len()) - } - } - - pub fn encrypt(&self, data: &CString) -> Box<Blob> { - unsafe { - Box::from_raw(dht_publickey_encrypt(self, - data.as_ptr(), data.as_bytes().len())) - } - } -} - -impl Drop for PublicKey { - fn drop(&mut self) { - unsafe { - dht_publickey_delete(&mut *self) - } - } -} - -impl PrivateKey { - pub fn new(key_length_bits: u32) -> Box<PrivateKey> { - unsafe { - Box::from_raw(dht_privatekey_generate(key_length_bits)) - } - } - - pub fn import(data: &str, password: &CString) -> Box<PrivateKey> { - unsafe { - Box::from_raw(dht_privatekey_import(data.as_ptr(), - data.as_bytes().len(), password.as_ptr())) - } - } - - pub fn public_key(&self) -> Box<PublicKey> { - unsafe { - Box::from_raw(dht_privatekey_get_publickey(self)) - } - } - -} - -impl Drop for PrivateKey { - fn drop(&mut self) { - unsafe { - dht_privatekey_delete(&mut *self) - } - } -} \ No newline at end of file +mod infohash; +mod pkid; +mod value; + +pub use blob::Blob; +pub use dhtrunner::{ DhtRunner, OpToken }; +pub use infohash::InfoHash; +pub use pkid::PkId; +pub use value::{ DataView, Value }; diff --git a/rust/src/pkid.rs b/rust/src/pkid.rs new file mode 100644 index 0000000000000000000000000000000000000000..ded558ac260110e2dd544fb3f7e9b649949dbd7d --- /dev/null +++ b/rust/src/pkid.rs @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use crate::ffi::*; +use std::ffi::CStr; +use std::fmt; + +pub use crate::ffi::PkId; + +impl fmt::Display for PkId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + let self_str = CStr::from_ptr( + dht_pkid_print(self) + ).to_str().unwrap_or(""); + write!(f, "{}", self_str) + } + } +} \ No newline at end of file diff --git a/rust/src/value.rs b/rust/src/value.rs new file mode 100644 index 0000000000000000000000000000000000000000..b1dd01b820c7cdb8522f70d4a5b5b4118241bd65 --- /dev/null +++ b/rust/src/value.rs @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +use crate::ffi::*; +use std::fmt; +use std::str; +use std::slice; + +pub use crate::ffi::{DataView, Value}; + +impl Value { + pub fn new(data: &str) -> Box<Value> { + unsafe { + Box::from_raw(dht_value_new(data.as_bytes().as_ptr(), + data.as_bytes().len())) + } + } + + fn dataview(&self) -> DataView { + unsafe { + dht_value_get_data(self) + } + } +} + +impl Drop for Value { + fn drop(&mut self) { + unsafe { + dht_value_unref(&mut *self) + } + } +} + +impl fmt::Display for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + let dataview = self.dataview(); + let slice = slice::from_raw_parts(dataview.data, dataview.size); + write!(f, "{}", str::from_utf8(slice).unwrap_or("")) + } + } +}