gardesk/garwarp / 0f82106

Browse files

add error codes to control protocol

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
0f821068e5b16b1e52b9c9bc14ddebded4834d73
Parents
33bdd6d
Tree
4c1a3d9

3 changed files

StatusFile+-
M garwarp-ipc/src/lib.rs 28 9
M garwarp/src/daemon.rs 7 0
M garwarpctl/src/main.rs 12 12
garwarp-ipc/src/lib.rsmodified
@@ -193,7 +193,7 @@ pub enum ControlResponse {
193193
     Status(StatusResponse),
194194
     AckStopping,
195195
     AckRequest { id: String, state: String },
196
-    Error { reason: String },
196
+    Error { code: u32, reason: String },
197197
 }
198198
 
199199
 impl ControlResponse {
@@ -210,7 +210,7 @@ impl ControlResponse {
210210
             Self::AckRequest { id, state } => {
211211
                 format!("ack request id={} state={}\n", id, state)
212212
             }
213
-            Self::Error { reason } => format!("error reason={}\n", reason),
213
+            Self::Error { code, reason } => format!("error code={} reason={}\n", code, reason),
214214
         }
215215
     }
216216
 
@@ -286,15 +286,30 @@ impl ControlResponse {
286286
                 None => Err(ParseError::MissingField("ack")),
287287
             },
288288
             Some("error") => match parts.next() {
289
-                Some(reason_field) => {
290
-                    let (key, value) = reason_field
291
-                        .split_once('=')
292
-                        .ok_or(ParseError::InvalidField(reason_field.to_string()))?;
293
-                    if key != "reason" {
294
-                        return Err(ParseError::InvalidField(reason_field.to_string()));
289
+                Some(first_field) => {
290
+                    let mut code = None;
291
+                    let mut reason = None;
292
+                    let mut fields = vec![first_field];
293
+                    fields.extend(parts);
294
+
295
+                    for field in fields {
296
+                        let (key, value) = field
297
+                            .split_once('=')
298
+                            .ok_or(ParseError::InvalidField(field.to_string()))?;
299
+                        match key {
300
+                            "code" => {
301
+                                code =
302
+                                    Some(value.parse::<u32>().map_err(|_| {
303
+                                        ParseError::InvalidField(field.to_string())
304
+                                    })?);
305
+                            }
306
+                            "reason" => reason = Some(value.to_string()),
307
+                            _ => return Err(ParseError::InvalidField(field.to_string())),
308
+                        }
295309
                     }
296310
                     Ok(Self::Error {
297
-                        reason: value.to_string(),
311
+                        code: code.ok_or(ParseError::MissingField("code"))?,
312
+                        reason: reason.ok_or(ParseError::MissingField("reason"))?,
298313
                     })
299314
                 }
300315
                 None => Err(ParseError::MissingField("reason")),
@@ -389,6 +404,10 @@ mod tests {
389404
                 id: "req-1".to_string(),
390405
                 state: "pending".to_string(),
391406
             },
407
+            ControlResponse::Error {
408
+                code: 2,
409
+                reason: "invalid_request".to_string(),
410
+            },
392411
         ] {
393412
             let line = response.to_line();
394413
             let parsed = ControlResponse::parse_line(&line).expect("response should parse");
garwarp/src/daemon.rsmodified
@@ -127,6 +127,7 @@ fn handle_connection(stream: UnixStream, state: &mut DaemonState) -> io::Result<
127127
                     return write_response(
128128
                         reader.into_inner(),
129129
                         ControlResponse::Error {
130
+                            code: mapping.code as u32,
130131
                             reason: mapping.reason.to_string(),
131132
                         },
132133
                     );
@@ -144,6 +145,7 @@ fn handle_connection(stream: UnixStream, state: &mut DaemonState) -> io::Result<
144145
                 Err(error) => {
145146
                     let mapping = map_request_error(&error);
146147
                     ControlResponse::Error {
148
+                        code: mapping.code as u32,
147149
                         reason: mapping.reason.to_string(),
148150
                     }
149151
                 }
@@ -165,6 +167,7 @@ fn handle_connection(stream: UnixStream, state: &mut DaemonState) -> io::Result<
165167
                 Err(error) => {
166168
                     let mapping = map_request_error(&error);
167169
                     ControlResponse::Error {
170
+                        code: mapping.code as u32,
168171
                         reason: mapping.reason.to_string(),
169172
                     }
170173
                 }
@@ -173,6 +176,7 @@ fn handle_connection(stream: UnixStream, state: &mut DaemonState) -> io::Result<
173176
         None => {
174177
             let mapping = map_portal_error(&PortalError::InvalidRequestPayload);
175178
             ControlResponse::Error {
179
+                code: mapping.code as u32,
176180
                 reason: mapping.reason.to_string(),
177181
             }
178182
         }
@@ -336,6 +340,7 @@ mod tests {
336340
         assert_eq!(
337341
             response,
338342
             ControlResponse::Error {
343
+                code: 2,
339344
                 reason: "invalid_request".to_string(),
340345
             }
341346
         );
@@ -399,6 +404,7 @@ mod tests {
399404
         assert_eq!(
400405
             response,
401406
             ControlResponse::Error {
407
+                code: 2,
402408
                 reason: "invalid_parent_window".to_string(),
403409
             }
404410
         );
@@ -436,6 +442,7 @@ mod tests {
436442
         assert_eq!(
437443
             response,
438444
             ControlResponse::Error {
445
+                code: 2,
439446
                 reason: "ownership_mismatch".to_string(),
440447
             }
441448
         );
garwarpctl/src/main.rsmodified
@@ -169,9 +169,9 @@ fn run(command: Command) -> io::Result<()> {
169169
                     println!("in_flight={}", status.in_flight_requests);
170170
                     Ok(())
171171
                 }
172
-                ControlResponse::Error { reason } => {
173
-                    Err(io::Error::other(format!("daemon error: {reason}")))
174
-                }
172
+                ControlResponse::Error { code, reason } => Err(io::Error::other(format!(
173
+                    "daemon error: code={code} reason={reason}"
174
+                ))),
175175
                 other => Err(io::Error::new(
176176
                     io::ErrorKind::InvalidData,
177177
                     format!("unexpected response: {other:?}"),
@@ -185,9 +185,9 @@ fn run(command: Command) -> io::Result<()> {
185185
                     println!("stopping");
186186
                     Ok(())
187187
                 }
188
-                ControlResponse::Error { reason } => {
189
-                    Err(io::Error::other(format!("daemon error: {reason}")))
190
-                }
188
+                ControlResponse::Error { code, reason } => Err(io::Error::other(format!(
189
+                    "daemon error: code={code} reason={reason}"
190
+                ))),
191191
                 other => Err(io::Error::new(
192192
                     io::ErrorKind::InvalidData,
193193
                     format!("unexpected response: {other:?}"),
@@ -212,9 +212,9 @@ fn run(command: Command) -> io::Result<()> {
212212
                     println!("state={state}");
213213
                     Ok(())
214214
                 }
215
-                ControlResponse::Error { reason } => {
216
-                    Err(io::Error::other(format!("daemon error: {reason}")))
217
-                }
215
+                ControlResponse::Error { code, reason } => Err(io::Error::other(format!(
216
+                    "daemon error: code={code} reason={reason}"
217
+                ))),
218218
                 other => Err(io::Error::new(
219219
                     io::ErrorKind::InvalidData,
220220
                     format!("unexpected response: {other:?}"),
@@ -239,9 +239,9 @@ fn run(command: Command) -> io::Result<()> {
239239
                     println!("state={state}");
240240
                     Ok(())
241241
                 }
242
-                ControlResponse::Error { reason } => {
243
-                    Err(io::Error::other(format!("daemon error: {reason}")))
244
-                }
242
+                ControlResponse::Error { code, reason } => Err(io::Error::other(format!(
243
+                    "daemon error: code={code} reason={reason}"
244
+                ))),
245245
                 other => Err(io::Error::new(
246246
                     io::ErrorKind::InvalidData,
247247
                     format!("unexpected response: {other:?}"),