2022-06-08 01:31:05 +00:00
|
|
|
use crate::api_tracing_layer::*;
|
2022-02-07 02:18:42 +00:00
|
|
|
use crate::attachment_manager::*;
|
2022-10-30 23:29:31 +00:00
|
|
|
use crate::crypto::Crypto;
|
2022-02-07 02:18:42 +00:00
|
|
|
use crate::veilid_api::*;
|
|
|
|
use crate::veilid_config::*;
|
|
|
|
use crate::xx::*;
|
|
|
|
|
2022-07-11 12:37:08 +00:00
|
|
|
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) + Send + Sync>;
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-03-09 03:32:12 +00:00
|
|
|
struct ServicesContext {
|
2022-02-07 02:18:42 +00:00
|
|
|
pub config: VeilidConfig,
|
2022-02-15 18:40:17 +00:00
|
|
|
pub update_callback: UpdateCallback,
|
2022-03-09 03:32:12 +00:00
|
|
|
|
|
|
|
pub protected_store: Option<ProtectedStore>,
|
|
|
|
pub table_store: Option<TableStore>,
|
|
|
|
pub block_store: Option<BlockStore>,
|
|
|
|
pub crypto: Option<Crypto>,
|
|
|
|
pub attachment_manager: Option<AttachmentManager>,
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-03-09 03:32:12 +00:00
|
|
|
impl ServicesContext {
|
|
|
|
pub fn new_empty(config: VeilidConfig, update_callback: UpdateCallback) -> Self {
|
|
|
|
Self {
|
|
|
|
config,
|
|
|
|
update_callback,
|
|
|
|
protected_store: None,
|
|
|
|
table_store: None,
|
|
|
|
block_store: None,
|
|
|
|
crypto: None,
|
|
|
|
attachment_manager: None,
|
2022-02-09 14:47:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-09 03:32:12 +00:00
|
|
|
pub fn new_full(
|
|
|
|
config: VeilidConfig,
|
2022-02-09 14:47:36 +00:00
|
|
|
update_callback: UpdateCallback,
|
2022-03-09 03:32:12 +00:00
|
|
|
protected_store: ProtectedStore,
|
|
|
|
table_store: TableStore,
|
|
|
|
block_store: BlockStore,
|
|
|
|
crypto: Crypto,
|
|
|
|
attachment_manager: AttachmentManager,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
config,
|
|
|
|
update_callback,
|
|
|
|
protected_store: Some(protected_store),
|
|
|
|
table_store: Some(table_store),
|
|
|
|
block_store: Some(block_store),
|
|
|
|
crypto: Some(crypto),
|
|
|
|
attachment_manager: Some(attachment_manager),
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
2022-02-09 14:47:36 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(err, skip_all)]
|
2022-07-10 21:36:50 +00:00
|
|
|
pub async fn startup(&mut self) -> EyreResult<()> {
|
2022-03-11 12:35:41 +00:00
|
|
|
info!("Veilid API starting up");
|
2022-03-09 03:32:12 +00:00
|
|
|
|
2022-07-01 16:13:52 +00:00
|
|
|
info!("init api tracing");
|
|
|
|
ApiTracingLayer::init(self.update_callback.clone()).await;
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
// Set up protected store
|
2022-03-09 03:32:12 +00:00
|
|
|
trace!("init protected store");
|
|
|
|
let protected_store = ProtectedStore::new(self.config.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
if let Err(e) = protected_store.init().await {
|
2022-03-09 03:32:12 +00:00
|
|
|
self.shutdown().await;
|
2022-07-10 21:36:50 +00:00
|
|
|
return Err(e);
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
2022-03-09 03:32:12 +00:00
|
|
|
self.protected_store = Some(protected_store.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
// Init node id from config now that protected store is set up
|
2022-03-09 03:32:12 +00:00
|
|
|
if let Err(e) = self.config.init_node_id(protected_store.clone()).await {
|
|
|
|
self.shutdown().await;
|
2022-07-10 21:36:50 +00:00
|
|
|
return Err(e).wrap_err("init node id failed");
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set up tablestore
|
2022-03-09 03:32:12 +00:00
|
|
|
trace!("init table store");
|
|
|
|
let table_store = TableStore::new(self.config.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
if let Err(e) = table_store.init().await {
|
2022-03-09 03:32:12 +00:00
|
|
|
self.shutdown().await;
|
2022-07-10 21:36:50 +00:00
|
|
|
return Err(e);
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
2022-03-09 03:32:12 +00:00
|
|
|
self.table_store = Some(table_store.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
// Set up crypto
|
2022-03-09 03:32:12 +00:00
|
|
|
trace!("init crypto");
|
|
|
|
let crypto = Crypto::new(self.config.clone(), table_store.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
if let Err(e) = crypto.init().await {
|
2022-03-09 03:32:12 +00:00
|
|
|
self.shutdown().await;
|
2022-07-10 21:36:50 +00:00
|
|
|
return Err(e);
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
2022-03-09 03:32:12 +00:00
|
|
|
self.crypto = Some(crypto.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
// Set up block store
|
2022-03-09 03:32:12 +00:00
|
|
|
trace!("init block store");
|
|
|
|
let block_store = BlockStore::new(self.config.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
if let Err(e) = block_store.init().await {
|
2022-03-09 03:32:12 +00:00
|
|
|
self.shutdown().await;
|
2022-07-10 21:36:50 +00:00
|
|
|
return Err(e);
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
2022-03-09 03:32:12 +00:00
|
|
|
self.block_store = Some(block_store.clone());
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
// Set up attachment manager
|
2022-03-09 03:32:12 +00:00
|
|
|
trace!("init attachment manager");
|
2022-03-24 14:14:50 +00:00
|
|
|
let update_callback = self.update_callback.clone();
|
2022-10-30 23:29:31 +00:00
|
|
|
let attachment_manager = AttachmentManager::new(
|
|
|
|
self.config.clone(),
|
|
|
|
protected_store,
|
|
|
|
table_store,
|
|
|
|
block_store,
|
|
|
|
crypto,
|
|
|
|
);
|
2022-03-24 14:14:50 +00:00
|
|
|
if let Err(e) = attachment_manager.init(update_callback).await {
|
2022-03-09 03:32:12 +00:00
|
|
|
self.shutdown().await;
|
2022-07-10 21:36:50 +00:00
|
|
|
return Err(e);
|
2022-03-09 03:32:12 +00:00
|
|
|
}
|
|
|
|
self.attachment_manager = Some(attachment_manager);
|
|
|
|
|
2022-03-11 12:35:41 +00:00
|
|
|
info!("Veilid API startup complete");
|
2022-03-09 03:32:12 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip_all)]
|
2022-03-09 03:32:12 +00:00
|
|
|
pub async fn shutdown(&mut self) {
|
2022-03-11 12:35:41 +00:00
|
|
|
info!("Veilid API shutting down");
|
2022-03-09 03:32:12 +00:00
|
|
|
|
|
|
|
if let Some(attachment_manager) = &mut self.attachment_manager {
|
|
|
|
trace!("terminate attachment manager");
|
|
|
|
attachment_manager.terminate().await;
|
|
|
|
}
|
|
|
|
if let Some(block_store) = &mut self.block_store {
|
|
|
|
trace!("terminate block store");
|
2022-02-07 02:18:42 +00:00
|
|
|
block_store.terminate().await;
|
2022-03-09 03:32:12 +00:00
|
|
|
}
|
|
|
|
if let Some(crypto) = &mut self.crypto {
|
|
|
|
trace!("terminate crypto");
|
2022-02-07 02:18:42 +00:00
|
|
|
crypto.terminate().await;
|
2022-03-09 03:32:12 +00:00
|
|
|
}
|
|
|
|
if let Some(table_store) = &mut self.table_store {
|
|
|
|
trace!("terminate table store");
|
2022-02-07 02:18:42 +00:00
|
|
|
table_store.terminate().await;
|
2022-03-09 03:32:12 +00:00
|
|
|
}
|
|
|
|
if let Some(protected_store) = &mut self.protected_store {
|
|
|
|
trace!("terminate protected store");
|
2022-02-07 02:18:42 +00:00
|
|
|
protected_store.terminate().await;
|
2022-03-09 03:32:12 +00:00
|
|
|
}
|
|
|
|
|
2022-03-11 12:35:41 +00:00
|
|
|
info!("Veilid API shutdown complete");
|
2022-03-09 03:32:12 +00:00
|
|
|
|
|
|
|
// api logger terminate is idempotent
|
2022-06-08 01:31:05 +00:00
|
|
|
ApiTracingLayer::terminate().await;
|
2022-03-09 03:32:12 +00:00
|
|
|
|
|
|
|
// send final shutdown update
|
2022-03-11 12:35:41 +00:00
|
|
|
(self.update_callback)(VeilidUpdate::Shutdown);
|
2022-03-09 03:32:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
///
|
|
|
|
pub struct VeilidCoreContext {
|
|
|
|
pub config: VeilidConfig,
|
|
|
|
pub update_callback: UpdateCallback,
|
|
|
|
// Services
|
|
|
|
pub protected_store: ProtectedStore,
|
|
|
|
pub table_store: TableStore,
|
|
|
|
pub block_store: BlockStore,
|
|
|
|
pub crypto: Crypto,
|
|
|
|
pub attachment_manager: AttachmentManager,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VeilidCoreContext {
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(err, skip_all)]
|
2022-03-09 03:32:12 +00:00
|
|
|
async fn new_with_config_callback(
|
|
|
|
update_callback: UpdateCallback,
|
|
|
|
config_callback: ConfigCallback,
|
|
|
|
) -> Result<VeilidCoreContext, VeilidAPIError> {
|
|
|
|
// Set up config from callback
|
|
|
|
trace!("setup config with callback");
|
|
|
|
let mut config = VeilidConfig::new();
|
2022-11-16 17:49:53 +00:00
|
|
|
config.setup(config_callback, update_callback.clone())?;
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-03-09 03:32:12 +00:00
|
|
|
Self::new_common(update_callback, config).await
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-06-11 22:47:58 +00:00
|
|
|
#[instrument(err, skip_all)]
|
2022-03-09 03:32:12 +00:00
|
|
|
async fn new_with_config_json(
|
|
|
|
update_callback: UpdateCallback,
|
|
|
|
config_json: String,
|
|
|
|
) -> Result<VeilidCoreContext, VeilidAPIError> {
|
|
|
|
// Set up config from callback
|
|
|
|
trace!("setup config with json");
|
|
|
|
let mut config = VeilidConfig::new();
|
2022-11-16 17:49:53 +00:00
|
|
|
config.setup_from_json(config_json, update_callback.clone())?;
|
2022-03-09 03:32:12 +00:00
|
|
|
Self::new_common(update_callback, config).await
|
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-06-11 22:47:58 +00:00
|
|
|
#[instrument(err, skip_all)]
|
2022-03-09 03:32:12 +00:00
|
|
|
async fn new_common(
|
|
|
|
update_callback: UpdateCallback,
|
|
|
|
config: VeilidConfig,
|
|
|
|
) -> Result<VeilidCoreContext, VeilidAPIError> {
|
|
|
|
cfg_if! {
|
|
|
|
if #[cfg(target_os = "android")] {
|
2022-08-22 23:25:00 +00:00
|
|
|
if crate::intf::utils::android::ANDROID_GLOBALS.lock().is_none() {
|
2022-03-09 03:32:12 +00:00
|
|
|
error!("Android globals are not set up");
|
|
|
|
return Err(VeilidAPIError::Internal { message: "Android globals are not set up".to_owned() });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-03-09 03:32:12 +00:00
|
|
|
let mut sc = ServicesContext::new_empty(config.clone(), update_callback);
|
2022-07-10 21:36:50 +00:00
|
|
|
sc.startup().await.map_err(VeilidAPIError::generic)?;
|
2022-02-15 18:40:17 +00:00
|
|
|
|
2022-03-09 03:32:12 +00:00
|
|
|
Ok(VeilidCoreContext {
|
|
|
|
update_callback: sc.update_callback,
|
|
|
|
config: sc.config,
|
|
|
|
protected_store: sc.protected_store.unwrap(),
|
|
|
|
table_store: sc.table_store.unwrap(),
|
|
|
|
block_store: sc.block_store.unwrap(),
|
|
|
|
crypto: sc.crypto.unwrap(),
|
|
|
|
attachment_manager: sc.attachment_manager.unwrap(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip_all)]
|
2022-03-09 03:32:12 +00:00
|
|
|
async fn shutdown(self) {
|
|
|
|
let mut sc = ServicesContext::new_full(
|
|
|
|
self.config.clone(),
|
|
|
|
self.update_callback.clone(),
|
|
|
|
self.protected_store,
|
|
|
|
self.table_store,
|
|
|
|
self.block_store,
|
|
|
|
self.crypto,
|
|
|
|
self.attachment_manager,
|
|
|
|
);
|
|
|
|
sc.shutdown().await;
|
2022-02-07 02:18:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-06-28 03:46:29 +00:00
|
|
|
lazy_static::lazy_static! {
|
|
|
|
static ref INITIALIZED: AsyncMutex<bool> = AsyncMutex::new(false);
|
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(err, skip_all)]
|
2022-02-09 14:47:36 +00:00
|
|
|
pub async fn api_startup(
|
|
|
|
update_callback: UpdateCallback,
|
|
|
|
config_callback: ConfigCallback,
|
|
|
|
) -> Result<VeilidAPI, VeilidAPIError> {
|
|
|
|
// See if we have an API started up already
|
|
|
|
let mut initialized_lock = INITIALIZED.lock().await;
|
|
|
|
if *initialized_lock {
|
|
|
|
return Err(VeilidAPIError::AlreadyInitialized);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create core context
|
|
|
|
let context =
|
|
|
|
VeilidCoreContext::new_with_config_callback(update_callback, config_callback).await?;
|
|
|
|
|
|
|
|
// Return an API object around our context
|
|
|
|
let veilid_api = VeilidAPI::new(context);
|
|
|
|
|
|
|
|
*initialized_lock = true;
|
|
|
|
|
|
|
|
Ok(veilid_api)
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(err, skip(update_callback))]
|
2022-02-09 14:47:36 +00:00
|
|
|
pub async fn api_startup_json(
|
|
|
|
update_callback: UpdateCallback,
|
|
|
|
config_json: String,
|
|
|
|
) -> Result<VeilidAPI, VeilidAPIError> {
|
2022-02-07 02:18:42 +00:00
|
|
|
// See if we have an API started up already
|
|
|
|
let mut initialized_lock = INITIALIZED.lock().await;
|
|
|
|
if *initialized_lock {
|
|
|
|
return Err(VeilidAPIError::AlreadyInitialized);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create core context
|
2022-02-09 14:47:36 +00:00
|
|
|
let context = VeilidCoreContext::new_with_config_json(update_callback, config_json).await?;
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
// Return an API object around our context
|
|
|
|
let veilid_api = VeilidAPI::new(context);
|
|
|
|
|
|
|
|
*initialized_lock = true;
|
|
|
|
|
|
|
|
Ok(veilid_api)
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip_all)]
|
2022-03-09 03:32:12 +00:00
|
|
|
pub(crate) async fn api_shutdown(context: VeilidCoreContext) {
|
2022-02-07 02:18:42 +00:00
|
|
|
let mut initialized_lock = INITIALIZED.lock().await;
|
|
|
|
context.shutdown().await;
|
|
|
|
*initialized_lock = false;
|
|
|
|
}
|