litep2p/protocol/request_response/
config.rs

1// Copyright 2023 litep2p developers
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use crate::{
22    codec::ProtocolCodec,
23    protocol::request_response::{
24        handle::{InnerRequestResponseEvent, RequestResponseCommand, RequestResponseHandle},
25        REQUEST_TIMEOUT,
26    },
27    types::protocol::ProtocolName,
28    DEFAULT_CHANNEL_SIZE,
29};
30
31use tokio::sync::mpsc::{channel, Receiver, Sender};
32
33use std::{
34    sync::{atomic::AtomicUsize, Arc},
35    time::Duration,
36};
37
38/// Request-response protocol configuration.
39pub struct Config {
40    /// Protocol name.
41    pub(crate) protocol_name: ProtocolName,
42
43    /// Fallback names for the main protocol name.
44    pub(crate) fallback_names: Vec<ProtocolName>,
45
46    /// Timeout for outbound requests.
47    pub(crate) timeout: Duration,
48
49    /// Codec used by the protocol.
50    pub(crate) codec: ProtocolCodec,
51
52    /// TX channel for sending events to the user protocol.
53    pub(super) event_tx: Sender<InnerRequestResponseEvent>,
54
55    /// RX channel for receiving commands from the user protocol.
56    pub(crate) command_rx: Receiver<RequestResponseCommand>,
57
58    /// Next ephemeral request ID.
59    pub(crate) next_request_id: Arc<AtomicUsize>,
60
61    /// Maximum number of concurrent inbound requests.
62    pub(crate) max_concurrent_inbound_request: Option<usize>,
63}
64
65impl Config {
66    /// Create new [`Config`].
67    pub fn new(
68        protocol_name: ProtocolName,
69        fallback_names: Vec<ProtocolName>,
70        max_message_size: usize,
71        timeout: Duration,
72        max_concurrent_inbound_request: Option<usize>,
73    ) -> (Self, RequestResponseHandle) {
74        let (event_tx, event_rx) = channel(DEFAULT_CHANNEL_SIZE);
75        let (command_tx, command_rx) = channel(DEFAULT_CHANNEL_SIZE);
76        let next_request_id = Default::default();
77        let handle = RequestResponseHandle::new(event_rx, command_tx, Arc::clone(&next_request_id));
78
79        (
80            Self {
81                event_tx,
82                command_rx,
83                protocol_name,
84                fallback_names,
85                next_request_id,
86                timeout,
87                max_concurrent_inbound_request,
88                codec: ProtocolCodec::UnsignedVarint(Some(max_message_size)),
89            },
90            handle,
91        )
92    }
93
94    /// Get protocol name.
95    pub(crate) fn protocol_name(&self) -> &ProtocolName {
96        &self.protocol_name
97    }
98}
99
100/// Builder for [`Config`].
101pub struct ConfigBuilder {
102    /// Protocol name.
103    pub(crate) protocol_name: ProtocolName,
104
105    /// Fallback names for the main protocol name.
106    pub(crate) fallback_names: Vec<ProtocolName>,
107
108    /// Maximum message size.
109    max_message_size: Option<usize>,
110
111    /// Timeout for outbound requests.
112    timeout: Option<Duration>,
113
114    /// Maximum number of concurrent inbound requests.
115    max_concurrent_inbound_request: Option<usize>,
116}
117
118impl ConfigBuilder {
119    /// Create new [`ConfigBuilder`].
120    pub fn new(protocol_name: ProtocolName) -> Self {
121        Self {
122            protocol_name,
123            fallback_names: Vec::new(),
124            max_message_size: None,
125            timeout: Some(REQUEST_TIMEOUT),
126            max_concurrent_inbound_request: None,
127        }
128    }
129
130    /// Set maximum message size.
131    pub fn with_max_size(mut self, max_message_size: usize) -> Self {
132        self.max_message_size = Some(max_message_size);
133        self
134    }
135
136    /// Set fallback names.
137    pub fn with_fallback_names(mut self, fallback_names: Vec<ProtocolName>) -> Self {
138        self.fallback_names = fallback_names;
139        self
140    }
141
142    /// Set timeout for outbound requests.
143    pub fn with_timeout(mut self, timeout: Duration) -> Self {
144        self.timeout = Some(timeout);
145        self
146    }
147
148    /// Specify the maximum number of concurrent inbound requests. By default the number of inbound
149    /// requests is not limited.
150    ///
151    /// If a new request is received while the number of inbound requests is already at a maximum,
152    /// the request is dropped.
153    pub fn with_max_concurrent_inbound_requests(
154        mut self,
155        max_concurrent_inbound_requests: usize,
156    ) -> Self {
157        self.max_concurrent_inbound_request = Some(max_concurrent_inbound_requests);
158        self
159    }
160
161    /// Build [`Config`].
162    pub fn build(mut self) -> (Config, RequestResponseHandle) {
163        Config::new(
164            self.protocol_name,
165            self.fallback_names,
166            self.max_message_size.take().expect("maximum message size to be set"),
167            self.timeout.take().expect("timeout to exist"),
168            self.max_concurrent_inbound_request,
169        )
170    }
171}