| 1052 | |
| 1053 | #[cfg(unix)] |
| 1054 | async fn send_daemon_request_line( |
| 1055 | socket_path: &Path, |
| 1056 | handshake: &DaemonHandshake, |
| 1057 | line: &str, |
| 1058 | ) -> Result<Vec<String>> { |
| 1059 | let stream = connect_to_daemon(socket_path).await?; |
| 1060 | let (reader, mut writer) = stream.into_split(); |
| 1061 | |
| 1062 | writer.write_all(handshake.to_line()?.as_bytes()).await?; |
| 1063 | writer.write_all(b"\n").await?; |
| 1064 | writer.write_all(line.as_bytes()).await?; |
| 1065 | if !line.ends_with('\n') { |
| 1066 | writer.write_all(b"\n").await?; |
| 1067 | } |
| 1068 | writer.flush().await?; |
| 1069 | writer.shutdown().await?; |
| 1070 | |
| 1071 | let mut lines = tokio::io::BufReader::new(reader).lines(); |
| 1072 | let request_id = serde_json::from_str::<JsonRpcRequest>(line) |
| 1073 | .ok() |
| 1074 | .and_then(|request| request.id); |
| 1075 | let mut responses = Vec::new(); |
| 1076 | let mut matched_response = request_id.is_none(); |
| 1077 | while let Some(response_line) = lines.next_line().await? { |
| 1078 | if response_line.trim().is_empty() { |
| 1079 | continue; |
| 1080 | } |
| 1081 | let is_matching_response = request_id.as_ref().is_some_and(|id| { |
| 1082 | serde_json::from_str::<serde_json::Value>(&response_line) |
| 1083 | .ok() |
| 1084 | .and_then(|value| value.get("id").cloned()) |
| 1085 | .as_ref() |
| 1086 | == Some(id) |
| 1087 | }); |
| 1088 | responses.push(format!("{response_line}\n")); |
| 1089 | if is_matching_response { |
| 1090 | matched_response = true; |
| 1091 | break; |
| 1092 | } |
| 1093 | } |
| 1094 | if !matched_response { |
| 1095 | return Err(TraceDecayError::Config { |
| 1096 | message: |
| 1097 | "daemon closed the connection before returning a matching response \ |
| 1098 | — it may have been restarted (e.g. by `tracedecay update`); retry the request" |
| 1099 | .to_string(), |
| 1100 | }); |
| 1101 | } |
| 1102 | Ok(responses) |
| 1103 | } |
| 1104 | |
| 1105 | /// Extracts the daemon's advertised version from a proxied `initialize` |
| 1106 | /// response (`result.serverInfo.version`, which daemons have always sent). |