confium_tc/coordinator/
net_server.rs1use std::io;
7use std::net::{TcpListener, TcpStream};
8use std::sync::{Arc, Mutex};
9use std::thread;
10
11use crate::coordinator::coordinator::Coordinator;
12use crate::coordinator::net::{ProtocolMessage, recv_message, send_message};
13use crate::coordinator::session::{Commitment, Share};
14use chrono::Utc;
15
16pub type SharedCoordinator = Arc<Mutex<Coordinator>>;
18
19pub struct CoordinatorServer {
21 addr: String,
22 coordinator: SharedCoordinator,
23}
24
25impl CoordinatorServer {
26 pub fn new(addr: &str) -> Self {
28 Self {
29 addr: addr.to_string(),
30 coordinator: Arc::new(Mutex::new(Coordinator::new())),
31 }
32 }
33
34 pub fn shared_coordinator(&self) -> SharedCoordinator {
36 Arc::clone(&self.coordinator)
37 }
38
39 pub fn start(&self) -> io::Result<String> {
41 let listener = TcpListener::bind(&self.addr)?;
42 let bound_addr = listener.local_addr()?.to_string();
43 let coordinator = Arc::clone(&self.coordinator);
44
45 thread::spawn(move || {
46 for stream_result in listener.incoming() {
47 match stream_result {
48 Ok(stream) => {
49 let coord = Arc::clone(&coordinator);
50 thread::spawn(move || {
51 let _ = handle_connection(stream, coord);
52 });
53 }
54 Err(e) => {
55 eprintln!("Coordinator: accept error: {e}");
56 }
57 }
58 }
59 });
60
61 Ok(bound_addr)
62 }
63}
64
65fn handle_connection(mut stream: TcpStream, coordinator: SharedCoordinator) -> io::Result<()> {
66 loop {
67 let msg = match recv_message(&mut stream) {
68 Ok(m) => m,
69 Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => break,
70 Err(_) => break,
71 };
72
73 let response = process_message(msg, &coordinator);
74 if let Some(resp) = response {
75 if send_message(&mut stream, &resp).is_err() {
76 break;
77 }
78 }
79 }
80 Ok(())
81}
82
83fn process_message(
84 msg: ProtocolMessage,
85 coordinator: &SharedCoordinator,
86) -> Option<ProtocolMessage> {
87 match msg {
88 ProtocolMessage::Register {
89 signer_id,
90 quorum_id: _,
91 } => Some(ProtocolMessage::Registered {
92 signer_id: signer_id.clone(),
93 }),
94
95 ProtocolMessage::CreateSession {
96 quorum_id,
97 scheme,
98 message,
99 threshold,
100 num_parties,
101 } => {
102 let mut coord = coordinator.lock().unwrap();
103 let request = crate::coordinator::session::SessionRequest {
104 quorum_id,
105 scheme,
106 message,
107 threshold,
108 num_parties,
109 unlock_window_minutes: 240,
110 requested_by: "tcp-client".into(),
111 };
112 match coord.create_session(request) {
113 Ok(session_id) => Some(ProtocolMessage::SessionCreated { session_id }),
114 Err(e) => Some(ProtocolMessage::Error {
115 message: format!("{e:?}"),
116 }),
117 }
118 }
119
120 ProtocolMessage::Commitment {
121 session_id,
122 signer_id,
123 bytes,
124 signature,
125 } => {
126 let mut coord = coordinator.lock().unwrap();
127 let commitment = Commitment {
128 signer_id: signer_id.clone(),
129 bytes,
130 signer_signature: signature,
131 submitted_at: Utc::now(),
132 };
133 match coord.submit_commitment(&session_id, commitment) {
134 Ok(()) => Some(ProtocolMessage::Ack { session_id }),
135 Err(e) => Some(ProtocolMessage::Error {
136 message: format!("{e:?}"),
137 }),
138 }
139 }
140
141 ProtocolMessage::Share {
142 session_id,
143 signer_id,
144 bytes,
145 signature,
146 } => {
147 let mut coord = coordinator.lock().unwrap();
148 let share = Share {
149 signer_id: signer_id.clone(),
150 bytes,
151 signer_signature: signature,
152 submitted_at: Utc::now(),
153 };
154 match coord.submit_share(&session_id, share) {
155 Ok(()) => {
156 let threshold = coord.session_threshold(&session_id).unwrap_or(0);
158 let share_count = coord.session_share_count(&session_id).unwrap_or(0);
159 if share_count >= threshold as usize {
160 match coord.aggregate(&session_id) {
161 Ok(sig) => Some(ProtocolMessage::Signature {
162 session_id: session_id.clone(),
163 bytes: sig.bytes,
164 algorithm: sig.algorithm,
165 contributing_signers: sig.contributing_signers,
166 }),
167 Err(e) => Some(ProtocolMessage::Error {
168 message: format!("{e:?}"),
169 }),
170 }
171 } else {
172 Some(ProtocolMessage::Ack { session_id })
173 }
174 }
175 Err(e) => Some(ProtocolMessage::Error {
176 message: format!("{e:?}"),
177 }),
178 }
179 }
180
181 ProtocolMessage::GetStatus { session_id } => {
182 let coord = coordinator.lock().unwrap();
183 match session_id {
184 Some(sid) => {
185 let state = coord.session_state(&sid);
186 Some(ProtocolMessage::Status {
187 session_id: sid,
188 state: format!("{:?}", state),
189 })
190 }
191 None => Some(ProtocolMessage::Error {
192 message: "session_id required".into(),
193 }),
194 }
195 }
196
197 ProtocolMessage::HealthCheck => Some(ProtocolMessage::HealthStatus {
198 alive: true,
199 ready: true,
200 session_count: coordinator.lock().unwrap().session_count(),
201 uptime_seconds: 0,
202 }),
203
204 _ => Some(ProtocolMessage::Error {
205 message: "unexpected message type".into(),
206 }),
207 }
208}