speedtest/
server.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::socket;
6use fidl::endpoints::{ControlHandle as _, Responder as _};
7use log::{error, warn};
8use {fidl_fuchsia_developer_ffx_speedtest as fspeedtest, fuchsia_async as fasync};
9
10pub struct Server {
11    scope: fasync::Scope,
12}
13
14impl Default for Server {
15    fn default() -> Self {
16        Self::new(fasync::Scope::new_with_name("speedtest-server"))
17    }
18}
19
20impl Server {
21    pub fn new(scope: fasync::Scope) -> Self {
22        Self { scope }
23    }
24
25    pub fn handle_request(&self, req: fspeedtest::SpeedtestRequest) -> Result<(), fidl::Error> {
26        match req {
27            fspeedtest::SpeedtestRequest::Ping { responder } => responder.send()?,
28            fspeedtest::SpeedtestRequest::SocketDown { socket, params, responder } => {
29                let socket = fasync::Socket::from_socket(socket);
30                match params.try_into() {
31                    Ok(params) => {
32                        let _: fasync::JoinHandle<()> = self.scope.spawn(async move {
33                            let report = socket::Transfer { socket, params }.receive().await;
34                            match report {
35                                Ok(report) => responder.send(&report.into()).unwrap_or_else(|e| {
36                                    if !e.is_closed() {
37                                        error!("error responding to transfer {e:?}")
38                                    }
39                                }),
40                                Err(e) => {
41                                    error!("SocketDown failed with {e:?}");
42                                    responder
43                                        .control_handle()
44                                        .shutdown_with_epitaph(zx_status::Status::INTERNAL);
45                                }
46                            }
47                        });
48                    }
49                    Err(e) => {
50                        error!("error initiating transfer: {e:?}");
51                        responder
52                            .control_handle()
53                            .shutdown_with_epitaph(zx_status::Status::INVALID_ARGS);
54                    }
55                }
56            }
57            fspeedtest::SpeedtestRequest::SocketUp { socket, params, responder } => {
58                let socket = fasync::Socket::from_socket(socket);
59                match params.try_into() {
60                    Ok(params) => {
61                        let _: fasync::JoinHandle<()> = self.scope.spawn(async move {
62                            let report = socket::Transfer { socket, params }.send().await;
63                            match report {
64                                Ok(report) => responder.send(&report.into()).unwrap_or_else(|e| {
65                                    if !e.is_closed() {
66                                        error!("error responding to transfer {e:?}")
67                                    }
68                                }),
69                                Err(e) => {
70                                    error!("SocketUp failed with {e:?}");
71                                    responder
72                                        .control_handle()
73                                        .shutdown_with_epitaph(zx_status::Status::INTERNAL);
74                                }
75                            }
76                        });
77                    }
78                    Err(e) => {
79                        error!("error initiating transfer: {e:?}");
80                        responder
81                            .control_handle()
82                            .shutdown_with_epitaph(zx_status::Status::INVALID_ARGS);
83                    }
84                }
85            }
86            fspeedtest::SpeedtestRequest::_UnknownMethod { ordinal, .. } => {
87                warn!("ignoring unknown method {ordinal}");
88            }
89        }
90        Ok(())
91    }
92}