diff --git a/services/tunnelbroker/src/main.rs b/services/tunnelbroker/src/main.rs index 54c56a01d..73f457f13 100644 --- a/services/tunnelbroker/src/main.rs +++ b/services/tunnelbroker/src/main.rs @@ -1,47 +1,70 @@ pub mod amqp; pub mod config; pub mod constants; pub mod database; pub mod error; pub mod grpc; pub mod identity; pub mod notifs; pub mod websockets; +use crate::constants::ENV_APNS_CONFIG; +use crate::notifs::apns::config::APNsConfig; +use crate::notifs::apns::APNsClient; +use crate::notifs::NotifClient; use anyhow::{anyhow, Result}; use config::CONFIG; use std::str::FromStr; -use tracing::{self, Level}; +use tracing::{self, error, info, Level}; use tracing_subscriber::EnvFilter; #[tokio::main] async fn main() -> Result<()> { let filter = EnvFilter::builder() .with_default_directive(Level::INFO.into()) .with_env_var(constants::LOG_LEVEL_ENV_VAR) .from_env_lossy(); let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish(); tracing::subscriber::set_global_default(subscriber) .expect("Unable to configure tracing"); config::parse_cmdline_args()?; let aws_config = config::load_aws_config().await; let db_client = database::DatabaseClient::new(&aws_config); let amqp_connection = amqp::connect().await; let apns_config = CONFIG.apns_config.clone(); + let apns = match apns_config { + Some(config) => match APNsClient::new(&config) { + Ok(apns_client) => { + info!("APNs client created successfully"); + Some(apns_client) + } + Err(err) => { + error!("Error creating APNs client: {}", err); + None + } + }, + None => { + error!("APNs config is missing"); + None + } + }; + + let notif_client = NotifClient { apns }; + let grpc_server = grpc::run_server(db_client.clone(), &amqp_connection); let websocket_server = websockets::run_server(db_client.clone(), &amqp_connection); tokio::select! { Ok(_) = grpc_server => { Ok(()) }, Ok(_) = websocket_server => { Ok(()) }, else => { tracing::error!("A grpc or websocket server crashed."); Err(anyhow!("A grpc or websocket server crashed.")) } } } diff --git a/services/tunnelbroker/src/notifs/apns/error.rs b/services/tunnelbroker/src/notifs/apns/error.rs index 10f41f1d4..72d97d3f9 100644 --- a/services/tunnelbroker/src/notifs/apns/error.rs +++ b/services/tunnelbroker/src/notifs/apns/error.rs @@ -1,12 +1,13 @@ use derive_more::{Display, Error, From}; #[derive(Debug, From, Display, Error)] pub enum Error { JWTError, + ReqwestError(reqwest::Error), } impl From for Error { fn from(_: jsonwebtoken::errors::Error) -> Self { Self::JWTError } } diff --git a/services/tunnelbroker/src/notifs/apns/mod.rs b/services/tunnelbroker/src/notifs/apns/mod.rs index b6327b0e1..118f6dccd 100644 --- a/services/tunnelbroker/src/notifs/apns/mod.rs +++ b/services/tunnelbroker/src/notifs/apns/mod.rs @@ -1,12 +1,32 @@ +use crate::notifs::apns::config::APNsConfig; use crate::notifs::apns::token::APNsToken; - +use std::time::Duration; pub mod config; -mod error; +pub mod error; pub mod token; #[derive(Clone)] pub struct APNsClient { http2_client: reqwest::Client, token: APNsToken, is_prod: bool, } + +impl APNsClient { + pub fn new(config: &APNsConfig) -> Result { + let token_ttl = Duration::from_secs(60 * 55); + let token = APNsToken::new(config, token_ttl)?; + + let http2_client = reqwest::Client::builder() + .http2_prior_knowledge() + .http2_keep_alive_interval(Some(Duration::from_secs(5))) + .http2_keep_alive_while_idle(true) + .build()?; + + Ok(APNsClient { + http2_client, + token, + is_prod: config.production, + }) + } +}