-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP Rust bindings for libknet and libnozzle
Not integrated into the main build system yet
- Loading branch information
1 parent
6d5ef32
commit 3a61498
Showing
21 changed files
with
7,270 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,3 +58,5 @@ xml-*/ | |
doxyxml | ||
*.3 | ||
cov* | ||
*/target/* | ||
*/Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[package] | ||
name = "rust-kronosnet" | ||
version = "0.1.0" | ||
authors = ["Christine Caulfield <ccaulfie@redhat.com>"] | ||
edition = "2018" | ||
readme = "README.md" | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/chrissie-c/rust-kronosnet" | ||
description = "Rust bindings for Kronosnet libraries" | ||
categories = ["api-bindings"] | ||
keywords = ["cluster", "high-availability"] | ||
|
||
[dependencies] | ||
bitflags = "1.2.1" | ||
lazy_static = "1.4.0" | ||
os_socketaddr = "0.2.0" | ||
libc = "0.2.93" | ||
|
||
[build-dependencies] | ||
pkg-config = "0.3" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
extern crate pkg_config; | ||
|
||
fn main() { | ||
if let Err(e) = pkg_config::probe_library("libknet") { | ||
match e { | ||
pkg_config::Error::Failure { .. } => panic! ( | ||
"Pkg-config failed - usually this is because knet development headers are not installed.\n\n\ | ||
For Fedora users:\n# dnf install libknet1-devel\n\n\ | ||
For Debian/Ubuntu users:\n# apt-get install libknet1-dev\n\n\ | ||
pkg_config details:\n{}", | ||
e | ||
), | ||
_ => panic!("{}", e) | ||
} | ||
} | ||
|
||
if let Err(e) = pkg_config::probe_library("libnozzle") { | ||
match e { | ||
pkg_config::Error::Failure { .. } => panic! ( | ||
"Pkg-config failed - usually this is because knet development headers are not installed.\n\n\ | ||
For Fedora users:\n# dnf install libnozzle1-devel\n\n\ | ||
For Debian/Ubuntu users:\n# apt-get install libnozzle1-dev\n\n\ | ||
pkg_config details:\n{}", | ||
e | ||
), | ||
_ => panic!("{}", e) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# | ||
# Regerate the FFI bindings in src/sys from the current Corosync headers | ||
# | ||
regen() | ||
{ | ||
bindgen \ | ||
--size_t-is-usize \ | ||
--no-recursive-whitelist \ | ||
--no-prepend-enum-name \ | ||
--no-layout-tests \ | ||
--no-doc-comments \ | ||
--generate functions,types,vars \ | ||
--fit-macro-constant-types \ | ||
--whitelist-var=$2.* \ | ||
--whitelist-type=.* \ | ||
--whitelist-function=*. \ | ||
../../$1.h -o src/sys/$1.rs | ||
} | ||
|
||
|
||
regen libknet KNET |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
//! This crate provides access to the kronosnet libknet | ||
//! from Rust. They are a fairly thin layer around the actual API calls but with Rust data types | ||
//! and iterators. | ||
//! | ||
//! No more information about knet itself will be provided here, it is expected that if | ||
//! you feel you need access to the knet API calls, you know what they do :) | ||
//! | ||
//! # Example | ||
//! extern crate rust_kronosnet as kronosnet; | ||
//! use kronosnet::libknet as knet; | ||
//! use std::net::{SocketAddr, IpAddr,Ipv4Addr}; | ||
//! use std::thread::spawn; | ||
//! use std::sync::mpsc::Receiver; | ||
//! use std::sync::mpsc::channel; | ||
//! use std::io::{Result, ErrorKind, Error}; | ||
//! use std::{thread, time}; | ||
//! | ||
//! const CHANNEL: i8 = 1; | ||
|
||
//! pub fn main() -> Result<()> | ||
//! { | ||
//! let host_id = knet::HostId::new(1); | ||
//! let other_host_id = knet::HostId::new(2); | ||
//! | ||
//! let (log_sender, log_receiver) = channel::<knet::LogMsg>(); | ||
//! spawn(move || logging_thread(log_receiver)); | ||
//! | ||
//! let knet_handle = match knet::handle_new(&our_hostid, Some(log_sender), | ||
//! knet::LogLevel::Debug, knet::HandleFlags::NONE) { | ||
//! Ok(h) => h, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! }; | ||
//! | ||
//! match knet::host_add(knet_handle, &other_hostid) { | ||
//! Ok(_) => {}, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! } | ||
//! match knet::link_set_config(knet_handle, &other_hostid, 0, | ||
//! knet::TransportId::Udp, | ||
//! &SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8000+(our_hostid.to_u16())), | ||
//! &SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8000+(other_hostid.to_u16())), | ||
//! knet::LinkFlags::NONE) { | ||
//! Ok(_) => {}, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! } | ||
//! match knet::handle_add_datafd(knet_handle, 0, CHANNEL) { | ||
//! Ok(_) => { | ||
//! }, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! } | ||
//! | ||
//! match knet::handle_crypto_rx_clear_traffic(knet_handle, knet::RxClearTraffic::Allow) { | ||
//! Ok(_) => {}, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! } | ||
//! | ||
//! match knet::link_set_enable(knet_handle, &other_hostid, 0, true) { | ||
//! Ok(_) => {}, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! } | ||
//! | ||
//! match knet::handle_set_fwd(knet_handle, true) { | ||
//! Ok(_) => {}, | ||
//! Err(e) => { | ||
//! return Err(e); | ||
//! } | ||
//! } | ||
//! | ||
//! Ok() | ||
//! } | ||
//! | ||
|
||
|
||
mod sys; | ||
pub mod libknet; | ||
|
||
#[macro_use] | ||
extern crate lazy_static; | ||
#[macro_use] | ||
extern crate bitflags; | ||
|
||
use std::os::raw::c_char; | ||
use std::ptr::copy_nonoverlapping; | ||
use std::ffi::CString; | ||
use std::io::{Error, Result, ErrorKind}; | ||
|
||
|
||
// Quick & dirty u8 to boolean | ||
fn u8_to_bool(val: u8) -> bool | ||
{ | ||
if val == 0 {false} else {true} | ||
} | ||
|
||
fn u32_to_bool(val: u32) -> bool | ||
{ | ||
if val == 0 {false} else {true} | ||
} | ||
|
||
// General internal routine to copy bytes from a C array into a Rust String | ||
fn string_from_bytes(bytes: *const ::std::os::raw::c_char, max_length: usize) -> Result<String> | ||
{ | ||
let mut newbytes = Vec::<u8>::new(); | ||
newbytes.resize(max_length, 0u8); | ||
|
||
unsafe { | ||
// We need to fully copy it, not shallow copy it. | ||
// Messy casting on both parts of the copy here to get it to work on both signed | ||
// and unsigned char machines | ||
copy_nonoverlapping(bytes as *mut i8, newbytes.as_mut_ptr() as *mut i8, max_length); | ||
} | ||
|
||
// Get length of the string in old-fashioned style | ||
let mut length: usize = 0; | ||
let mut count : usize = 0; | ||
for i in &newbytes { | ||
if *i == 0 && length == 0 { | ||
length = count; | ||
break; | ||
} | ||
count += 1; | ||
} | ||
|
||
// Cope with an empty string | ||
if length == 0 { | ||
return Ok(String::new()); | ||
} | ||
|
||
let cs = CString::new(&newbytes[0..length as usize])?; | ||
|
||
// This is just to convert the error type | ||
match cs.into_string() { | ||
Ok(s) => Ok(s), | ||
Err(_) => Err(Error::new(ErrorKind::Other, "Cannot convert to String")), | ||
} | ||
} | ||
|
||
// As below but always returns a string even if there was an error doing the conversion | ||
fn string_from_bytes_safe(bytes: *const ::std::os::raw::c_char, max_length: usize) -> String | ||
{ | ||
match string_from_bytes(bytes, max_length) { | ||
Ok(s) => s, | ||
Err(_)=> "".to_string() | ||
} | ||
} | ||
|
||
fn string_to_bytes(s: &String, bytes: &mut [c_char]) ->Result<()> | ||
{ | ||
let c_name = match CString::new(s.as_str()) { | ||
Ok(n) => n, | ||
Err(_) => return Err(Error::new(ErrorKind::Other, "Rust conversion error")), | ||
}; | ||
|
||
if c_name.as_bytes().len() > bytes.len() { | ||
return Err(Error::new(ErrorKind::Other, "String too long")); | ||
} | ||
unsafe { | ||
// NOTE param order is 'wrong-way round' from C | ||
copy_nonoverlapping(c_name.as_ptr(), bytes.as_mut_ptr(), bytes.len()); | ||
} | ||
Ok(()) | ||
} |
Oops, something went wrong.