Skip to main content

cloudpub_client/
client.rs

1use anyhow::{anyhow, bail, Context, Result};
2use backoff::backoff::Backoff;
3use cloudpub_common::data::DataChannel;
4use cloudpub_common::fair_channel::{fair_channel, FairSender};
5use cloudpub_common::protocol::message::Message;
6use cloudpub_common::protocol::{
7    AgentInfo, ConnectState, Data, DataChannelAck, DataChannelData, DataChannelDataUdp,
8    DataChannelEof, ErrorInfo, ErrorKind, HeartBeat, Protocol,
9};
10use cloudpub_common::transport::{AddrMaybeCached, SocketOpts, Transport, WebsocketTransport};
11use cloudpub_common::utils::{
12    get_platform, proto_to_socket_addr, socket_addr_to_proto, udp_connect,
13};
14use cloudpub_common::VERSION;
15use dashmap::DashMap;
16use parking_lot::RwLock;
17use std::net::SocketAddr;
18use std::sync::Arc;
19use tokio::io::{AsyncReadExt, AsyncWriteExt};
20use tokio::net::{TcpStream, UdpSocket};
21use tokio::sync::mpsc;
22use tokio::time::{self, Duration, Instant};
23use tracing::{debug, error, info, trace, warn};
24
25use cloudpub_common::constants::{
26    run_control_chan_backoff, CONTROL_CHANNEL_SIZE, DATA_BUFFER_SIZE, DATA_CHANNEL_SIZE,
27    DEFAULT_CLIENT_RETRY_INTERVAL_SECS, UDP_BUFFER_SIZE, UDP_TIMEOUT,
28};
29use futures::future::FutureExt;
30
31use crate::config::{ClientConfig, ClientOpts};
32use crate::upgrade::handle_upgrade_available;
33use bytes::Bytes;
34use cloudpub_common::transport::ProtobufStream;
35
36#[cfg(feature = "plugins")]
37use crate::plugins::plugin_trait::PluginHandle;
38#[cfg(feature = "plugins")]
39use crate::plugins::registry::PluginRegistry;
40
41type Service = Arc<DataChannel>;
42
43type Services = Arc<DashMap<String, Service>>;
44
45// Holds the state of a client
46struct Client<T: Transport> {
47    config: Arc<RwLock<ClientConfig>>,
48    opts: ClientOpts,
49    services: Services,
50    transport: Arc<T>,
51    connected: bool,
52    #[cfg(feature = "plugins")]
53    plugin_processes: Arc<DashMap<String, PluginHandle>>,
54    data_channels: Arc<DashMap<u32, Arc<DataChannel>>>,
55}
56
57impl<T: 'static + Transport> Client<T> {
58    // Create a Client from `[client]` config block
59    async fn from(config: Arc<RwLock<ClientConfig>>, opts: ClientOpts) -> Result<Client<T>> {
60        let transport = Arc::new(
61            T::new(&config.clone().read().transport)
62                .with_context(|| "Failed to create the transport")?,
63        );
64        Ok(Client {
65            config,
66            opts,
67            services: Default::default(),
68            transport,
69            connected: false,
70            #[cfg(feature = "plugins")]
71            plugin_processes: Arc::new(DashMap::new()),
72            data_channels: Arc::new(DashMap::new()),
73        })
74    }
75
76    // The entrypoint of Client
77    async fn run(
78        &mut self,
79        mut command_rx: mpsc::Receiver<Message>,
80        result_tx: mpsc::Sender<Message>,
81    ) -> Result<()> {
82        let transport = self.transport.clone();
83
84        let mut retry_backoff = run_control_chan_backoff(DEFAULT_CLIENT_RETRY_INTERVAL_SECS);
85
86        let mut start = Instant::now();
87        result_tx
88            .send(Message::ConnectState(ConnectState::Connecting.into()))
89            .await
90            .context("Can't send Connecting event")?;
91        while let Err(err) = self
92            .run_control_channel(transport.clone(), &mut command_rx, &result_tx)
93            .boxed()
94            .await
95        {
96            if result_tx.is_closed() {
97                // The client is shutting down
98                break;
99            }
100
101            if self.connected {
102                result_tx
103                    .send(Message::Error(ErrorInfo {
104                        kind: ErrorKind::HandshakeFailed.into(),
105                        message: crate::t!("error-network"),
106                        guid: String::new(),
107                    }))
108                    .await
109                    .context("Can't send Error event")?;
110                result_tx
111                    .send(Message::ConnectState(ConnectState::Disconnected.into()))
112                    .await
113                    .context("Can't send Disconnected event")?;
114                result_tx
115                    .send(Message::ConnectState(ConnectState::Connecting.into()))
116                    .await
117                    .context("Can't send Connecting event")?;
118                self.connected = false;
119            }
120
121            self.services.clear();
122            #[cfg(feature = "plugins")]
123            self.plugin_processes.clear();
124            self.data_channels.clear();
125
126            if start.elapsed() > Duration::from_secs(3) {
127                // The client runs for at least 3 secs and then disconnects
128                retry_backoff.reset();
129            }
130
131            if let Some(duration) = retry_backoff.next_backoff() {
132                warn!("{:#}. Retry in {:?}...", err, duration);
133                time::sleep(duration).await;
134            }
135
136            start = Instant::now();
137        }
138
139        self.services.clear();
140        #[cfg(feature = "plugins")]
141        self.plugin_processes.clear();
142        self.data_channels.clear();
143
144        Ok(())
145    }
146
147    async fn run_control_channel(
148        &mut self,
149        transport: Arc<T>,
150        command_rx: &mut mpsc::Receiver<Message>,
151        result_tx: &mpsc::Sender<Message>,
152    ) -> Result<()> {
153        let url = self.config.read().server.clone();
154        let port = url.port().unwrap_or(443);
155        let host = url.host_str().context("Failed to get host")?;
156        let mut host_and_port = format!("{}:{}", host, port);
157
158        let (mut conn, _remote_addr) = loop {
159            let mut remote_addr = AddrMaybeCached::new(&host_and_port);
160            remote_addr
161                .resolve()
162                .await
163                .context("Failed to resolve server address")?;
164
165            let mut conn = transport.connect(&remote_addr).await.context(format!(
166                "Failed to connect control channel to {}",
167                &host_and_port
168            ))?;
169
170            self.connected = true;
171
172            T::hint(&conn, SocketOpts::for_control_channel());
173
174            let (email, password) = if let Some(ref cred) = self.opts.credentials {
175                (cred.0.clone(), cred.1.clone())
176            } else {
177                (String::new(), String::new())
178            };
179
180            let token = self
181                .config
182                .read()
183                .token
184                .clone()
185                .unwrap_or_default()
186                .to_string();
187
188            let hwid = self.config.read().get_hwid();
189
190            let agent_info = AgentInfo {
191                agent_id: self.config.read().agent_id.clone(),
192                token,
193                email,
194                password,
195                hostname: hostname::get()?.to_string_lossy().into_owned(),
196                version: VERSION.to_string(),
197                gui: self.opts.gui,
198                platform: get_platform(),
199                hwid,
200                server_host_and_port: host_and_port.clone(),
201                transient: self.opts.transient,
202                secondary: self.opts.secondary,
203                is_service: self.opts.is_service,
204            };
205
206            debug!("Sending hello: {:?}", agent_info);
207
208            let hello_send = Message::AgentHello(agent_info);
209
210            conn.send_message(&hello_send)
211                .await
212                .context("Failed to send hello message")?;
213
214            debug!("Reading ack");
215            match conn
216                .recv_message()
217                .await
218                .context("Failed to read ack message")?
219            {
220                Some(msg) => match msg {
221                    Message::AgentAck(args) => {
222                        if !args.token.is_empty() {
223                            let mut c = self.config.write();
224                            c.token = Some(args.token.as_str().into());
225                            c.save().context("Write config")?;
226                        }
227                        break (conn, remote_addr);
228                    }
229                    Message::Redirect(r) => {
230                        host_and_port = r.host_and_port.clone();
231                        debug!("Redirecting to {}", host_and_port);
232                        continue;
233                    }
234                    Message::Error(err) => {
235                        result_tx
236                            .send(Message::Error(err.clone()))
237                            .await
238                            .context("Can't send server error event")?;
239                        bail!("Error: {:?}", err.kind);
240                    }
241                    v => bail!("Unexpected ack message: {:?}", v),
242                },
243                None => bail!("Connection closed while reading ack message"),
244            };
245        };
246
247        debug!("Control channel established");
248
249        result_tx
250            .send(Message::ConnectState(ConnectState::Connected.into()))
251            .await
252            .context("Can't send Connected event")?;
253
254        let (to_server_tx, mut to_server_rx) = fair_channel::<Message>(CONTROL_CHANNEL_SIZE);
255        // Used to break long running setup
256
257        let heartbeat_timeout = self.config.read().heartbeat_timeout;
258
259        loop {
260            tokio::select! {
261                cmd = to_server_rx.recv() => {
262                    if let Some(cmd) = cmd {
263                        conn.send_message(&cmd).await.context("Failed to send command")?;
264                    }
265                },
266                cmd = command_rx.recv() => {
267                    if let Some(cmd) = cmd {
268                        debug!("Received message: {:?}", cmd);
269                        match cmd {
270                            Message::PerformUpgrade(info) => {
271                                let config_clone = self.config.clone();
272                                if let Err(e) = handle_upgrade_available(
273                                    &info.version,
274                                    config_clone,
275                                    self.opts.gui,
276                                    command_rx,
277                                    result_tx,
278                                )
279                                .await
280                                {
281                                    result_tx.send(Message::Error(ErrorInfo {
282                                        kind: ErrorKind::Fatal.into(),
283                                        message: e.to_string(),
284                                        guid: String::new(),
285                                    }))
286                                    .await
287                                    .context("Can't send Error event")?;
288                                }
289                            }
290                            Message::Stop(_x) => {
291                                info!("Stopping the client");
292                                break;
293                            }
294                            Message::Break(break_msg) => {
295                                info!("Breaking operation for guid: {}", break_msg.guid);
296                                #[cfg(feature = "plugins")]
297                                if let Some((_, handle)) = self.plugin_processes.remove(&break_msg.guid) {
298                                    info!("Dropped plugin handle for guid: {}", break_msg.guid);
299                                    drop(handle);
300                                }
301                            }
302                            cmd => {
303                                conn.send_message(&cmd).await.context("Failed to send message")?;
304                            }
305                        };
306                    } else {
307                        debug!("No more commands, shutting down...");
308                        break;
309                    }
310                },
311                val = conn.recv_message() => {
312                    match val? {
313                        Some(val) => {
314                            match val {
315                                Message::EndpointAck(mut endpoint) => {
316                                    #[cfg(feature = "plugins")]
317                                    {
318                                        let to_server_tx = to_server_tx.clone();
319                                        let config = self.config.clone();
320                                        let opts = self.opts.clone();
321                                        if endpoint.error.is_empty() {
322                                            let protocol: Protocol = endpoint
323                                                .client
324                                                .as_ref()
325                                                .unwrap()
326                                                .local_proto
327                                                .try_into()
328                                                .unwrap_or(Protocol::Tcp);
329                                            if let Some(plugin) = PluginRegistry::new().get(protocol) {
330                                                // Duplicate EndpointStart for a publication this
331                                                // client already serves (the server re-sends them
332                                                // after EndpointStartAll and on repeated
333                                                // registrations): replacing the handle would kill
334                                                // the running subprocess mid-flight.
335                                                let already_running = self
336                                                    .plugin_processes
337                                                    .get(&endpoint.guid)
338                                                    .map(|h| h.same_config(&endpoint) && h.is_healthy())
339                                                    .unwrap_or(false);
340                                                if already_running {
341                                                    debug!(
342                                                        "Endpoint {} already running with the same config, \
343                                                         ignoring duplicate start",
344                                                        endpoint.guid
345                                                    );
346                                                } else {
347                                                    let handle = PluginHandle::spawn(
348                                                        plugin,
349                                                        endpoint.clone(),
350                                                        config,
351                                                        opts,
352                                                        to_server_tx,
353                                                    );
354                                                    self.plugin_processes.insert(endpoint.guid.clone(), handle);
355                                                }
356                                            } else {
357                                                endpoint.status = Some("online".into());
358                                                let _ = to_server_tx.send(Message::EndpointStatus(endpoint.clone())).await;
359                                            }
360                                        }
361                                    }
362                                    #[cfg(not(feature = "plugins"))]
363                                    {
364                                        endpoint.status = Some("online".into());
365                                        let _ = to_server_tx.send(Message::EndpointStatus(endpoint.clone())).await;
366                                    }
367                                    result_tx
368                                        .send(Message::EndpointAck(endpoint))
369                                        .await
370                                        .context("Can't send EndpointAck event")?;
371                                }
372
373                                Message::CreateDataChannelWithId(create_msg) => {
374                                    let channel_id = create_msg.channel_id;
375                                    let endpoint = create_msg.endpoint.unwrap();
376
377                                    trace!("Creating data channel {} for endpoint {:?}", channel_id, endpoint.guid);
378
379                                    // Create channels for data flow
380                                    let (to_service_tx, to_service_rx) = mpsc::channel::<Data>(DATA_CHANNEL_SIZE);
381
382                                    // Register the data channel
383                                    let data_channel = Arc::new(DataChannel::new_client(channel_id, to_service_tx.clone()));
384                                    self.data_channels.insert(channel_id, data_channel.clone());
385
386                                    // Check if endpoint handled by plugin server
387                                    let client = endpoint.client.unwrap();
388                                    #[allow(unused_mut)]
389                                    let mut local_addr = format!("{}:{}", client.local_addr, client.local_port);
390                                    #[cfg(feature = "plugins")]
391                                    if let Some(handle) = self.plugin_processes.get(&endpoint.guid) {
392                                        if let Some(port) = handle.value().port() {
393                                            local_addr = format!("127.0.0.1:{}", port);
394                                        }
395                                    }
396
397                                    // Immediately start handling the data channel
398                                    let data_channels = self.data_channels.clone();
399                                    let protocol: Protocol = client.local_proto.try_into().unwrap();
400
401                                    let to_server_tx_cloned = to_server_tx.clone();
402                                    tokio::spawn(async move {
403                                        if let Err(err) = if protocol == Protocol::Udp {
404                                            handle_udp_data_channel(
405                                                data_channel,
406                                                local_addr,
407                                                to_server_tx_cloned.clone(),
408                                                to_service_rx
409                                            ).await
410                                        } else {
411                                            handle_tcp_data_channel(
412                                                data_channel,
413                                                local_addr,
414                                                to_server_tx_cloned.clone(),
415                                                to_service_rx
416                                            ).await
417                                        } {
418                                            error!("DataChannel {{ channel_id: {} }}: {:?}", channel_id, err);
419                                            to_server_tx_cloned
420                                                .send(Message::DataChannelEof(
421                                                        DataChannelEof {
422                                                            channel_id,
423                                                            error: err.to_string()
424                                                    })
425                                                ).await.ok();
426                                        }
427                                        if let Some((_, dc)) = data_channels.remove(&channel_id) { dc.close() }
428                                    });
429                                },
430
431                                Message::DataChannelData(data) => {
432                                    // Forward data to the appropriate data channel
433                                    let to_service_tx = self.data_channels.get(&data.channel_id).map(|ch| ch.data_tx.clone());
434                                    if let Some(tx) = to_service_tx {
435                                        if let Err(err) = tx.send(Data {
436                                            data: data.data.into(),
437                                            socket_addr: None
438                                        }).await {
439                                            self.data_channels.remove(&data.channel_id);
440                                            error!("Error send to data channel {}: {:?}", data.channel_id, err);
441                                        }
442                                    } else {
443                                        trace!("Data channel {} not found, dropping data", data.channel_id);
444                                    }
445                                },
446
447                                Message::DataChannelDataUdp(data) => {
448                                    // Forward UDP data to the appropriate data channel
449                                    let to_service_tx = self.data_channels.get(&data.channel_id).map(|ch| ch.data_tx.clone());
450                                    if let Some(tx) = to_service_tx {
451                                        let socket_addr = data.socket_addr.as_ref()
452                                            .map(proto_to_socket_addr)
453                                            .transpose()
454                                            .unwrap_or_else(|err| {
455                                                error!("Invalid socket address for UDP data channel {}: {:?}", data.channel_id, err);
456                                                None
457                                            });
458
459                                        if let Err(err) = tx.send(Data {
460                                            data: data.data.into(),
461                                            socket_addr,
462                                        }).await {
463                                            self.data_channels.remove(&data.channel_id);
464                                            error!("Error send to UDP data channel {}: {:?}", data.channel_id, err);
465                                        }
466                                    } else {
467                                        trace!("UDP Data channel {} not found, dropping data", data.channel_id);
468                                    }
469                                },
470
471                                Message::DataChannelEof(eof) => {
472                                    // Signal EOF by dropping the data channel
473                                    if let Some((_, dc)) = self.data_channels.remove(&eof.channel_id) { dc.close() }
474                                    if eof.error.is_empty() {
475                                        // Normal EOF without error
476                                        trace!("Data channel {} closed by server", eof.channel_id);
477                                    } else {
478                                        // EOF with error
479                                        trace!("Data channel {} closed by server with error: {}", eof.channel_id, eof.error);
480                                    }
481                                },
482
483                                Message::DataChannelAck(DataChannelAck { channel_id, consumed }) => {
484                                    if let Some(ch) = self.data_channels.get(&channel_id) {
485                                        ch.add_capacity(consumed);
486                                    }
487                                }
488
489                                Message::EndpointStopAck(ref ep) => {
490                                    self.services.remove(&ep.guid);
491                                    #[cfg(feature = "plugins")]
492                                    self.plugin_processes.remove(&ep.guid);
493                                    result_tx.send(val).await.context("Can't send result message")?;
494                                }
495
496                                Message::EndpointRemoveAck(ref ep) => {
497                                    self.services.remove(&ep.guid);
498                                    #[cfg(feature = "plugins")]
499                                    self.plugin_processes.remove(&ep.guid);
500                                    result_tx.send(val).await.context("Can't send result message")?;
501                                }
502
503                                Message::HeartBeat(_) => {
504                                    conn.send_message(&Message::HeartBeat(HeartBeat{})).await.context("Failed to send heartbeat")?;
505                                },
506
507                                Message::Error(ref err) => {
508                                    let kind: ErrorKind = err.kind.try_into().unwrap_or(ErrorKind::Fatal);
509                                    result_tx.send(val.clone()).await.context("Can't send result message")?;
510                                    if kind == ErrorKind::Fatal || kind == ErrorKind::AuthFailed {
511                                        error!("Fatal error received, stop client: {:?}", err);
512                                        break;
513                                    }
514                                }
515
516                                Message::Break(break_msg) => {
517                                    info!("Breaking operation for guid: {}", break_msg.guid);
518                                    #[cfg(feature = "plugins")]
519                                    self.plugin_processes.remove(&break_msg.guid);
520                                }
521
522                                Message::PerformUpgrade(info) => {
523                                    let config_clone = self.config.clone();
524                                    #[cfg(feature = "plugins")]
525                                    self.plugin_processes.clear();
526                                    self.services.clear();
527                                    self.data_channels.clear();
528
529                                    if let Err(e) = handle_upgrade_available(
530                                        &info.version,
531                                        config_clone,
532                                        self.opts.gui,
533                                        command_rx,
534                                        result_tx,
535                                    )
536                                    .await
537                                    {
538                                        conn.send_message(&Message::Error(ErrorInfo {
539                                            kind: ErrorKind::UpgradeFailed.into(),
540                                            message: e.to_string(),
541                                            guid: String::new(),
542                                        }))
543                                        .await
544                                        .context("Can't send Error event")?;
545                                    }
546                                }
547
548                                v => {
549                                    result_tx.send(v).await.context("Can't send result message")?;
550                                }
551                            }
552                        },
553                        None => {
554                            debug!("Connection closed by server");
555                            break;
556                        }
557                    }
558                },
559                _ = time::sleep(Duration::from_secs(heartbeat_timeout)), if heartbeat_timeout != 0 => {
560                    return Err(anyhow!("Heartbeat timed out"))
561                }
562            }
563        }
564
565        info!("Control channel shutdown");
566        result_tx
567            .send(Message::ConnectState(ConnectState::Disconnected.into()))
568            .await
569            .context("Can't send Disconnected event")?;
570        conn.close().await.ok();
571        time::sleep(Duration::from_millis(100)).await; // Give some time for the connection to close gracefully
572        Ok(())
573    }
574}
575
576pub async fn run_client(
577    config: Arc<RwLock<ClientConfig>>,
578    opts: ClientOpts,
579    command_rx: mpsc::Receiver<Message>,
580    result_tx: mpsc::Sender<Message>,
581) -> Result<()> {
582    let mut client = Client::<WebsocketTransport>::from(config, opts)
583        .await
584        .context("Failed to create Websocket client")?;
585    client.run(command_rx, result_tx).await
586}
587async fn handle_tcp_data_channel(
588    data_channel: Arc<DataChannel>,
589    local_addr: String,
590    to_server_tx: FairSender<Message>,
591    mut data_rx: mpsc::Receiver<Data>,
592) -> Result<()> {
593    trace!("Handling client {:?} to {}", data_channel, local_addr);
594
595    // Connect to local service immediately
596    let mut local_stream = TcpStream::connect(&local_addr)
597        .await
598        .with_context(|| format!("Failed to connect to local service at {}", local_addr))?;
599
600    // Set TCP_NODELAY for low latency
601    local_stream
602        .set_nodelay(true)
603        .context("Failed to set TCP_NODELAY")?;
604
605    let mut buf = [0u8; DATA_BUFFER_SIZE]; // Smaller buffer for low latency
606
607    loop {
608        tokio::select! {
609            res = local_stream.read(&mut buf) => {
610                match res {
611                    Ok(0) => {
612                        trace!("EOF received from local service for {:?}", data_channel);
613                        if let Err(err) = to_server_tx.send(Message::DataChannelEof(DataChannelEof {
614                            channel_id: data_channel.id,
615                            error: String::new()
616                        }))
617                        .await {
618                            trace!("Failed to send EOF to server for {:?}: {:#}", data_channel, err);
619                        }
620                        break;
621                    },
622                    Ok(n) => {
623                        //debug!("Read {} bytes from local service for {:?}", n, data_channel);
624                        if data_channel.wait_for_capacity(n as u32).await.is_err() {
625                            trace!("Data channel {} closed when waiting for capacity", data_channel.id);
626                            break;
627                        }
628                        if let Err(err) = to_server_tx.send(Message::DataChannelData(DataChannelData {
629                            channel_id: data_channel.id,
630                            data: buf[0..n].to_vec()
631                        }))
632                        .await {
633                            trace!("Failed to send data to server for {:?}: {:#}", data_channel, err);
634                            break;
635                        }
636                    },
637                    Err(e) => {
638                        return Err(e).context("Failed to read from local service");
639                    }
640                }
641            }
642
643            // Receive data from server via control channel and write to local service
644            data_result = data_rx.recv() => {
645                match data_result {
646                    Some(data) => {
647                        trace!("Received {} bytes from server for {:?}", data.data.len(), data_channel);
648                        local_stream.write_all(&data.data).await.context("Failed to write data to local service")?;
649                        to_server_tx.send(Message::DataChannelAck(
650                            DataChannelAck {
651                                channel_id: data_channel.id,
652                                consumed: data.data.len() as u32
653                            }
654                        )).await.with_context(|| "Failed to send TCP traffic ack to the server")?;
655                    },
656                    None => {
657                        trace!("EOF received from server for {:?}", data_channel);
658                        break;
659                    }
660                }
661            }
662
663            _ = data_channel.closed() => {
664                trace!("Data channel {} closed", data_channel.id);
665                break;
666            }
667        }
668    }
669    Ok(())
670}
671
672// UDP port map for managing forwarders per remote address
673type UdpPortMap = Arc<DashMap<SocketAddr, mpsc::Sender<Bytes>>>;
674
675async fn handle_udp_data_channel(
676    data_channel: Arc<DataChannel>,
677    local_addr: String,
678    to_server_tx: FairSender<Message>,
679    mut data_rx: mpsc::Receiver<Data>,
680) -> Result<()> {
681    trace!(
682        "Handling client UDP channel {:?} to {}",
683        data_channel,
684        local_addr
685    );
686
687    let port_map: UdpPortMap = Arc::new(DashMap::new());
688
689    loop {
690        let data_channel = data_channel.clone();
691        // Receive data from server via control channel
692        tokio::select! {
693            data = data_rx.recv() => {
694                match data {
695                    Some(data) => {
696                        let external_addr = data.socket_addr.unwrap();
697
698                        if !port_map.contains_key(&external_addr) {
699                            // This packet is from an address we haven't seen for a while,
700                            // which is not in the UdpPortMap.
701                            // So set up a mapping (and a forwarder) for it
702
703                            match udp_connect(&local_addr).await {
704                                Ok(s) => {
705                                    let (to_service_tx, to_service_rx) = mpsc::channel(DATA_CHANNEL_SIZE);
706                                    port_map.insert(external_addr, to_service_tx);
707                                    tokio::spawn(run_udp_forwarder(
708                                        s,
709                                        to_service_rx,
710                                        to_server_tx.clone(),
711                                        external_addr,
712                                        data_channel,
713                                        port_map.clone(),
714                                    ));
715                                }
716                                Err(e) => {
717                                    error!(
718                                        "Failed to create UDP forwarder for {}: {:#}",
719                                        external_addr, e
720                                    );
721                                }
722                            }
723                        }
724
725                        // Now there should be a udp forwarder that can receive the packet
726                        if let Some(tx) = port_map.get(&external_addr) {
727                            let _ = tx.send(data.data).await;
728                        }
729                    }
730                    None => {
731                        trace!("EOF received from server for UDP {:?}", data_channel);
732                        break;
733                    }
734                }
735            }
736            _ = data_channel.closed() => {
737                trace!("Data channel {} closed", data_channel.id);
738                break;
739            }
740        }
741    }
742    Ok(())
743}
744
745// Run a UdpSocket for the visitor `from`
746async fn run_udp_forwarder(
747    s: UdpSocket,
748    mut to_service_rx: mpsc::Receiver<Bytes>,
749    to_server_tx: FairSender<Message>,
750    from: SocketAddr,
751    data_channel: Arc<DataChannel>,
752    port_map: UdpPortMap,
753) -> Result<()> {
754    trace!("UDP forwarder created for {} on {:?}", from, data_channel);
755    let mut buf = vec![0u8; UDP_BUFFER_SIZE];
756
757    loop {
758        tokio::select! {
759            // Receive from the server
760            data = to_service_rx.recv() => {
761                if let Some(data) = data {
762                    s.send(&data).await.with_context(|| "Failed to send UDP traffic to the service")?;
763                    to_server_tx.send(Message::DataChannelAck(
764                        DataChannelAck {
765                            channel_id: data_channel.id,
766                            consumed: data.len() as u32
767                        }
768                    )).await.with_context(|| "Failed to send UDP traffic ack to the server")?;
769                } else {
770                    break;
771                }
772            },
773
774            // Receive from the service
775            val = s.recv(&mut buf) => {
776                let len = match val {
777                    Ok(v) => v,
778                    Err(_) => break
779                };
780
781                if data_channel.wait_for_capacity(len as u32).await.is_err() {
782                    break;
783                }
784
785                to_server_tx.send(Message::DataChannelDataUdp(
786                    DataChannelDataUdp {
787                    channel_id: data_channel.id,
788                    data: buf[..len].to_vec(),
789                    socket_addr: Some(socket_addr_to_proto(&from)),
790                })).await.with_context(|| "Failed to send UDP traffic to the server")?;
791            },
792
793            // No traffic for the duration of UDP_TIMEOUT, clean up the state
794            _ = time::sleep(Duration::from_secs(UDP_TIMEOUT)) => {
795                break;
796            }
797
798            _ = data_channel.closed() => {
799                trace!("Data channel {} closed", data_channel.id);
800                break;
801            }
802        }
803    }
804
805    port_map.remove(&from);
806
807    debug!("UDP forwarder dropped for {} on {:?}", from, data_channel);
808    Ok(())
809}