Seregon/zftpd

Zero-copy FTP/HTTP Daemon compatible with all POSIX systems

C/11.0 KB/No license
ffi/rust/src/lib.rs
zftpd / ffi / rust / src / lib.rs
1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4 
5use std::ffi::CString;
6use std::os::raw::c_char;
7use std::ptr;
8 
9// Generate unsafe FFI bindings
10pub mod sys {
11 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
12}
13 
14/*===========================================================================*
15 * Safe Rust Idiomatic Wrappers
16 *===========================================================================*/
17 
18#[derive(Debug)]
19pub enum Error {
20 InvalidParam,
21 OutOfMemory,
22 Unknown,
23 FfiError(i32)
24}
25 
26impl From<i32> for Error {
27 fn from(err: i32) -> Self {
28 match err {
29 sys::PAL_FFI_ERR_INVALID_PARAM => Error::InvalidParam,
30 sys::PAL_FFI_ERR_OUT_OF_MEMORY => Error::OutOfMemory,
31 sys::PAL_FFI_ERR_UNKNOWN => Error::Unknown,
32 _ => Error::FfiError(err),
33 }
34 }
35}
36 
37pub type Result<T> = std::result::Result<T, Error>;
38 
39/// Memory Allocator Abstraction
40pub struct PalAlloc;
41 
42impl PalAlloc {
43 pub fn init_default() -> Result<()> {
44 let res = unsafe { sys::pal_ffi_alloc_init_default() };
45 if res == sys::PAL_FFI_OK as i32 {
46 Ok(())
47 } else {
48 Err(Error::from(res))
49 }
50 }
51 
52 pub fn malloc(size: usize) -> *mut libc::c_void {
53 unsafe { sys::pal_ffi_malloc(size as _) }
54 }
55 
56 pub fn free(ptr: *mut libc::c_void) {
57 unsafe { sys::pal_ffi_free(ptr) }
58 }
59 
60 pub fn get_arena_free_approx() -> usize {
61 unsafe { sys::pal_ffi_alloc_arena_free_approx() as usize }
62 }
63}
64 
65/// Event Loop Wrapper
66pub struct EventLoop {
67 handle: *mut libc::c_void,
68}
69 
70impl EventLoop {
71 pub fn new() -> Result<Self> {
72 let handle = unsafe { sys::pal_ffi_event_loop_create() };
73 if handle.is_null() {
74 return Err(Error::Unknown);
75 }
76 Ok(Self { handle })
77 }
78 
79 pub fn run(&self) -> Result<()> {
80 let res = unsafe { sys::pal_ffi_event_loop_run(self.handle) };
81 if res == 0 {
82 Ok(())
83 } else {
84 Err(Error::from(res))
85 }
86 }
87 
88 pub fn stop(&self) {
89 unsafe { sys::pal_ffi_event_loop_stop(self.handle) }
90 }
91}
92 
93impl Drop for EventLoop {
94 fn drop(&mut self) {
95 if !self.handle.is_null() {
96 unsafe { sys::pal_ffi_event_loop_destroy(self.handle) }
97 }
98 }
99}
100 
101/// FTP Server
102pub struct FtpServer {
103 handle: *mut libc::c_void,
104}
105 
106impl FtpServer {
107 pub fn new(bind_ip: &str, port: u16, root_path: &str) -> Result<Self> {
108 let c_ip = CString::new(bind_ip).map_err(|_| Error::InvalidParam)?;
109 let c_root = CString::new(root_path).map_err(|_| Error::InvalidParam)?;
110 
111 let handle = unsafe {
112 sys::pal_ffi_ftp_server_create(
113 c_ip.as_ptr() as *const c_char,
114 port,
115 c_root.as_ptr() as *const c_char,
116 )
117 };
118 
119 if handle.is_null() {
120 return Err(Error::Unknown);
121 }
122 Ok(Self { handle })
123 }
124 
125 pub fn start(&self) -> Result<()> {
126 let res = unsafe { sys::pal_ffi_ftp_server_start(self.handle) };
127 if res == sys::PAL_FFI_OK as i32 {
128 Ok(())
129 } else {
130 Err(Error::from(res))
131 }
132 }
133 
134 pub fn is_running(&self) -> bool {
135 let res = unsafe { sys::pal_ffi_ftp_server_is_running(self.handle) };
136 res == 1
137 }
138 
139 pub fn active_sessions(&self) -> u32 {
140 unsafe { sys::pal_ffi_ftp_server_get_active_sessions(self.handle) }
141 }
142 
143 pub fn stop(&self) {
144 unsafe { sys::pal_ffi_ftp_server_stop(self.handle) }
145 }
146}
147 
148impl Drop for FtpServer {
149 fn drop(&mut self) {
150 if !self.handle.is_null() {
151 unsafe { sys::pal_ffi_ftp_server_destroy(self.handle) }
152 }
153 }
154}
155 
156/// HTTP Server
157pub struct HttpServer {
158 handle: *mut libc::c_void,
159}
160 
161impl HttpServer {
162 pub fn new(loop_ctx: &EventLoop, port: u16) -> Result<Self> {
163 let handle = unsafe { sys::pal_ffi_http_server_create(loop_ctx.handle, port) };
164 if handle.is_null() {
165 return Err(Error::Unknown);
166 }
167 Ok(Self { handle })
168 }
169}
170 
171impl Drop for HttpServer {
172 fn drop(&mut self) {
173 if !self.handle.is_null() {
174 unsafe { sys::pal_ffi_http_server_destroy(self.handle) }
175 }
176 }
177}
178