use std::sync::mpsc::{channel}; use std::ffi::{CString}; use sovrin::api::agent::{ sovrin_agent_add_identity, sovrin_agent_close_connection, sovrin_agent_close_listener, sovrin_agent_connect, sovrin_agent_listen, sovrin_agent_remove_identity, sovrin_agent_send, }; use sovrin::api::ErrorCode; use utils::callback::CallbackUtils; use utils::timeout::TimeoutUtils; pub struct AgentUtils {} impl AgentUtils { pub fn connect(pool_handle: i32, wallet_handle: i32, sender_did: &str, receiver_did: &str, on_msg: Option>) -> Result { let (sender, receiver) = channel(); let closure = Box::new(move |err, connection_handle| { sender.send((err, connection_handle)).unwrap(); }); let (cmd_connect, cb) = CallbackUtils::closure_to_agent_connect_cb(closure); let (cb_id, msg_cb) = CallbackUtils::closure_to_agent_message_cb(Box::new(move |conn_handle, err, msg| { info!("On connection {} received (with error {:?}) agent message (SRV->CLI): {}", conn_handle, err, msg); if let Some(ref on_msg) = on_msg { on_msg(conn_handle, msg); } })); //TODO make as parameter? let err = sovrin_agent_connect(cmd_connect, pool_handle, wallet_handle, CString::new(sender_did).unwrap().as_ptr(), CString::new(receiver_did).unwrap().as_ptr(), cb, msg_cb); if err != ErrorCode::Success { return Err(err); } let (err, conn_handle) = receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); if err != ErrorCode::Success { return Err(err); } CallbackUtils::closure_map_ids(cb_id, conn_handle); Ok(conn_handle) } pub fn listen(endpoint: &str, on_connect: Option>, on_msg: Option>) -> Result { let (sender, receiver) = channel(); let on_msg = Box::new(move |conn_handle, err, msg| { info!("On connection {} received (with error {:?}) agent message (CLI->SRV): {}", conn_handle, err, msg); if let Some(ref on_msg) = on_msg { on_msg(conn_handle, msg); } }); let (on_msg_cb_id, on_msg) = CallbackUtils::closure_to_agent_message_cb(on_msg); let on_connect = Box::new(move |listener_handle, err, conn_handle, sender_did, receiver_did| { if let Some(ref on_connect) = on_connect { on_connect(listener_handle, conn_handle); } CallbackUtils::closure_map_ids(on_msg_cb_id, conn_handle); info!("New connection {} on listener {}, err {:?}, sender DID {}, receiver DID {}", conn_handle, listener_handle, err, sender_did, receiver_did); }); let (on_connect_cb_id, on_connect) = CallbackUtils::closure_to_agent_connected_cb(on_connect); let cb = Box::new(move |err, listener_handle| sender.send((err, listener_handle)).unwrap()); let (cmd_id, cb) = CallbackUtils::closure_to_agent_listen_cb(cb); let res = sovrin_agent_listen(cmd_id, CString::new(endpoint).unwrap().as_ptr(), cb, on_connect, on_msg); if res != ErrorCode::Success { return Err(res); } let (res, listener_handle) = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); CallbackUtils::closure_map_ids(on_connect_cb_id, listener_handle); if res != ErrorCode::Success { return Err(res); } Ok(listener_handle) } pub fn add_identity(listener_handle: i32, pool_handle: i32, wallet_handle: i32, did: &str) -> Result<(), ErrorCode> { let (sender, receiver) = channel(); let (cmd_id, cb) = CallbackUtils::closure_to_agent_add_identity_cb( Box::new(move |err_code| sender.send(err_code).unwrap()) ); let res = sovrin_agent_add_identity(cmd_id, listener_handle, pool_handle, wallet_handle, CString::new(did).unwrap().as_ptr(), cb); if res != ErrorCode::Success { return Err(res); } let res = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); if res != ErrorCode::Success { return Err(res) } Ok(()) } pub fn rm_identity(listener_handle: i32, wallet_handle: i32, did: &str) -> Result<(), ErrorCode> { let (sender, receiver) = channel(); let (cmd_id, cb) = CallbackUtils::closure_to_agent_rm_identity_cb( Box::new(move |err_code| sender.send(err_code).unwrap()) ); let res = sovrin_agent_remove_identity(cmd_id, listener_handle, wallet_handle, CString::new(did).unwrap().as_ptr(), cb); if res != ErrorCode::Success { return Err(res); } let res = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); if res != ErrorCode::Success { return Err(res) } Ok(()) } pub fn send(conn_handle: i32, msg: &str) -> Result<(), ErrorCode> { let (send_sender, send_receiver) = channel(); let (send_cmd_id, send_cb) = CallbackUtils::closure_to_agent_send_cb( Box::new(move |err_code| send_sender.send(err_code).unwrap()) ); let res = sovrin_agent_send(send_cmd_id, conn_handle, CString::new(msg).unwrap().as_ptr(), send_cb); if res != ErrorCode::Success { return Err(res); } let res = send_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap(); if res != ErrorCode::Success { return Err(res) } Ok(()) } pub fn close_connection(conn_handle: i32) -> Result<(), ErrorCode> { let (sender, receiver) = channel(); let (cmd_id, cb) = CallbackUtils::closure_to_agent_close_cb(Box::new(move |res| { sender.send(res).unwrap(); })); let res = sovrin_agent_close_connection(cmd_id, conn_handle, cb); if res != ErrorCode::Success { return Err(res); } let res = receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); if res != ErrorCode::Success { return Err(res); } Ok(()) } pub fn close_listener(listener_handle: i32) -> Result<(), ErrorCode> { let (sender, receiver) = channel(); let (cmd_id, cb) = CallbackUtils::closure_to_agent_close_cb(Box::new(move |res| { sender.send(res).unwrap(); })); let res = sovrin_agent_close_listener(cmd_id, listener_handle, cb); if res != ErrorCode::Success { return Err(res); } let res = receiver.recv_timeout(TimeoutUtils::medium_timeout()).unwrap(); if res != ErrorCode::Success { return Err(res); } Ok(()) } }