1use std::{borrow::Cow, sync::Arc};
71
72use crate::service::{RxJsonRpcMessage, ServiceRole, TxJsonRpcMessage};
73
74pub mod sink_stream;
75
76#[cfg(feature = "transport-async-rw")]
77pub mod async_rw;
78
79#[cfg(feature = "transport-worker")]
80pub mod worker;
81#[cfg(feature = "transport-worker")]
82pub use worker::WorkerTransport;
83
84#[cfg(feature = "transport-child-process")]
85pub mod child_process;
86#[cfg(feature = "which-command")]
87pub use child_process::which_command;
88#[cfg(feature = "transport-child-process")]
89pub use child_process::{ConfigureCommandExt, TokioChildProcess};
90
91#[cfg(feature = "transport-io")]
92pub mod io;
93#[cfg(feature = "transport-io")]
94pub use io::stdio;
95
96#[cfg(feature = "auth")]
97pub mod auth;
98#[cfg(feature = "auth-client-credentials-jwt")]
99pub use auth::JwtSigningAlgorithm;
100#[cfg(feature = "auth")]
101pub use auth::{
102 AuthClient, AuthError, AuthorizationManager, AuthorizationSession, AuthorizedHttpClient,
103 ClientCredentialsConfig, CredentialStore, EXTENSION_OAUTH_CLIENT_CREDENTIALS,
104 InMemoryCredentialStore, InMemoryStateStore, OAuthHttpClient, OAuthHttpClientError,
105 OAuthHttpClientFuture, OAuthHttpRedirectPolicy, OAuthHttpRequest, ScopeUpgradeConfig,
106 StateStore, StoredAuthorizationState, StoredCredentials, WWWAuthenticateParams,
107};
108
109#[cfg(feature = "transport-streamable-http-server-session")]
112pub mod streamable_http_server;
113#[cfg(all(feature = "transport-streamable-http-server", not(feature = "local")))]
114pub use streamable_http_server::tower::{StreamableHttpServerConfig, StreamableHttpService};
115
116#[cfg(feature = "transport-streamable-http-client")]
117pub mod streamable_http_client;
118#[cfg(all(unix, feature = "transport-streamable-http-client-unix-socket"))]
119pub use common::unix_socket::UnixSocketHttpClient;
120#[cfg(feature = "transport-streamable-http-client")]
121pub use streamable_http_client::StreamableHttpClientTransport;
122
123pub mod common;
125
126pub trait Transport<R>: Send
127where
128 R: ServiceRole,
129{
130 type Error: std::error::Error + Send + Sync + 'static;
131 fn name() -> Cow<'static, str> {
132 std::any::type_name::<Self>().into()
133 }
134 fn send(
140 &mut self,
141 item: TxJsonRpcMessage<R>,
142 ) -> impl Future<Output = Result<(), Self::Error>> + Send + 'static;
143
144 fn receive(&mut self) -> impl Future<Output = Option<RxJsonRpcMessage<R>>> + Send;
146
147 fn close(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send;
149}
150
151pub trait IntoTransport<R, E, A>: Send + 'static
152where
153 R: ServiceRole,
154 E: std::error::Error + Send + 'static,
155{
156 fn into_transport(self) -> impl Transport<R, Error = E> + 'static;
157}
158
159#[non_exhaustive]
160pub enum TransportAdapterIdentity {}
161impl<R, T, E> IntoTransport<R, E, TransportAdapterIdentity> for T
162where
163 T: Transport<R, Error = E> + Send + 'static,
164 R: ServiceRole,
165 E: std::error::Error + Send + Sync + 'static,
166{
167 fn into_transport(self) -> impl Transport<R, Error = E> + 'static {
168 self
169 }
170}
171
172pub struct OneshotTransport<R>
174where
175 R: ServiceRole,
176{
177 message: Option<RxJsonRpcMessage<R>>,
178 sender: tokio::sync::mpsc::Sender<TxJsonRpcMessage<R>>,
179 termination: Arc<tokio::sync::Semaphore>,
180}
181
182impl<R> OneshotTransport<R>
183where
184 R: ServiceRole,
185{
186 pub fn new(
187 message: RxJsonRpcMessage<R>,
188 ) -> (Self, tokio::sync::mpsc::Receiver<TxJsonRpcMessage<R>>) {
189 let (sender, receiver) = tokio::sync::mpsc::channel(16);
190 (
191 Self {
192 message: Some(message),
193 sender,
194 termination: Arc::new(tokio::sync::Semaphore::new(0)),
195 },
196 receiver,
197 )
198 }
199}
200
201impl<R> Transport<R> for OneshotTransport<R>
202where
203 R: ServiceRole,
204{
205 type Error = tokio::sync::mpsc::error::SendError<TxJsonRpcMessage<R>>;
206
207 fn send(
208 &mut self,
209 item: TxJsonRpcMessage<R>,
210 ) -> impl Future<Output = Result<(), Self::Error>> + Send + 'static {
211 let sender = self.sender.clone();
212 let terminate = matches!(item, TxJsonRpcMessage::<R>::Response(_))
213 || matches!(item, TxJsonRpcMessage::<R>::Error(_));
214 let termination = self.termination.clone();
215 async move {
216 sender.send(item).await?;
217 if terminate {
218 termination.add_permits(1);
219 }
220 Ok(())
221 }
222 }
223
224 async fn receive(&mut self) -> Option<RxJsonRpcMessage<R>> {
225 if let Some(msg) = self.message.take() {
226 return Some(msg);
227 }
228 let _ = self.termination.acquire().await;
229 None
230 }
231
232 fn close(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send {
233 self.message.take();
234 std::future::ready(Ok(()))
235 }
236}
237
238#[derive(Debug, thiserror::Error)]
239#[error("Transport [{transport_name}] error: {error}")]
240#[non_exhaustive]
241pub struct DynamicTransportError {
242 pub transport_name: Cow<'static, str>,
243 pub transport_type_id: std::any::TypeId,
244 #[source]
245 pub error: Box<dyn std::error::Error + Send + Sync>,
246}
247
248impl DynamicTransportError {
249 pub fn new<T: Transport<R> + 'static, R: ServiceRole>(e: T::Error) -> Self {
250 Self {
251 transport_name: T::name(),
252 transport_type_id: std::any::TypeId::of::<T>(),
253 error: Box::new(e),
254 }
255 }
256
257 pub fn from_parts(
263 transport_name: impl Into<Cow<'static, str>>,
264 transport_type_id: std::any::TypeId,
265 error: Box<dyn std::error::Error + Send + Sync>,
266 ) -> Self {
267 Self {
268 transport_name: transport_name.into(),
269 transport_type_id,
270 error,
271 }
272 }
273
274 pub fn downcast<T: Transport<R> + 'static, R: ServiceRole>(self) -> Result<T::Error, Self> {
275 if !self.is::<T, R>() {
276 Err(self)
277 } else {
278 Ok(self
279 .error
280 .downcast::<T::Error>()
281 .map(|e| *e)
282 .expect("type is checked"))
283 }
284 }
285 pub fn is<T: Transport<R> + 'static, R: ServiceRole>(&self) -> bool {
286 self.error.is::<T::Error>() && self.transport_type_id == std::any::TypeId::of::<T>()
287 }
288}