ecksport_net/
channel_state.rs1use std::collections::*;
2
3use ecksport_core::topic;
4
5use crate::errors::Error;
6
7#[derive(Clone, Debug)]
9pub struct ChannelTable {
10 next_local_chan: u32,
12
13 next_remote_chan: u32,
15
16 channels: HashMap<u32, ChannelState>,
18}
19
20impl ChannelTable {
21 pub fn new(inited_by: Creator) -> Self {
23 let (nlc, nrc) = match inited_by {
24 Creator::Local => (0, 1),
25 Creator::Remote => (1, 0),
26 };
27
28 Self {
29 next_local_chan: nlc,
30 next_remote_chan: nrc,
31 channels: HashMap::new(),
32 }
33 }
34
35 pub fn num_open_channels(&self) -> usize {
37 self.channels.len()
38 }
39
40 fn init_chan(
42 &mut self,
43 creator: Creator,
44 topic: topic::Topic,
45 local_open: bool,
46 remote_open: bool,
47 ) -> u32 {
48 let id = match creator {
49 Creator::Local => self.consume_local_chan_id(),
50 Creator::Remote => self.consume_remote_chan_id(),
51 };
52
53 let chstate = ChannelState::new(topic, local_open, remote_open);
55 assert!(self.channels.insert(id, chstate).is_none());
56
57 id
58 }
59
60 pub fn init_local_chan(&mut self, topic: topic::Topic, im_close: bool) -> u32 {
62 self.init_chan(Creator::Local, topic, im_close, true)
63 }
64
65 pub fn init_remote_chan(&mut self, topic: topic::Topic, im_close: bool) -> u32 {
67 self.init_chan(Creator::Remote, topic, true, im_close)
68 }
69
70 pub fn mark_chan_local_closed(&mut self, id: u32) -> Option<bool> {
73 let ch = self.channels.get_mut(&id)?;
74 ch.close_local();
75 let died = !ch.is_live();
76 if died {
77 self.channels.remove(&id);
78 }
79 Some(died)
80 }
81
82 pub fn mark_chan_remote_closed(&mut self, id: u32) -> Option<bool> {
85 let ch = self.channels.get_mut(&id)?;
86 ch.close_remote();
87 let died = !ch.is_live();
88 if died {
89 self.channels.remove(&id);
90 }
91 Some(died)
92 }
93
94 fn consume_local_chan_id(&mut self) -> u32 {
95 let id = self.next_local_chan;
96 self.next_local_chan += 2;
97 id
98 }
99
100 fn consume_remote_chan_id(&mut self) -> u32 {
101 let id = self.next_remote_chan;
102 self.next_remote_chan += 2;
103 id
104 }
105
106 pub fn check_recv_on_chan(&self, id: u32) -> Result<(), Error> {
109 let Some(chstate) = self.channels.get(&id) else {
110 return Err(Error::RecvOnUnkChan(id));
111 };
112
113 if !chstate.remote_open {
114 return Err(Error::RecvOnClosedChan(id));
115 }
116
117 Ok(())
118 }
119
120 pub fn check_send_on_chan(&self, id: u32) -> Result<(), Error> {
123 let Some(chstate) = self.channels.get(&id) else {
124 return Err(Error::SendOnUnkChan(id));
125 };
126
127 if !chstate.local_open {
128 return Err(Error::SendOnClosedChan(id));
129 }
130
131 Ok(())
132 }
133}
134
135#[derive(Clone, Debug)]
137pub struct ChannelState {
138 topic: topic::Topic,
140
141 local_open: bool,
143
144 remote_open: bool,
146}
147
148impl ChannelState {
149 pub fn new(topic: topic::Topic, local_open: bool, remote_open: bool) -> Self {
150 Self {
151 topic,
152 local_open,
153 remote_open,
154 }
155 }
156
157 pub fn topic(&self) -> topic::Topic {
158 self.topic
159 }
160
161 pub fn close_local(&mut self) {
162 self.local_open = false;
163 }
164
165 pub fn close_remote(&mut self) {
166 self.remote_open = false;
167 }
168
169 pub fn is_live(&self) -> bool {
170 self.local_open && self.remote_open
171 }
172}
173
174#[derive(Copy, Clone, Debug, Eq, PartialEq)]
176pub enum Creator {
177 Local,
178 Remote,
179}