debugger/ipc/
transport.rs1use std::io;
7use tokio::io::{AsyncReadExt, AsyncWriteExt};
8
9use crate::common::paths;
10
11const MAX_MESSAGE_SIZE: u32 = 10 * 1024 * 1024;
13
14#[cfg(unix)]
16pub mod platform {
17 pub use interprocess::local_socket::tokio::{
18 prelude::*,
19 Listener, Stream,
20 };
21 pub use interprocess::local_socket::{
22 GenericFilePath, ListenerOptions,
23 };
24}
25
26#[cfg(windows)]
27pub mod platform {
28 pub use interprocess::local_socket::tokio::{
29 prelude::*,
30 Listener, Stream,
31 };
32 pub use interprocess::local_socket::{
33 GenericNamespaced, ListenerOptions,
34 };
35}
36
37use platform::*;
38
39pub use platform::Stream;
41
42pub async fn create_listener() -> io::Result<Listener> {
44 paths::ensure_socket_dir()?;
46 paths::remove_socket()?;
47
48 let name = paths::socket_name();
49
50 #[cfg(unix)]
51 let listener = {
52 let name = name.to_fs_name::<GenericFilePath>()?;
53 ListenerOptions::new()
54 .name(name)
55 .create_tokio()?
56 };
57
58 #[cfg(windows)]
59 let listener = {
60 let name = name.to_ns_name::<GenericNamespaced>()?;
61 ListenerOptions::new()
62 .name(name)
63 .create_tokio()?
64 };
65
66 #[cfg(unix)]
68 {
69 use std::os::unix::fs::PermissionsExt;
70 let path = paths::socket_path();
71 std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o600))?;
72 }
73
74 Ok(listener)
75}
76
77pub async fn connect() -> io::Result<Stream> {
79 let name = paths::socket_name();
80
81 #[cfg(unix)]
82 let stream = {
83 let name = name.to_fs_name::<GenericFilePath>()?;
84 Stream::connect(name).await?
85 };
86
87 #[cfg(windows)]
88 let stream = {
89 let name = name.to_ns_name::<GenericNamespaced>()?;
90 Stream::connect(name).await?
91 };
92
93 Ok(stream)
94}
95
96pub async fn send_message<W: AsyncWriteExt + Unpin>(
98 writer: &mut W,
99 data: &[u8],
100) -> io::Result<()> {
101 if data.len() > MAX_MESSAGE_SIZE as usize {
102 return Err(io::Error::new(
103 io::ErrorKind::InvalidInput,
104 "Message too large",
105 ));
106 }
107
108 let len = data.len() as u32;
109 writer.write_all(&len.to_le_bytes()).await?;
110 writer.write_all(data).await?;
111 writer.flush().await?;
112 Ok(())
113}
114
115pub async fn recv_message<R: AsyncReadExt + Unpin>(reader: &mut R) -> io::Result<Vec<u8>> {
117 let mut len_buf = [0u8; 4];
118 reader.read_exact(&mut len_buf).await?;
119 let len = u32::from_le_bytes(len_buf);
120
121 if len > MAX_MESSAGE_SIZE {
122 return Err(io::Error::new(
123 io::ErrorKind::InvalidData,
124 format!("Message too large: {} bytes", len),
125 ));
126 }
127
128 let mut data = vec![0u8; len as usize];
129 reader.read_exact(&mut data).await?;
130 Ok(data)
131}
132
133pub fn socket_exists() -> bool {
135 #[cfg(unix)]
136 {
137 paths::socket_path().exists()
138 }
139
140 #[cfg(windows)]
141 {
142 true
145 }
146}