diff options
Diffstat (limited to 'src/requests/start.rs')
-rw-r--r-- | src/requests/start.rs | 113 |
1 files changed, 79 insertions, 34 deletions
diff --git a/src/requests/start.rs b/src/requests/start.rs index d0c4411..882b154 100644 --- a/src/requests/start.rs +++ b/src/requests/start.rs | |||
@@ -1,29 +1,19 @@ | |||
1 | use std::time::Duration; | ||
2 | |||
3 | use futures_util::{StreamExt, SinkExt}; | 1 | use futures_util::{StreamExt, SinkExt}; |
4 | use indicatif::{ProgressBar, ProgressStyle}; | 2 | use indicatif::MultiProgress; |
5 | use reqwest::StatusCode; | 3 | use reqwest::StatusCode; |
6 | use serde::Deserialize; | 4 | use serde::Deserialize; |
7 | use tokio_tungstenite::{connect_async, tungstenite::Message}; | 5 | use tokio_tungstenite::{connect_async, tungstenite::Message}; |
8 | 6 | ||
9 | use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols}; | 7 | use crate::{error::CliError, default_headers, ErrorResponse, format_url, Protocols, OVERVIEW_STYLE, DEFAULT_STYLE, DONE_STYLE, finish_pb, ERROR_STYLE, OVERVIEW_ERROR, OVERVIEW_DONE, add_pb}; |
10 | 8 | ||
11 | pub async fn start(id: String, ping: bool) -> Result<(), CliError> { | 9 | pub async fn start(id: String, ping: bool) -> Result<(), CliError> { |
12 | 10 | ||
13 | let send_start = ProgressBar::new(1); | 11 | let send_start = MultiProgress::new(); |
12 | let overview = add_pb(&send_start, OVERVIEW_STYLE, format!("start {}", id)); | ||
14 | 13 | ||
15 | // TODO: calculate average start-time on server | 14 | // TODO: calculate average start-time on server |
16 | send_start.set_style( | ||
17 | ProgressStyle::with_template("{spinner:.green} ({elapsed}) {wide_msg}") | ||
18 | .unwrap() | ||
19 | .tick_chars("|/-\\\\") | ||
20 | ); | ||
21 | |||
22 | let url = format_url("start", Protocols::Http)?; | 15 | let url = format_url("start", Protocols::Http)?; |
23 | 16 | let connect = add_pb(&send_start, DEFAULT_STYLE, format!("connect to {}", url)); | |
24 | send_start.set_message(format!("connect to {}", url)); | ||
25 | send_start.enable_steady_tick(Duration::from_millis(125)); | ||
26 | |||
27 | let res = reqwest::Client::new() | 17 | let res = reqwest::Client::new() |
28 | .post(url) | 18 | .post(url) |
29 | .headers(default_headers()?) | 19 | .headers(default_headers()?) |
@@ -33,7 +23,9 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { | |||
33 | .send() | 23 | .send() |
34 | .await | 24 | .await |
35 | .map_err(CliError::Reqwest)?; | 25 | .map_err(CliError::Reqwest)?; |
26 | finish_pb(connect, "connected, got response".to_string(), DONE_STYLE); | ||
36 | 27 | ||
28 | let res_pb = add_pb(&send_start, DEFAULT_STYLE, "analyzing response".to_string()); | ||
37 | match res.status() { | 29 | match res.status() { |
38 | StatusCode::OK => { | 30 | StatusCode::OK => { |
39 | let body = serde_json::from_str::<StartResponse>( | 31 | let body = serde_json::from_str::<StartResponse>( |
@@ -42,11 +34,16 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { | |||
42 | .map_err(CliError::Serde)?; | 34 | .map_err(CliError::Serde)?; |
43 | 35 | ||
44 | if body.boot { | 36 | if body.boot { |
45 | send_start.println("connected, sent start packet"); | 37 | finish_pb(res_pb, "sent start packet".to_string(), DONE_STYLE); |
46 | } | 38 | } |
47 | 39 | ||
48 | if ping { | 40 | if ping { |
49 | send_start.println(status_socket(body.uuid, &send_start).await?.to_string()); | 41 | let status = status_socket(body.uuid, &send_start).await?; |
42 | if status { | ||
43 | finish_pb(overview, format!("successfully started {}", body.id), OVERVIEW_DONE); | ||
44 | } else { | ||
45 | finish_pb(overview, format!("error while starting {}", body.id), OVERVIEW_ERROR); | ||
46 | } | ||
50 | } | 47 | } |
51 | }, | 48 | }, |
52 | _ => { | 49 | _ => { |
@@ -55,37 +52,63 @@ pub async fn start(id: String, ping: bool) -> Result<(), CliError> { | |||
55 | ) | 52 | ) |
56 | .map_err(CliError::Serde)?; | 53 | .map_err(CliError::Serde)?; |
57 | 54 | ||
58 | println!("got error: {}", body.error); | 55 | res_pb.finish_with_message(format!("✗ got error: {}", body.error)); |
59 | } | 56 | } |
60 | } | 57 | } |
61 | 58 | ||
62 | Ok(()) | 59 | Ok(()) |
63 | } | 60 | } |
64 | 61 | ||
65 | async fn status_socket(uuid: String, pb: &ProgressBar) -> Result<bool, CliError> { | 62 | async fn status_socket(uuid: String, pb: &MultiProgress) -> Result<bool, CliError> { |
66 | pb.set_message("setup websocket"); | 63 | // TODO: Remove unwraps |
67 | 64 | let ws_pb = add_pb(pb, DEFAULT_STYLE, "connect to websocket".to_string()); | |
68 | let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) | 65 | let (mut ws_stream, _response) = connect_async(format_url("status", Protocols::Websocket)?) |
69 | .await | 66 | .await |
70 | .expect("Failed to connect"); | 67 | .expect("Failed to connect"); |
71 | pb.println("connected to websocket"); | 68 | finish_pb(ws_pb, "connected to websocket".to_string(), DONE_STYLE); |
72 | 69 | ||
73 | pb.set_message("send uuid message"); | 70 | ws_stream.send(Message::Text(uuid.clone())).await.unwrap(); |
74 | ws_stream.send(Message::Text(uuid)).await.unwrap(); | ||
75 | pb.println("sent uuid message"); | ||
76 | 71 | ||
77 | pb.set_message("wait for message"); | 72 | let msg_pb = add_pb(pb, DEFAULT_STYLE, "await message".to_string()); |
78 | let msg = ws_stream.next().await.unwrap(); | 73 | let msg = ws_stream.next().await.unwrap(); |
74 | finish_pb(msg_pb, "received message".to_string(), DONE_STYLE); | ||
79 | 75 | ||
80 | pb.println(format!("msg: {:?}", msg)); | ||
81 | |||
82 | ws_stream.close(None).await.unwrap(); | 76 | ws_stream.close(None).await.unwrap(); |
83 | pb.println("connection closed"); | ||
84 | // TODO: Check for correct UUID and timeout | ||
85 | pb.set_message("verifying message"); | ||
86 | if msg.is_ok() { return Ok(true) } | ||
87 | 77 | ||
88 | Ok(false) | 78 | let v_pb = add_pb(pb, DEFAULT_STYLE, "verify response".to_string()); |
79 | let res = verify_response(msg.unwrap().to_string(), uuid)?; | ||
80 | match res { | ||
81 | Verified::WrongUuid => { | ||
82 | finish_pb(v_pb, "returned wrong uuid".to_string(), ERROR_STYLE); | ||
83 | Ok(false) | ||
84 | }, | ||
85 | Verified::ResponseType(res_type) => { | ||
86 | match res_type { | ||
87 | ResponseType::Start => { | ||
88 | finish_pb(v_pb, "device started".to_string(), DONE_STYLE); | ||
89 | Ok(true) | ||
90 | }, | ||
91 | ResponseType::Timeout => { | ||
92 | finish_pb(v_pb, "ping timed out".to_string(), ERROR_STYLE); | ||
93 | Ok(false) | ||
94 | }, | ||
95 | ResponseType::NotFound => { | ||
96 | finish_pb(v_pb, "unknown uuid".to_string(), ERROR_STYLE); | ||
97 | Ok(false) | ||
98 | }, | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | fn verify_response(res: String, org_uuid: String) -> Result<Verified, CliError> { | ||
105 | let spl: Vec<&str> = res.split('_').collect(); | ||
106 | let res_type = spl[0]; | ||
107 | let uuid = spl[1]; | ||
108 | |||
109 | if uuid != org_uuid { return Ok(Verified::WrongUuid) }; | ||
110 | |||
111 | Ok(Verified::ResponseType(ResponseType::from(res_type)?)) | ||
89 | } | 112 | } |
90 | 113 | ||
91 | #[derive(Debug, Deserialize)] | 114 | #[derive(Debug, Deserialize)] |
@@ -94,3 +117,25 @@ struct StartResponse { | |||
94 | id: String, | 117 | id: String, |
95 | uuid: String, | 118 | uuid: String, |
96 | } | 119 | } |
120 | |||
121 | enum Verified { | ||
122 | ResponseType(ResponseType), | ||
123 | WrongUuid | ||
124 | } | ||
125 | |||
126 | enum ResponseType { | ||
127 | Start, | ||
128 | Timeout, | ||
129 | NotFound, | ||
130 | } | ||
131 | |||
132 | impl ResponseType { | ||
133 | fn from(value: &str) -> Result<Self, CliError> { | ||
134 | match value { | ||
135 | "start" => Ok(ResponseType::Start), | ||
136 | "timeout" => Ok(ResponseType::Timeout), | ||
137 | "notfound" => Ok(ResponseType::NotFound), | ||
138 | _ => Err(CliError::WsResponse), | ||
139 | } | ||
140 | } | ||
141 | } | ||