protocol: add C bindings for Connector
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
		@ -13,6 +13,7 @@ crate-type = ['lib', 'cdylib']
 | 
				
			|||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
chrono = "0.4"
 | 
					chrono = "0.4"
 | 
				
			||||||
endian_trait = "0.6"
 | 
					endian_trait = "0.6"
 | 
				
			||||||
 | 
					errno = "0.2"
 | 
				
			||||||
failure = "0.1"
 | 
					failure = "0.1"
 | 
				
			||||||
libc = "0.2"
 | 
					libc = "0.2"
 | 
				
			||||||
openssl = "0.10"
 | 
					openssl = "0.10"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										145
									
								
								proxmox-protocol/src/c_connector.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								proxmox-protocol/src/c_connector.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					//! C API for the `Connector`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::ffi::CStr;
 | 
				
			||||||
 | 
					use std::os::raw::{c_char, c_int};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::Connector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[inline(always)]
 | 
				
			||||||
 | 
					fn with_errno<T>(err: c_int, value: T) -> T {
 | 
				
			||||||
 | 
					    errno::set_errno(errno::Errno(err));
 | 
				
			||||||
 | 
					    value
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[inline]
 | 
				
			||||||
 | 
					fn checkstr(ptr: *const c_char) -> Option<String> {
 | 
				
			||||||
 | 
					    if ptr.is_null() {
 | 
				
			||||||
 | 
					        return None;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let cstr = unsafe { CStr::from_ptr(ptr) };
 | 
				
			||||||
 | 
					    match cstr.to_str() {
 | 
				
			||||||
 | 
					        Ok(s) => Some(s.to_string()),
 | 
				
			||||||
 | 
					        Err(_) => None,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[inline(always)]
 | 
				
			||||||
 | 
					fn wrap_buildcall<F>(me: *mut Connector, func: F)
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    F: FnOnce(Connector) -> Connector,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    let me = unsafe { &mut *me };
 | 
				
			||||||
 | 
					    let moved_me = std::mem::replace(me, unsafe { std::mem::uninitialized() });
 | 
				
			||||||
 | 
					    std::mem::forget(std::mem::replace(me, func(moved_me)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Create a connector object.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns a valid pointer or `NULL` on error, with `errno` set.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Errors:
 | 
				
			||||||
 | 
					///   * `EINVAL`: a required parameter was `NULL` or contained invalid bytes.
 | 
				
			||||||
 | 
					#[no_mangle]
 | 
				
			||||||
 | 
					pub extern "C" fn proxmox_connector_new(
 | 
				
			||||||
 | 
					    user: *const c_char,
 | 
				
			||||||
 | 
					    server: *const c_char,
 | 
				
			||||||
 | 
					    store: *const c_char,
 | 
				
			||||||
 | 
					) -> *mut Connector {
 | 
				
			||||||
 | 
					    let (user, server, store) = match (checkstr(user), checkstr(server), checkstr(store)) {
 | 
				
			||||||
 | 
					        (Some(user), Some(server), Some(store)) => (user, server, store),
 | 
				
			||||||
 | 
					        _ => return with_errno(libc::EINVAL, std::ptr::null_mut()),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Box::leak(Box::new(Connector::new(user, server, store)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// If a connector is not required anymore and has not been used up via a call to
 | 
				
			||||||
 | 
					/// `proxmox_connector_connect`, this can be used to free the associated resources.
 | 
				
			||||||
 | 
					#[no_mangle]
 | 
				
			||||||
 | 
					pub extern "C" fn proxmox_connector_drop(me: *mut Connector) {
 | 
				
			||||||
 | 
					    unsafe { Box::from_raw(me) };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Use a password
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns `0` on success, a negative `errno` value on error.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Errors:
 | 
				
			||||||
 | 
					///   * `EINVAL`: a required parameter was `NULL` or contained invalid bytes.
 | 
				
			||||||
 | 
					#[no_mangle]
 | 
				
			||||||
 | 
					pub extern "C" fn proxmox_connector_set_password(
 | 
				
			||||||
 | 
					    me: *mut Connector,
 | 
				
			||||||
 | 
					    password: *const c_char,
 | 
				
			||||||
 | 
					) -> c_int {
 | 
				
			||||||
 | 
					    let password = match checkstr(password) {
 | 
				
			||||||
 | 
					        Some(pw) =>  pw,
 | 
				
			||||||
 | 
					        _ => return -libc::EINVAL,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wrap_buildcall(me, move |me| me.password(password));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Use an existing ticket.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns `0` on success, a negative `errno` value on error.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Errors:
 | 
				
			||||||
 | 
					///   * `EINVAL`: a required parameter was `NULL` or contained invalid bytes.
 | 
				
			||||||
 | 
					#[no_mangle]
 | 
				
			||||||
 | 
					pub extern "C" fn proxmox_connector_set_ticket(
 | 
				
			||||||
 | 
					    me: *mut Connector,
 | 
				
			||||||
 | 
					    ticket: *const c_char,
 | 
				
			||||||
 | 
					    token: *const c_char,
 | 
				
			||||||
 | 
					) -> c_int {
 | 
				
			||||||
 | 
					    let (ticket, token) = match (checkstr(ticket), checkstr(token)) {
 | 
				
			||||||
 | 
					        (Some(ticket), Some(token)) => (ticket, token),
 | 
				
			||||||
 | 
					        _ => return -libc::EINVAL,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wrap_buildcall(me, move |me| me.ticket(ticket, token));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Change whether certificate validation should be used on the connector.
 | 
				
			||||||
 | 
					#[no_mangle]
 | 
				
			||||||
 | 
					pub extern "C" fn proxmox_connector_set_certificate_validation(me: *mut Connector, on: bool) {
 | 
				
			||||||
 | 
					    let me = unsafe { &mut *me };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wrap_buildcall(me, move |me| me.certificate_validation(on));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Initiate the connection. This consumes the Connector, invalidating the pointer to it!
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns a `ProxmoxBackup*`, or `NULL` on error.
 | 
				
			||||||
 | 
					#[no_mangle]
 | 
				
			||||||
 | 
					pub extern "C" fn proxmox_connector_connect(
 | 
				
			||||||
 | 
					    me: *mut Connector,
 | 
				
			||||||
 | 
					) -> *mut crate::c_client::CClient {
 | 
				
			||||||
 | 
					    let boxed = unsafe { Box::from_raw(me) };
 | 
				
			||||||
 | 
					    let me = *boxed;
 | 
				
			||||||
 | 
					    match me.do_connect() {
 | 
				
			||||||
 | 
					        Ok(stream) => {
 | 
				
			||||||
 | 
					            let mut client = crate::c_client::make_c_compatible_client(stream);
 | 
				
			||||||
 | 
					            match client.wait_for_handshake() {
 | 
				
			||||||
 | 
					                Ok(true) => crate::c_client::make_c_client(client),
 | 
				
			||||||
 | 
					                Ok(false) => {
 | 
				
			||||||
 | 
					                    // This is a synchronous blocking connection, so this should be impossible:
 | 
				
			||||||
 | 
					                    eprintln!("proxmox backup protocol error handshake did not complete?");
 | 
				
			||||||
 | 
					                    std::ptr::null_mut()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Err(err) => {
 | 
				
			||||||
 | 
					                    eprintln!("error during handshake with backup server: {}", err);
 | 
				
			||||||
 | 
					                    std::ptr::null_mut()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(err) => {
 | 
				
			||||||
 | 
					            eprintln!("error connecting to backup server: {}", err);
 | 
				
			||||||
 | 
					            std::ptr::null_mut()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -21,3 +21,4 @@ pub use types::*;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub mod c_chunker;
 | 
					pub mod c_chunker;
 | 
				
			||||||
pub mod c_client;
 | 
					pub mod c_client;
 | 
				
			||||||
 | 
					pub mod c_connector;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user