1use core::cell::Cell;
25use core::fmt;
26use core::future::Future;
27use core::marker::PhantomData;
28use core::{any, mem};
29
30use alloc::boxed::Box;
31use alloc::string::{String, ToString};
32use alloc::sync::Arc;
33use alloc::vec::Vec;
34
35use std::collections::HashMap;
36use std::collections::hash_map::Entry;
37use std::sync::Mutex;
38use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU32, Ordering};
39
40use bytes::Bytes;
41use rand::prelude::*;
42use rand::rngs::SmallRng;
43use slab::Slab;
44use tokio::sync::{mpsc, oneshot, watch};
45use tokio::time::{Duration, Instant};
46
47use crate::api::{self, ChannelId, DecodeBody, Event, Format, MessageId};
48use crate::format;
49
50const INITIAL_TIMEOUT: Duration = Duration::from_millis(250);
52const MAX_TIMEOUT: Duration = Duration::from_millis(4000);
54const MAX_FUZZ: u64 = 50;
56const DEFAULT_SEED: u64 = 0xdeadbeef;
58
59#[non_exhaustive]
61pub struct EmptyBody;
62
63#[non_exhaustive]
65pub struct EmptyCallback;
66
67#[cfg_attr(not(feature = "tungstenite029"), allow(dead_code))]
75pub(crate) enum Message {
76 Text,
79 Binary(Bytes),
81 Ping,
85 Pong,
87 Close,
89}
90
91pub(crate) mod sealed_socket {
92 pub trait Sealed {}
93}
94
95pub(crate) trait SocketImpl
96where
97 Self: 'static + Send + Sized + self::sealed_socket::Sealed,
98{
99 #[doc(hidden)]
100 type Error;
101
102 #[doc(hidden)]
107 fn recv(&mut self) -> impl Future<Output = Option<Result<Message, Self::Error>>> + Send + '_;
108
109 #[doc(hidden)]
111 fn send(&mut self, data: &[u8]) -> impl Future<Output = Result<(), Self::Error>> + Send + '_;
112
113 #[doc(hidden)]
115 fn close(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send + '_;
116}
117
118pub(crate) mod sealed_client {
119 pub trait Sealed {}
120}
121
122pub trait ClientImpl
133where
134 Self: 'static + Copy + Sized + self::sealed_client::Sealed,
135{
136 #[doc(hidden)]
137 type Error: 'static + Send + Sync + core::error::Error;
138
139 #[doc(hidden)]
140 #[allow(private_bounds)]
141 type Socket: SocketImpl<Error = Self::Error>;
142
143 #[doc(hidden)]
144 fn connect(url: &str) -> impl Future<Output = Result<Self::Socket, Self::Error>> + Send;
145}
146
147pub fn connect<T>(url: impl AsRef<str>) -> ServiceBuilder<T, EmptyCallback>
149where
150 T: ClientImpl,
151{
152 ServiceBuilder {
153 url: url.as_ref().to_string(),
154 on_error: EmptyCallback,
155 reconnect: true,
156 seed: DEFAULT_SEED,
157 format: Format::DEFAULT,
158 _marker: PhantomData,
159 }
160}
161
162#[derive(Debug, PartialEq, Eq, Clone, Copy)]
166#[non_exhaustive]
167pub enum State {
168 Open,
170 Closed,
172}
173
174impl State {
175 #[inline]
186 pub fn is_open(&self) -> bool {
187 matches!(self, Self::Open)
188 }
189}
190
191pub trait Callback<I>
193where
194 Self: 'static + Send + Sync,
195{
196 fn call(&self, input: I);
198}
199
200impl<I> Callback<I> for EmptyCallback {
201 #[inline]
202 fn call(&self, _: I) {}
203}
204
205impl<F, I> Callback<I> for F
206where
207 F: 'static + Send + Sync + Fn(I),
208{
209 #[inline]
210 fn call(&self, input: I) {
211 self(input)
212 }
213}
214
215#[derive(Debug)]
217pub struct Error {
218 kind: ErrorKind,
219}
220
221impl Error {
222 #[inline]
223 const fn new(kind: ErrorKind) -> Self {
224 Self { kind }
225 }
226
227 #[inline]
240 pub fn is_empty_packet(&self) -> bool {
241 matches!(self.kind, ErrorKind::EmptyPacket)
242 }
243
244 #[inline]
250 pub fn is_not_connected(&self) -> bool {
251 matches!(self.kind, ErrorKind::NotConnected)
252 }
253
254 #[inline]
262 pub fn as_server_error(&self) -> Option<&str> {
263 match &self.kind {
264 ErrorKind::Server(message) => Some(message),
265 _ => None,
266 }
267 }
268
269 #[inline]
271 pub fn message(message: impl fmt::Display) -> Self {
272 Self::new(ErrorKind::Message(message.to_string()))
273 }
274
275 #[inline]
276 fn server(message: impl fmt::Display) -> Self {
277 Self::new(ErrorKind::Server(message.to_string()))
278 }
279
280 #[inline]
281 fn transport<E>(error: E) -> Self
282 where
283 E: 'static + Send + Sync + core::error::Error,
284 {
285 Self::new(ErrorKind::Transport(Box::new(error)))
286 }
287
288 #[inline]
289 fn decode_response_header(error: format::Error) -> Self {
290 Self::new(ErrorKind::DecodeResponseHeader(error))
291 }
292
293 #[inline]
294 fn decode_error_message(error: format::Error) -> Self {
295 Self::new(ErrorKind::DecodeErrorMessage(error))
296 }
297
298 #[inline]
299 fn decode_packet(error: format::Error) -> Self {
300 Self::new(ErrorKind::DecodePacket(error))
301 }
302
303 #[inline]
304 fn encoding_header(error: format::Error) -> Self {
305 Self::new(ErrorKind::EncodingHeader(error))
306 }
307
308 #[inline]
309 fn encoding_body(error: format::Error) -> Self {
310 Self::new(ErrorKind::EncodingBody(error))
311 }
312}
313
314#[derive(Debug)]
315enum ErrorKind {
316 EmptyPacket,
317 NotConnected,
318 Message(String),
319 Server(String),
320 Transport(Box<dyn core::error::Error + Send + Sync>),
321 DecodeResponseHeader(format::Error),
322 DecodeErrorMessage(format::Error),
323 DecodePacket(format::Error),
324 EncodingHeader(format::Error),
325 EncodingBody(format::Error),
326}
327
328impl fmt::Display for Error {
329 #[inline]
330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331 match &self.kind {
332 ErrorKind::EmptyPacket => write!(f, "Packet is empty"),
333 ErrorKind::NotConnected => write!(f, "Client is not connected"),
334 ErrorKind::Message(message) => write!(f, "{message}"),
335 ErrorKind::Server(message) => write!(f, "Server error: {message}"),
336 ErrorKind::Transport(..) => write!(f, "Error in underlying transport"),
337 ErrorKind::DecodeResponseHeader(..) => {
338 write!(f, "Encoding error when decoding response header")
339 }
340 ErrorKind::DecodeErrorMessage(..) => {
341 write!(f, "Encoding error when decoding error response")
342 }
343 ErrorKind::DecodePacket(..) => write!(f, "Encoding error when decoding packet"),
344 ErrorKind::EncodingHeader(..) => write!(f, "Encoding error when encoding header"),
345 ErrorKind::EncodingBody(..) => write!(f, "Encoding error when encoding body"),
346 }
347 }
348}
349
350impl core::error::Error for Error {
351 #[inline]
352 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
353 match &self.kind {
354 ErrorKind::Transport(error) => Some(&**error),
355 ErrorKind::DecodeResponseHeader(error) => Some(error),
356 ErrorKind::DecodeErrorMessage(error) => Some(error),
357 ErrorKind::DecodePacket(error) => Some(error),
358 ErrorKind::EncodingHeader(error) => Some(error),
359 ErrorKind::EncodingBody(error) => Some(error),
360 _ => None,
361 }
362 }
363}
364
365type Result<T, E = Error> = core::result::Result<T, E>;
366
367type Broadcasts = HashMap<MessageId, Slab<mpsc::UnboundedSender<Result<RawPacket>>>>;
369
370enum Command {
372 Send {
374 serial: u32,
375 data: Vec<u8>,
376 pending: Pending,
377 },
378 Disconnect { channel: ChannelId },
380 Close,
382}
383
384enum Pending {
386 Negotiate { format: Format },
388 Request {
390 id: MessageId,
391 reply: oneshot::Sender<Result<RawPacket>>,
392 },
393 Channel {
395 reply: oneshot::Sender<Result<ChannelId>>,
396 },
397}
398
399impl Pending {
400 #[inline]
401 fn error(self, error: Error) {
402 match self {
403 Pending::Negotiate { .. } => {
404 tracing::debug!("Format negotiation failed: {error}");
405 }
406 Pending::Request { reply, .. } => {
407 _ = reply.send(Err(error));
408 }
409 Pending::Channel { reply } => {
410 _ = reply.send(Err(error));
411 }
412 }
413 }
414}
415
416struct Shared {
418 tx: mpsc::UnboundedSender<Command>,
419 serial: AtomicU32,
420 state: watch::Sender<State>,
421 broadcasts: Mutex<Broadcasts>,
422 gone: AtomicBool,
425 format: AtomicU8,
431}
432
433impl Shared {
434 #[inline]
435 fn next_serial(&self) -> u32 {
436 self.serial.fetch_add(1, Ordering::Relaxed)
437 }
438
439 #[inline]
440 fn is_open(&self) -> bool {
441 self.state.borrow().is_open()
442 }
443
444 #[inline]
446 fn format(&self) -> Format {
447 Format::from_u8(self.format.load(Ordering::Acquire)).unwrap_or(Format::DEFAULT)
448 }
449
450 #[inline]
451 fn set_format(&self, format: Format) {
452 self.format.store(format.to_u8(), Ordering::Release);
453 }
454
455 #[inline]
457 fn is_gone(&self) -> bool {
458 self.gone.load(Ordering::Acquire)
459 }
460
461 fn set_gone(&self) {
463 self.gone.store(true, Ordering::Release);
464 self.state.send_modify(|state| *state = State::Closed);
467 }
468
469 #[inline]
470 fn send(&self, command: Command) -> Result<()> {
471 if self.tx.send(command).is_err() {
472 return Err(Error::message("Client service is down"));
473 }
474
475 Ok(())
476 }
477}
478
479pub struct ServiceBuilder<T, E> {
483 url: String,
484 on_error: E,
485 reconnect: bool,
486 seed: u64,
487 format: Format,
488 _marker: PhantomData<T>,
489}
490
491impl<T, E> ServiceBuilder<T, E>
492where
493 T: ClientImpl,
494 E: Callback<Error>,
495{
496 #[inline]
502 pub fn on_error<U>(self, on_error: U) -> ServiceBuilder<T, U>
503 where
504 U: Callback<Error>,
505 {
506 ServiceBuilder {
507 url: self.url,
508 on_error,
509 reconnect: self.reconnect,
510 seed: self.seed,
511 format: self.format,
512 _marker: self._marker,
513 }
514 }
515
516 #[inline]
528 pub fn format(mut self, format: Format) -> Self {
529 self.format = format;
530 self
531 }
532
533 #[inline]
539 pub fn reconnect(mut self, reconnect: bool) -> Self {
540 self.reconnect = reconnect;
541 self
542 }
543
544 #[inline]
550 pub fn seed(mut self, seed: u64) -> Self {
551 self.seed = seed;
552 self
553 }
554
555 pub fn build(self) -> Service<T> {
559 let (tx, rx) = mpsc::unbounded_channel();
560 let (state, _) = watch::channel(State::Closed);
561
562 let shared = Arc::new(Shared {
563 tx,
564 serial: AtomicU32::new(0),
565 state,
566 broadcasts: Mutex::new(Broadcasts::new()),
567 gone: AtomicBool::new(false),
568 format: AtomicU8::new(self.format.to_u8()),
569 });
570
571 Service {
572 handle: Handle {
573 shared: shared.clone(),
574 },
575 shared,
576 rx,
577 url: self.url,
578 on_error: Box::new(self.on_error),
579 reconnect: self.reconnect,
580 socket: None,
581 pending: HashMap::new(),
582 timeout: INITIAL_TIMEOUT,
583 next_attempt: Some(Instant::now()),
584 rng: SmallRng::seed_from_u64(self.seed),
585 closed: false,
586 requested: self.format,
587 }
588 }
589}
590
591pub struct Service<T>
596where
597 T: ClientImpl,
598{
599 handle: Handle,
600 shared: Arc<Shared>,
601 rx: mpsc::UnboundedReceiver<Command>,
602 url: String,
603 on_error: Box<dyn Callback<Error>>,
604 reconnect: bool,
605 socket: Option<T::Socket>,
606 pending: HashMap<u32, Pending>,
607 timeout: Duration,
608 next_attempt: Option<Instant>,
609 rng: SmallRng,
610 closed: bool,
611 requested: Format,
614}
615
616enum Output<E> {
618 Message(Option<Result<Message, E>>),
620 Command(Option<Command>),
622 Connect,
624}
625
626impl<T> Service<T>
627where
628 T: ClientImpl,
629{
630 #[inline]
634 pub fn handle(&self) -> &Handle {
635 &self.handle
636 }
637
638 pub async fn run(&mut self) -> Result<()> {
651 while !self.closed {
652 let output = {
653 let rx = &mut self.rx;
654
655 match &mut self.socket {
656 Some(socket) => {
657 tokio::select! {
658 message = socket.recv() => Output::Message(message),
659 command = rx.recv() => Output::Command(command),
660 }
661 }
662 None => match self.next_attempt {
663 Some(deadline) => {
664 tokio::select! {
665 _ = tokio::time::sleep_until(deadline) => Output::Connect,
666 command = rx.recv() => Output::Command(command),
667 }
668 }
669 None => Output::Command(rx.recv().await),
670 },
671 }
672 };
673
674 match output {
675 Output::Connect => {
676 self.connect().await;
677 }
678 Output::Command(command) => {
679 let Some(command) = command else {
680 break;
683 };
684
685 self.command(command).await;
686 }
687 Output::Message(message) => {
688 let Some(message) = message else {
689 tracing::debug!("Connection closed by server");
690 self.disconnect().await;
691 continue;
692 };
693
694 let message = match message {
695 Ok(message) => message,
696 Err(error) => {
697 self.on_error.call(Error::transport(error));
698 self.disconnect().await;
699 continue;
700 }
701 };
702
703 match message {
704 Message::Binary(bytes) => match self.message(bytes) {
705 Ok(Post::Negotiate) => self.send_negotiate().await,
706 Ok(Post::None) => {}
707 Err(error) => self.on_error.call(error),
708 },
709 Message::Text => {
710 self.on_error
711 .call(Error::message("Unsupported text message"));
712 self.disconnect().await;
713 }
714 Message::Ping | Message::Pong => {}
715 Message::Close => {
716 tracing::debug!("Close message received");
717 self.disconnect().await;
718 }
719 }
720 }
721 }
722 }
723
724 self.shutdown().await;
725 Ok(())
726 }
727
728 async fn connect(&mut self) {
730 tracing::debug!(url = self.url.as_str(), "Connecting");
731
732 match T::connect(&self.url).await {
733 Ok(socket) => {
734 tracing::debug!("Connection established");
735 self.socket = Some(socket);
736 self.next_attempt = None;
737 self.timeout = INITIAL_TIMEOUT;
738 }
739 Err(error) => {
740 self.on_error.call(Error::transport(error));
741 self.schedule_reconnect();
742 }
743 }
744 }
745
746 async fn disconnect(&mut self) {
748 if let Some(mut socket) = self.socket.take() {
749 _ = socket.close().await;
750 }
751
752 self.emit_state(State::Closed);
753 self.close_pending(|| Error::message("Connection closed"));
754 self.schedule_reconnect();
755 }
756
757 async fn shutdown(&mut self) {
759 if let Some(mut socket) = self.socket.take() {
760 _ = socket.close().await;
761 }
762
763 self.emit_state(State::Closed);
764 self.close_pending(|| Error::message("Client service closed"));
765 }
766
767 fn schedule_reconnect(&mut self) {
768 if !self.reconnect {
769 tracing::debug!("Reconnecting is disabled, closing service");
770 self.closed = true;
771 return;
772 }
773
774 let fuzz = self.rng.random_range(0..=MAX_FUZZ);
775
776 let timeout = self
777 .timeout
778 .saturating_add(Duration::from_millis(fuzz))
779 .min(MAX_TIMEOUT);
780
781 self.timeout = self.timeout.saturating_mul(2).min(MAX_TIMEOUT);
782 self.next_attempt = Some(Instant::now() + timeout);
783 tracing::debug!(?timeout, "Scheduling reconnect");
784 }
785
786 fn close_pending(&mut self, error: impl Fn() -> Error) {
789 for (_, pending) in self.pending.drain() {
790 pending.error(error());
791 }
792 }
793
794 fn emit_state(&mut self, state: State) {
795 self.shared.state.send_if_modified(|current| {
796 if *current == state {
797 return false;
798 }
799
800 *current = state;
801 true
802 });
803 }
804
805 async fn command(&mut self, command: Command) {
807 match command {
808 Command::Send {
809 serial,
810 data,
811 pending,
812 } => {
813 let Some(socket) = self.socket.as_mut() else {
814 pending.error(Error::new(ErrorKind::NotConnected));
815 return;
816 };
817
818 if let Err(error) = socket.send(&data).await {
819 pending.error(Error::transport(error));
820 self.disconnect().await;
821 return;
822 }
823
824 if let Some(existing) = self.pending.insert(serial, pending) {
825 existing.error(Error::message("Request cancelled"));
826 }
827 }
828 Command::Disconnect { channel } => {
829 if let Err(error) = self.send_disconnect(channel).await {
830 self.on_error.call(error);
831 }
832 }
833 Command::Close => {
834 self.closed = true;
835 }
836 }
837 }
838
839 async fn send_disconnect(&mut self, channel: ChannelId) -> Result<()> {
840 let Some(socket) = self.socket.as_mut() else {
841 return Ok(());
842 };
843
844 let mut data = Vec::new();
845
846 let header = api::RequestHeader {
847 serial: 0,
848 id: MessageId::DISCONNECT.get(),
849 format: 0,
851 channel,
852 };
853
854 format::encode_envelope(&mut data, &header).map_err(Error::encoding_header)?;
855
856 tracing::debug!(?channel, "Sending disconnect");
857
858 if let Err(error) = socket.send(&data).await {
859 let error = Error::transport(error);
860 self.disconnect().await;
861 return Err(error);
862 }
863
864 Ok(())
865 }
866
867 fn dispatch(&self, id: MessageId, value: impl Fn() -> Result<RawPacket>) {
873 let broadcasts = self
874 .shared
875 .broadcasts
876 .lock()
877 .unwrap_or_else(|e| e.into_inner());
878
879 let Some(slots) = broadcasts.get(&id) else {
880 return;
881 };
882
883 for (_, tx) in slots.iter() {
884 _ = tx.send(value());
885 }
886 }
887
888 fn body_format(header: &api::ResponseHeader) -> Result<Format> {
890 let Some(format) = Format::from_u8(header.format) else {
891 return Err(Error::message(format_args!(
892 "Server used unknown format id {} for a message body",
893 header.format
894 )));
895 };
896
897 Ok(format)
898 }
899
900 fn message(&mut self, bytes: Bytes) -> Result<Post> {
902 let mut at = 0;
903
904 let header: api::ResponseHeader =
905 format::decode_envelope(&bytes, &mut at).map_err(Error::decode_response_header)?;
906
907 if let Some(broadcast) = MessageId::new(header.broadcast) {
908 tracing::debug!(?header, "Got broadcast");
909
910 if broadcast == MessageId::SERVER_HELLO {
911 tracing::debug!("Server hello, negotiating format");
915 return Ok(Post::Negotiate);
916 }
917
918 if let Some(id) = MessageId::new(header.error) {
919 let error = match id {
920 MessageId::ERROR_MESSAGE => Self::body_format(&header)?
921 .decode(&bytes, &mut at)
922 .map_err(Error::decode_error_message)?,
923 _ => api::ErrorMessage {
924 message: "Unsupported broadcast",
925 },
926 };
927
928 self.dispatch(broadcast, || Err(Error::server(error.message)));
929 return Ok(Post::None);
930 }
931
932 let format = Self::body_format(&header)?;
933
934 let packet = RawPacket {
935 id: broadcast,
936 buf: bytes,
937 at: Cell::new(at),
938 format,
939 channel: header.channel,
940 };
941
942 self.dispatch(broadcast, || Ok(packet.clone()));
943 return Ok(Post::None);
944 }
945
946 tracing::debug!(?header, "Got response");
947
948 let Some(pending) = self.pending.remove(&header.serial) else {
949 tracing::trace!(?header.serial, "Got message with unknown serial");
952 return Ok(Post::None);
953 };
954
955 if let Some(id) = MessageId::new(header.error) {
956 let error = match id {
957 MessageId::ERROR_MESSAGE => Self::body_format(&header)?
958 .decode(&bytes, &mut at)
959 .map_err(Error::decode_error_message)?,
960 _ => api::ErrorMessage {
961 message: "Unsupported request",
962 },
963 };
964
965 match pending {
966 Pending::Negotiate { format } => {
967 self.on_error.call(Error::message(format_args!(
972 "Server rejected format `{format}` ({}), falling back to `{}`",
973 error.message,
974 Format::DEFAULT
975 )));
976
977 self.shared.set_format(Format::DEFAULT);
978 self.emit_state(State::Open);
979 }
980 pending => {
981 pending.error(Error::server(error.message));
982 }
983 }
984
985 return Ok(Post::None);
986 }
987
988 match pending {
989 Pending::Negotiate { format } => {
990 let accepted = Format::from_u8(header.format).unwrap_or(format);
993 tracing::debug!(?accepted, "Format negotiated");
994 self.shared.set_format(accepted);
995 self.emit_state(State::Open);
996 }
997 Pending::Channel { reply } => {
998 _ = reply.send(Ok(header.channel));
999 }
1000 Pending::Request { id, reply } => {
1001 let format = Self::body_format(&header)?;
1002
1003 let packet = RawPacket {
1004 id,
1005 buf: bytes,
1006 at: Cell::new(at),
1007 format,
1008 channel: header.channel,
1009 };
1010
1011 _ = reply.send(Ok(packet));
1012 }
1013 }
1014
1015 Ok(Post::None)
1016 }
1017
1018 async fn send_negotiate(&mut self) {
1021 let format = self.requested;
1022 let serial = self.shared.next_serial();
1023
1024 let header = api::RequestHeader {
1025 serial,
1026 id: MessageId::NEGOTIATE.get(),
1027 format: format.to_u8(),
1028 channel: ChannelId::NONE,
1030 };
1031
1032 let mut data = Vec::new();
1033
1034 if let Err(error) = format::encode_envelope(&mut data, &header) {
1035 self.on_error.call(Error::encoding_header(error));
1036 return;
1037 }
1038
1039 let Some(socket) = self.socket.as_mut() else {
1040 return;
1041 };
1042
1043 tracing::debug!(?format, "Requesting format");
1044
1045 if let Err(error) = socket.send(&data).await {
1046 self.on_error.call(Error::transport(error));
1047 self.disconnect().await;
1048 return;
1049 }
1050
1051 self.pending.insert(serial, Pending::Negotiate { format });
1052 }
1053}
1054
1055enum Post {
1058 None,
1060 Negotiate,
1062}
1063
1064impl<T> Drop for Service<T>
1065where
1066 T: ClientImpl,
1067{
1068 fn drop(&mut self) {
1069 self.shared.set_gone();
1070
1071 for (_, pending) in self.pending.drain() {
1072 pending.error(Error::message("Client service closed"));
1073 }
1074
1075 self.shared
1076 .broadcasts
1077 .lock()
1078 .unwrap_or_else(|e| e.into_inner())
1079 .clear();
1080 }
1081}
1082
1083impl<T> fmt::Debug for Service<T>
1084where
1085 T: ClientImpl,
1086{
1087 #[inline]
1088 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 f.debug_struct("Service")
1090 .field("url", &self.url)
1091 .field("state", &*self.shared.state.borrow())
1092 .finish_non_exhaustive()
1093 }
1094}
1095
1096#[derive(Clone)]
1100pub struct Handle {
1101 shared: Arc<Shared>,
1102}
1103
1104impl Handle {
1105 #[inline]
1107 pub fn state(&self) -> State {
1108 *self.shared.state.borrow()
1109 }
1110
1111 #[inline]
1113 pub fn is_open(&self) -> bool {
1114 self.shared.is_open()
1115 }
1116
1117 #[inline]
1124 pub fn format(&self) -> Format {
1125 self.shared.format()
1126 }
1127
1128 #[inline]
1134 pub fn on_state_change(&self) -> StateListener {
1135 StateListener {
1136 rx: self.shared.state.subscribe(),
1137 shared: self.shared.clone(),
1138 }
1139 }
1140
1141 pub async fn wait_until_open(&self) -> Result<()> {
1150 let mut listener = self.on_state_change();
1151
1152 if listener.wait_until(State::Open).await {
1153 return Ok(());
1154 }
1155
1156 Err(Error::message("Client service is down"))
1157 }
1158
1159 pub async fn channel(&self) -> Result<Channel> {
1176 if !self.shared.is_open() {
1177 return Err(Error::new(ErrorKind::NotConnected));
1178 }
1179
1180 let serial = self.shared.next_serial();
1181
1182 let header = api::RequestHeader {
1183 serial,
1184 id: MessageId::CONNECT.get(),
1185 format: 0,
1187 channel: ChannelId::NONE,
1188 };
1189
1190 let mut data = Vec::new();
1191 format::encode_envelope(&mut data, &header).map_err(Error::encoding_header)?;
1192
1193 let (reply, rx) = oneshot::channel();
1194
1195 self.shared.send(Command::Send {
1196 serial,
1197 data,
1198 pending: Pending::Channel { reply },
1199 })?;
1200
1201 let Ok(result) = rx.await else {
1202 return Err(Error::message("Client service is down"));
1203 };
1204
1205 Ok(Channel {
1206 shared: self.shared.clone(),
1207 id: result?,
1208 })
1209 }
1210
1211 #[inline]
1215 pub fn request(&self) -> RequestBuilder<'_, EmptyBody> {
1216 RequestBuilder {
1217 shared: &self.shared,
1218 channel: ChannelId::NONE,
1219 body: EmptyBody,
1220 }
1221 }
1222
1223 pub fn on_broadcast<T>(&self) -> Listener<T>
1234 where
1235 T: api::Broadcast,
1236 {
1237 let (tx, rx) = mpsc::unbounded_channel();
1238
1239 let index = {
1240 let mut broadcasts = self
1241 .shared
1242 .broadcasts
1243 .lock()
1244 .unwrap_or_else(|e| e.into_inner());
1245
1246 broadcasts.entry(T::ID).or_default().insert(tx)
1247 };
1248
1249 Listener {
1250 shared: Some(self.shared.clone()),
1251 id: T::ID,
1252 index,
1253 rx,
1254 _marker: PhantomData,
1255 }
1256 }
1257
1258 #[inline]
1262 pub fn close(&self) {
1263 _ = self.shared.tx.send(Command::Close);
1264 }
1265}
1266
1267impl PartialEq for Handle {
1268 #[inline]
1269 fn eq(&self, other: &Self) -> bool {
1270 Arc::ptr_eq(&self.shared, &other.shared)
1271 }
1272}
1273
1274impl Eq for Handle {}
1275
1276impl fmt::Debug for Handle {
1277 #[inline]
1278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1279 f.debug_struct("Handle")
1280 .field("state", &*self.shared.state.borrow())
1281 .finish_non_exhaustive()
1282 }
1283}
1284
1285pub struct Channel {
1294 shared: Arc<Shared>,
1295 id: ChannelId,
1296}
1297
1298impl Channel {
1299 #[inline]
1301 pub fn id(&self) -> ChannelId {
1302 self.id
1303 }
1304
1305 #[inline]
1310 pub fn handle(&self) -> Handle {
1311 Handle {
1312 shared: self.shared.clone(),
1313 }
1314 }
1315
1316 #[inline]
1320 pub fn request(&self) -> RequestBuilder<'_, EmptyBody> {
1321 RequestBuilder {
1322 shared: &self.shared,
1323 channel: self.id,
1324 body: EmptyBody,
1325 }
1326 }
1327}
1328
1329impl Drop for Channel {
1330 #[inline]
1331 fn drop(&mut self) {
1332 _ = self.shared.send(Command::Disconnect { channel: self.id });
1333 }
1334}
1335
1336impl fmt::Debug for Channel {
1337 #[inline]
1338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1339 f.debug_struct("Channel")
1340 .field("id", &self.id)
1341 .field("state", &*self.shared.state.borrow())
1342 .finish_non_exhaustive()
1343 }
1344}
1345
1346pub struct RequestBuilder<'a, B> {
1351 shared: &'a Arc<Shared>,
1352 channel: ChannelId,
1353 body: B,
1354}
1355
1356impl<'a, B> RequestBuilder<'a, B> {
1357 #[inline]
1359 pub fn body<U>(self, body: U) -> RequestBuilder<'a, U>
1360 where
1361 U: api::Request,
1362 {
1363 RequestBuilder {
1364 shared: self.shared,
1365 channel: self.channel,
1366 body,
1367 }
1368 }
1369}
1370
1371impl<B> RequestBuilder<'_, B>
1372where
1373 B: api::Request,
1374{
1375 pub async fn send(self) -> Result<Packet<B::Endpoint>> {
1377 Ok(Packet::new(self.send_raw().await?))
1378 }
1379
1380 pub async fn send_raw(self) -> Result<RawPacket> {
1382 let id = <B::Endpoint as api::Endpoint>::ID;
1383
1384 if !self.shared.is_open() {
1385 return Err(Error::new(ErrorKind::NotConnected));
1386 }
1387
1388 let serial = self.shared.next_serial();
1389 let format = self.shared.format();
1390
1391 let header = api::RequestHeader {
1392 serial,
1393 id: id.get(),
1394 format: format.to_u8(),
1395 channel: self.channel,
1396 };
1397
1398 let mut data = Vec::new();
1399 format::encode_envelope(&mut data, &header).map_err(Error::encoding_header)?;
1400 format
1401 .encode(&mut data, &self.body)
1402 .map_err(Error::encoding_body)?;
1403
1404 tracing::debug!(serial, ?id, ?format, len = data.len(), "Sending request");
1405
1406 let (reply, rx) = oneshot::channel();
1407
1408 self.shared.send(Command::Send {
1409 serial,
1410 data,
1411 pending: Pending::Request { id, reply },
1412 })?;
1413
1414 let Ok(result) = rx.await else {
1415 return Err(Error::message("Client service is down"));
1416 };
1417
1418 result
1419 }
1420}
1421
1422pub struct Listener<T> {
1427 shared: Option<Arc<Shared>>,
1428 id: MessageId,
1429 index: usize,
1430 rx: mpsc::UnboundedReceiver<Result<RawPacket>>,
1431 _marker: PhantomData<T>,
1432}
1433
1434impl<T> Listener<T> {
1435 #[inline]
1439 pub async fn recv_raw(&mut self) -> Option<Result<RawPacket>> {
1440 self.rx.recv().await
1441 }
1442
1443 #[inline]
1447 pub async fn recv(&mut self) -> Option<Result<Packet<T>>> {
1448 Some(match self.rx.recv().await? {
1449 Ok(packet) => Ok(Packet::new(packet)),
1450 Err(error) => Err(error),
1451 })
1452 }
1453
1454 pub fn clear(&mut self) {
1460 let Some(shared) = self.shared.take() else {
1461 return;
1462 };
1463
1464 let index = mem::take(&mut self.index);
1465
1466 let mut broadcasts = shared.broadcasts.lock().unwrap_or_else(|e| e.into_inner());
1467
1468 let Entry::Occupied(mut e) = broadcasts.entry(self.id) else {
1469 return;
1470 };
1471
1472 _ = e.get_mut().try_remove(index);
1473
1474 if e.get().is_empty() {
1475 e.remove();
1476 }
1477 }
1478}
1479
1480impl<T> Drop for Listener<T> {
1481 #[inline]
1482 fn drop(&mut self) {
1483 self.clear();
1484 }
1485}
1486
1487impl<T> fmt::Debug for Listener<T> {
1488 #[inline]
1489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1490 f.debug_struct("Listener")
1491 .field("type", &any::type_name::<T>())
1492 .field("id", &self.id)
1493 .finish_non_exhaustive()
1494 }
1495}
1496
1497pub struct StateListener {
1501 rx: watch::Receiver<State>,
1502 shared: Arc<Shared>,
1503}
1504
1505impl StateListener {
1506 #[inline]
1508 pub fn state(&self) -> State {
1509 *self.rx.borrow()
1510 }
1511
1512 #[inline]
1516 pub async fn changed(&mut self) -> Option<State> {
1517 if self.shared.is_gone() {
1518 return None;
1519 }
1520
1521 self.rx.changed().await.ok()?;
1522
1523 if self.shared.is_gone() {
1524 return None;
1525 }
1526
1527 Some(*self.rx.borrow_and_update())
1528 }
1529
1530 pub async fn wait_until(&mut self, state: State) -> bool {
1535 loop {
1536 if *self.rx.borrow_and_update() == state {
1537 return true;
1538 }
1539
1540 if self.shared.is_gone() {
1541 return false;
1542 }
1543
1544 if self.rx.changed().await.is_err() {
1545 return false;
1546 }
1547 }
1548 }
1549}
1550
1551impl Clone for StateListener {
1552 #[inline]
1553 fn clone(&self) -> Self {
1554 Self {
1555 rx: self.rx.clone(),
1556 shared: self.shared.clone(),
1557 }
1558 }
1559}
1560
1561impl fmt::Debug for StateListener {
1562 #[inline]
1563 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1564 f.debug_struct("StateListener")
1565 .field("state", &*self.rx.borrow())
1566 .finish()
1567 }
1568}
1569
1570#[derive(Clone)]
1572pub struct RawPacket {
1573 id: MessageId,
1574 buf: Bytes,
1575 at: Cell<usize>,
1576 format: Format,
1577 channel: ChannelId,
1578}
1579
1580impl RawPacket {
1581 #[inline]
1595 pub const fn empty() -> Self {
1596 Self {
1597 id: MessageId::EMPTY,
1598 buf: Bytes::new(),
1599 at: Cell::new(0),
1600 format: Format::DEFAULT,
1601 channel: ChannelId::NONE,
1602 }
1603 }
1604
1605 #[inline]
1617 pub fn format(&self) -> Format {
1618 self.format
1619 }
1620
1621 #[inline]
1626 pub fn channel(&self) -> ChannelId {
1627 self.channel
1628 }
1629
1630 pub fn decode<'this, T>(&'this self) -> Result<T>
1637 where
1638 T: DecodeBody<'this>,
1639 {
1640 if self.id == MessageId::EMPTY {
1641 return Err(Error::new(ErrorKind::EmptyPacket));
1642 }
1643
1644 let mut at = self.at.get();
1645
1646 match self.format.decode(&self.buf, &mut at) {
1647 Ok(value) => {
1648 self.at.set(at);
1649 Ok(value)
1650 }
1651 Err(error) => {
1652 self.at.set(self.len());
1653 Err(Error::decode_packet(error))
1654 }
1655 }
1656 }
1657
1658 #[inline]
1669 pub fn as_slice(&self) -> &[u8] {
1670 &self.buf
1671 }
1672
1673 #[inline]
1684 pub fn remaining(&self) -> usize {
1685 self.buf.len().saturating_sub(self.at.get())
1686 }
1687
1688 #[inline]
1699 pub fn len(&self) -> usize {
1700 self.buf.len()
1701 }
1702
1703 #[inline]
1714 pub fn is_empty(&self) -> bool {
1715 self.at.get() >= self.len()
1716 }
1717
1718 #[inline]
1724 pub fn id(&self) -> MessageId {
1725 self.id
1726 }
1727}
1728
1729impl fmt::Debug for RawPacket {
1730 #[inline]
1731 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1732 f.debug_struct("RawPacket")
1733 .field("id", &self.id)
1734 .field("remaining", &self.remaining())
1735 .finish()
1736 }
1737}
1738
1739pub struct Packet<T> {
1741 raw: RawPacket,
1742 _marker: PhantomData<T>,
1743}
1744
1745impl<T> Packet<T> {
1746 #[inline]
1760 pub const fn empty() -> Self {
1761 Self {
1762 raw: RawPacket::empty(),
1763 _marker: PhantomData,
1764 }
1765 }
1766
1767 #[inline]
1773 pub fn new(raw: RawPacket) -> Self {
1774 Self {
1775 raw,
1776 _marker: PhantomData,
1777 }
1778 }
1779
1780 #[inline]
1785 pub fn channel(&self) -> ChannelId {
1786 self.raw.channel()
1787 }
1788
1789 #[inline]
1791 pub fn format(&self) -> Format {
1792 self.raw.format()
1793 }
1794
1795 #[inline]
1797 pub fn into_raw(self) -> RawPacket {
1798 self.raw
1799 }
1800
1801 #[inline]
1812 pub fn remaining(&self) -> usize {
1813 self.raw.remaining()
1814 }
1815
1816 #[inline]
1827 pub fn is_empty(&self) -> bool {
1828 self.raw.is_empty()
1829 }
1830
1831 #[inline]
1837 pub fn id(&self) -> MessageId {
1838 self.raw.id()
1839 }
1840}
1841
1842impl<T> Packet<T>
1843where
1844 T: api::Decodable,
1845{
1846 #[inline]
1853 pub fn decode(&self) -> Result<T::Type<'_>> {
1854 self.decode_any()
1855 }
1856
1857 #[inline]
1864 pub fn decode_any<'de, R>(&'de self) -> Result<R>
1865 where
1866 R: DecodeBody<'de>,
1867 {
1868 self.raw.decode()
1869 }
1870}
1871
1872impl<T> Packet<T>
1873where
1874 T: api::Endpoint,
1875{
1876 #[inline]
1883 pub fn decode_response(&self) -> Result<T::Response<'_>> {
1884 self.decode_any_response()
1885 }
1886
1887 #[inline]
1894 pub fn decode_any_response<'de, R>(&'de self) -> Result<R>
1895 where
1896 R: DecodeBody<'de>,
1897 {
1898 self.raw.decode()
1899 }
1900}
1901
1902impl<T> Packet<T>
1903where
1904 T: api::Broadcast,
1905{
1906 #[inline]
1908 pub fn decode_event<'de>(&'de self) -> Result<T::Event<'de>>
1909 where
1910 T: api::BroadcastWithEvent,
1911 {
1912 self.decode_event_any()
1913 }
1914
1915 #[inline]
1917 pub fn decode_event_any<'de, E>(&'de self) -> Result<E>
1918 where
1919 E: Event<Broadcast = T> + DecodeBody<'de>,
1920 {
1921 self.raw.decode()
1922 }
1923}
1924
1925impl<T> Clone for Packet<T> {
1926 #[inline]
1927 fn clone(&self) -> Self {
1928 Self {
1929 raw: self.raw.clone(),
1930 _marker: PhantomData,
1931 }
1932 }
1933}
1934
1935impl<T> fmt::Debug for Packet<T> {
1936 #[inline]
1937 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1938 f.debug_struct("Packet")
1939 .field("type", &any::type_name::<T>())
1940 .field("remaining", &self.remaining())
1941 .finish()
1942 }
1943}