pharos_runtime_core/connection.rs
1use std::io::{Read, Write};
2use std::net::{Shutdown, TcpListener, TcpStream};
3#[cfg(unix)]
4use std::os::unix::net::UnixStream;
5
6#[derive(Debug, Clone, Copy, Eq, PartialEq)]
7/// Transport families supported by the native connection wrapper.
8///
9/// # Variants
10///
11/// - `Unknown`: Supported `NativeTransportType` variant.
12/// - `Tcp`: Supported `NativeTransportType` variant.
13/// - `Unix`: Supported `NativeTransportType` variant.
14///
15/// # Examples
16///
17/// ```rust,ignore
18/// let _ = pharos_runtime_core::connection::NativeTransportType::Unknown;
19/// ```
20///
21/// # Related
22///
23/// - [`crate::connection`] for constructors, helpers, and neighboring runtime types.
24pub enum NativeTransportType {
25 Unknown,
26 Tcp,
27 Unix,
28}
29
30enum NativeConnectionStream {
31 Tcp(TcpStream),
32 #[cfg(unix)]
33 Unix(UnixStream),
34}
35
36/// Native connection wrapper used by the runtime for TCP and Unix transports.
37///
38/// # Fields
39///
40/// - `fd`: Stored field on `NativeConnection`.
41/// - `write_fd`: Stored field on `NativeConnection`.
42/// - `close_fds`: Stored field on `NativeConnection`.
43/// - `transport_type`: Stored field on `NativeConnection`.
44/// - `peer_info`: Stored field on `NativeConnection`.
45/// - `local_info`: Stored field on `NativeConnection`.
46///
47/// # Examples
48///
49/// ```rust,ignore
50/// let _ = std::mem::size_of::<pharos_runtime_core::connection::NativeConnection>();
51/// ```
52///
53/// # Related
54///
55/// - [`crate::connection`] for constructors, helpers, and neighboring runtime types.
56pub struct NativeConnection {
57 pub fd: i32,
58 pub write_fd: i32,
59 pub close_fds: bool,
60 pub transport_type: NativeTransportType,
61 pub peer_info: Option<String>,
62 pub local_info: Option<String>,
63 stream: Option<NativeConnectionStream>,
64}
65
66impl NativeConnection {
67 /// Performs metadata only.
68 ///
69 /// # Parameters
70 ///
71 /// - `transport_type`: Input consumed by [`crate::connection::metadata_only`].
72 /// - `peer_info`: Input consumed by [`crate::connection::metadata_only`].
73 /// - `local_info`: Input consumed by [`crate::connection::metadata_only`].
74 ///
75 /// # Returns
76 ///
77 /// Returns the computed value produced by [`crate::connection::metadata_only`].
78 ///
79 /// # Examples
80 ///
81 /// ```rust,ignore
82 /// let _result = pharos_runtime_core::connection::metadata_only(todo!(), todo!(), todo!());
83 /// ```
84 ///
85 /// # Related
86 ///
87 /// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
88 pub fn metadata_only(
89 transport_type: NativeTransportType,
90 peer_info: Option<String>,
91 local_info: Option<String>,
92 ) -> Self {
93 Self {
94 fd: -1,
95 write_fd: -1,
96 close_fds: true,
97 transport_type,
98 peer_info,
99 local_info,
100 stream: None,
101 }
102 }
103
104 /// Performs from TCP stream.
105 ///
106 /// # Parameters
107 ///
108 /// - `stream`: Input consumed by [`crate::connection::from_tcp_stream`].
109 ///
110 /// # Returns
111 ///
112 /// Returns the computed value produced by [`crate::connection::from_tcp_stream`].
113 ///
114 /// # Examples
115 ///
116 /// ```rust,ignore
117 /// let _result = pharos_runtime_core::connection::from_tcp_stream(todo!());
118 /// ```
119 ///
120 /// # Related
121 ///
122 /// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
123 pub fn from_tcp_stream(stream: TcpStream) -> Self {
124 let peer_info = stream.peer_addr().ok().map(|value| value.to_string());
125 let local_info = stream.local_addr().ok().map(|value| value.to_string());
126 Self {
127 fd: 0,
128 write_fd: 0,
129 close_fds: true,
130 transport_type: NativeTransportType::Tcp,
131 peer_info,
132 local_info,
133 stream: Some(NativeConnectionStream::Tcp(stream)),
134 }
135 }
136
137 #[cfg(unix)]
138 /// Wraps a Unix-domain stream in a [`NativeConnection`].
139 ///
140 /// # Parameters
141 ///
142 /// - `stream`: Input consumed by [`crate::connection::from_unix_stream`].
143 ///
144 /// # Returns
145 ///
146 /// Returns the computed value produced by [`crate::connection::from_unix_stream`].
147 ///
148 /// # Examples
149 ///
150 /// ```rust,ignore
151 /// let _result = pharos_runtime_core::connection::from_unix_stream(todo!());
152 /// ```
153 ///
154 /// # Related
155 ///
156 /// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
157 pub fn from_unix_stream(stream: UnixStream) -> Self {
158 let peer_info = Some(
159 stream
160 .peer_addr()
161 .ok()
162 .and_then(|value| {
163 value
164 .as_pathname()
165 .map(|path| path.to_string_lossy().into_owned())
166 })
167 .unwrap_or_else(|| "unix".to_owned()),
168 );
169 let local_info = Some(
170 stream
171 .local_addr()
172 .ok()
173 .and_then(|value| {
174 value
175 .as_pathname()
176 .map(|path| path.to_string_lossy().into_owned())
177 })
178 .unwrap_or_else(|| "unix".to_owned()),
179 );
180 Self {
181 fd: 0,
182 write_fd: 0,
183 close_fds: true,
184 transport_type: NativeTransportType::Unix,
185 peer_info,
186 local_info,
187 stream: Some(NativeConnectionStream::Unix(stream)),
188 }
189 }
190}
191
192/// Initializes a metadata-only connection before a transport is attached.
193///
194/// # Parameters
195///
196/// - `transport_type`: Input consumed by [`crate::connection::connection_init`].
197/// - `peer_info`: Input consumed by [`crate::connection::connection_init`].
198/// - `local_info`: Input consumed by [`crate::connection::connection_init`].
199///
200/// # Returns
201///
202/// Returns the computed value produced by [`crate::connection::connection_init`].
203///
204/// # Examples
205///
206/// ```rust,ignore
207/// let _result = pharos_runtime_core::connection::connection_init(todo!(), todo!(), todo!());
208/// ```
209///
210/// # Related
211///
212/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
213pub fn connection_init(
214 transport_type: NativeTransportType,
215 peer_info: Option<String>,
216 local_info: Option<String>,
217) -> NativeConnection {
218 NativeConnection::metadata_only(transport_type, peer_info, local_info)
219}
220
221/// Performs connection flush.
222///
223/// # Parameters
224///
225/// - `connection`: Input consumed by [`crate::connection::connection_flush`].
226///
227/// # Returns
228///
229/// Returns the computed value produced by [`crate::connection::connection_flush`].
230///
231/// # Examples
232///
233/// ```rust,ignore
234/// let _result = pharos_runtime_core::connection::connection_flush(todo!());
235/// ```
236///
237/// # Related
238///
239/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
240pub fn connection_flush(connection: &mut NativeConnection) -> i32 {
241 match connection.stream.as_mut() {
242 Some(NativeConnectionStream::Tcp(stream)) => stream.flush().map(|_| 0).unwrap_or(69),
243 #[cfg(unix)]
244 Some(NativeConnectionStream::Unix(stream)) => stream.flush().map(|_| 0).unwrap_or(69),
245 None => 0,
246 }
247}
248
249/// Formats endpoint text without exposing platform socket handles or FFI state.
250///
251/// # Parameters
252///
253/// - `endpoint`: Input consumed by [`crate::connection::connection_format_sockaddr`].
254///
255/// # Returns
256///
257/// Returns the computed value produced by [`crate::connection::connection_format_sockaddr`].
258///
259/// # Examples
260///
261/// ```rust,ignore
262/// let _result = pharos_runtime_core::connection::connection_format_sockaddr("127.0.0.1:8080");
263/// ```
264///
265/// # Related
266///
267/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
268pub fn connection_format_sockaddr(endpoint: Option<&str>) -> String {
269 endpoint
270 .map(str::trim)
271 .filter(|value| !value.is_empty())
272 .unwrap_or("unknown")
273 .to_owned()
274}
275
276/// Reads at most one caller-provided buffer from the attached transport.
277///
278/// # Parameters
279///
280/// - `connection`: Input consumed by [`crate::connection::connection_read`].
281/// - `buffer`: Input consumed by [`crate::connection::connection_read`].
282///
283/// # Returns
284///
285/// Returns the computed value produced by [`crate::connection::connection_read`].
286///
287/// # Examples
288///
289/// ```rust,ignore
290/// let _result = pharos_runtime_core::connection::connection_read(todo!(), &mut []);
291/// ```
292///
293/// # Related
294///
295/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
296pub fn connection_read(connection: &mut NativeConnection, buffer: &mut [u8]) -> i32 {
297 if buffer.is_empty() {
298 return 0;
299 }
300 match connection.stream.as_mut() {
301 Some(NativeConnectionStream::Tcp(stream)) => {
302 stream.read(buffer).map(|count| count as i32).unwrap_or(-1)
303 }
304 #[cfg(unix)]
305 Some(NativeConnectionStream::Unix(stream)) => {
306 stream.read(buffer).map(|count| count as i32).unwrap_or(-1)
307 }
308 None => -1,
309 }
310}
311
312/// Writes one complete caller-provided buffer to the attached transport.
313///
314/// # Parameters
315///
316/// - `connection`: Input consumed by [`crate::connection::connection_write`].
317/// - `buffer`: Input consumed by [`crate::connection::connection_write`].
318///
319/// # Returns
320///
321/// Returns the computed value produced by [`crate::connection::connection_write`].
322///
323/// # Examples
324///
325/// ```rust,ignore
326/// let _result = pharos_runtime_core::connection::connection_write(todo!(), &mut []);
327/// ```
328///
329/// # Related
330///
331/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
332pub fn connection_write(connection: &mut NativeConnection, buffer: &[u8]) -> i32 {
333 if buffer.is_empty() {
334 return 0;
335 }
336 match connection.stream.as_mut() {
337 Some(NativeConnectionStream::Tcp(stream)) => {
338 stream.write(buffer).map(|count| count as i32).unwrap_or(-1)
339 }
340 #[cfg(unix)]
341 Some(NativeConnectionStream::Unix(stream)) => {
342 stream.write(buffer).map(|count| count as i32).unwrap_or(-1)
343 }
344 None => -1,
345 }
346}
347
348/// Accepts the next TCP connection from a native listener.
349///
350/// # Parameters
351///
352/// - `listener`: Input consumed by [`crate::connection::connection_accept_next`].
353///
354/// # Returns
355///
356/// Returns the successful value produced by [`crate::connection::connection_accept_next`] or an error when the operation fails.
357///
358/// # Errors
359///
360/// Returns an error value when [`crate::connection::connection_accept_next`] cannot complete successfully.
361///
362/// # Examples
363///
364/// ```rust,ignore
365/// let _result = pharos_runtime_core::connection::connection_accept_next(todo!());
366/// ```
367///
368/// # Related
369///
370/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
371pub fn connection_accept_next(listener: &TcpListener) -> Result<NativeConnection, i32> {
372 listener
373 .accept()
374 .map(|(stream, _)| NativeConnection::from_tcp_stream(stream))
375 .map_err(|_| 71)
376}
377
378/// Closes one connection and clears its owned stream.
379///
380/// # Parameters
381///
382/// - `connection`: Input consumed by [`crate::connection::connection_close`].
383///
384/// # Returns
385///
386/// Returns the computed value produced by [`crate::connection::connection_close`].
387///
388/// # Examples
389///
390/// ```rust,ignore
391/// let _result = pharos_runtime_core::connection::connection_close(todo!());
392/// ```
393///
394/// # Related
395///
396/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
397pub fn connection_close(connection: &mut NativeConnection) -> i32 {
398 let status = connection_shutdown(connection);
399 connection.stream = None;
400 connection.fd = -1;
401 connection.write_fd = -1;
402 status
403}
404
405/// Applies bounded read and write timeouts to a native connection.
406///
407/// # Parameters
408///
409/// - `connection`: Input consumed by [`crate::connection::connection_apply_timeouts`].
410/// - `read_ms`: Input consumed by [`crate::connection::connection_apply_timeouts`].
411/// - `write_ms`: Input consumed by [`crate::connection::connection_apply_timeouts`].
412///
413/// # Returns
414///
415/// Returns the computed value produced by [`crate::connection::connection_apply_timeouts`].
416///
417/// # Examples
418///
419/// ```rust,ignore
420/// let _result = pharos_runtime_core::connection::connection_apply_timeouts(todo!(), todo!(), todo!());
421/// ```
422///
423/// # Related
424///
425/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
426pub fn connection_apply_timeouts(
427 connection: &mut NativeConnection,
428 read_ms: Option<u64>,
429 write_ms: Option<u64>,
430) -> i32 {
431 let result = match connection.stream.as_mut() {
432 Some(NativeConnectionStream::Tcp(stream)) => {
433 let read = read_ms
434 .map(std::time::Duration::from_millis)
435 .map(|value| stream.set_read_timeout(Some(value)));
436 let write = write_ms
437 .map(std::time::Duration::from_millis)
438 .map(|value| stream.set_write_timeout(Some(value)));
439 read.into_iter().chain(write).all(|result| result.is_ok())
440 }
441 #[cfg(unix)]
442 Some(NativeConnectionStream::Unix(stream)) => {
443 let read = read_ms
444 .map(std::time::Duration::from_millis)
445 .map(|value| stream.set_read_timeout(Some(value)));
446 let write = write_ms
447 .map(std::time::Duration::from_millis)
448 .map(|value| stream.set_write_timeout(Some(value)));
449 read.into_iter().chain(write).all(|result| result.is_ok())
450 }
451 None => true,
452 };
453 i32::from(!result)
454}
455
456/// Closes the underlying socket transport.
457///
458/// # Parameters
459///
460/// - `connection`: Input consumed by [`crate::connection::connection_close_socket`].
461///
462/// # Returns
463///
464/// Returns the computed value produced by [`crate::connection::connection_close_socket`].
465///
466/// # Examples
467///
468/// ```rust,ignore
469/// let _result = pharos_runtime_core::connection::connection_close_socket(todo!());
470/// ```
471///
472/// # Related
473///
474/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
475pub fn connection_close_socket(connection: &mut NativeConnection) -> i32 {
476 connection_close(connection)
477}
478
479/// Shuts down both directions of the attached socket and preserves close semantics.
480///
481/// # Parameters
482///
483/// - `connection`: Input consumed by [`crate::connection::connection_shutdown_socket`].
484///
485/// # Returns
486///
487/// Returns the computed value produced by [`crate::connection::connection_shutdown_socket`].
488///
489/// # Examples
490///
491/// ```rust,ignore
492/// let _result = pharos_runtime_core::connection::connection_shutdown_socket(todo!());
493/// ```
494///
495/// # Related
496///
497/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
498pub fn connection_shutdown_socket(connection: &mut NativeConnection) -> i32 {
499 connection_shutdown(connection)
500}
501
502/// Returns the transport kind currently attached to a connection.
503///
504/// # Parameters
505///
506/// - `connection`: Input consumed by [`crate::connection::connection_detect_transport`].
507///
508/// # Returns
509///
510/// Returns the computed value produced by [`crate::connection::connection_detect_transport`].
511///
512/// # Examples
513///
514/// ```rust,ignore
515/// let _result = pharos_runtime_core::connection::connection_detect_transport(todo!());
516/// ```
517///
518/// # Related
519///
520/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
521pub fn connection_detect_transport(connection: &NativeConnection) -> NativeTransportType {
522 connection.transport_type
523}
524
525/// Refreshes peer and local endpoint metadata from the attached stream.
526///
527/// # Parameters
528///
529/// - `connection`: Input consumed by [`crate::connection::connection_populate_endpoint_info`].
530///
531/// # Returns
532///
533/// Returns `true` when the condition checked by [`crate::connection::connection_populate_endpoint_info`] holds and `false` otherwise.
534///
535/// # Examples
536///
537/// ```rust,ignore
538/// let _result = pharos_runtime_core::connection::connection_populate_endpoint_info(todo!());
539/// ```
540///
541/// # Related
542///
543/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
544pub fn connection_populate_endpoint_info(connection: &mut NativeConnection) -> bool {
545 match connection.stream.as_ref() {
546 Some(NativeConnectionStream::Tcp(stream)) => {
547 connection.peer_info = stream.peer_addr().ok().map(|value| value.to_string());
548 connection.local_info = stream.local_addr().ok().map(|value| value.to_string());
549 true
550 }
551 #[cfg(unix)]
552 Some(NativeConnectionStream::Unix(_)) => true,
553 None => false,
554 }
555}
556
557/// Resets a connection to an empty metadata-only state.
558///
559/// # Parameters
560///
561/// - `connection`: Input consumed by [`crate::connection::connection_reset`].
562///
563/// # Returns
564///
565/// Returns after [`crate::connection::connection_reset`] applies its in-place effect.
566///
567/// # Examples
568///
569/// ```rust,ignore
570/// let _result = pharos_runtime_core::connection::connection_reset(todo!());
571/// ```
572///
573/// # Related
574///
575/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
576pub fn connection_reset(connection: &mut NativeConnection) {
577 connection.stream = None;
578 connection.fd = -1;
579 connection.write_fd = -1;
580 connection.peer_info = None;
581 connection.local_info = None;
582 connection.transport_type = NativeTransportType::Unknown;
583}
584
585/// Performs connection shutdown.
586///
587/// # Parameters
588///
589/// - `connection`: Input consumed by [`crate::connection::connection_shutdown`].
590///
591/// # Returns
592///
593/// Returns the computed value produced by [`crate::connection::connection_shutdown`].
594///
595/// # Examples
596///
597/// ```rust,ignore
598/// let _result = pharos_runtime_core::connection::connection_shutdown(todo!());
599/// ```
600///
601/// # Related
602///
603/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
604pub fn connection_shutdown(connection: &mut NativeConnection) -> i32 {
605 if connection.fd < 0 || !connection.close_fds {
606 return 0;
607 }
608 match connection.stream.as_mut() {
609 Some(NativeConnectionStream::Tcp(stream)) => {
610 stream.shutdown(Shutdown::Both).map(|_| 0).unwrap_or(-1)
611 }
612 #[cfg(unix)]
613 Some(NativeConnectionStream::Unix(stream)) => {
614 stream.shutdown(Shutdown::Both).map(|_| 0).unwrap_or(-1)
615 }
616 None => 0,
617 }
618}
619
620/// Performs connection peer info.
621///
622/// # Parameters
623///
624/// - `connection`: Input consumed by [`crate::connection::connection_peer_info`].
625///
626/// # Returns
627///
628/// Returns the computed value produced by [`crate::connection::connection_peer_info`].
629///
630/// # Examples
631///
632/// ```rust,ignore
633/// let _result = pharos_runtime_core::connection::connection_peer_info(todo!());
634/// ```
635///
636/// # Related
637///
638/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
639pub fn connection_peer_info(connection: &NativeConnection) -> &str {
640 connection.peer_info.as_deref().unwrap_or("unknown")
641}
642
643/// Performs connection local info.
644///
645/// # Parameters
646///
647/// - `connection`: Input consumed by [`crate::connection::connection_local_info`].
648///
649/// # Returns
650///
651/// Returns the computed value produced by [`crate::connection::connection_local_info`].
652///
653/// # Examples
654///
655/// ```rust,ignore
656/// let _result = pharos_runtime_core::connection::connection_local_info(todo!());
657/// ```
658///
659/// # Related
660///
661/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
662pub fn connection_local_info(connection: &NativeConnection) -> &str {
663 connection.local_info.as_deref().unwrap_or("unknown")
664}
665
666/// Performs connection transport type.
667///
668/// # Parameters
669///
670/// - `connection`: Input consumed by [`crate::connection::connection_transport_type`].
671///
672/// # Returns
673///
674/// Returns the computed value produced by [`crate::connection::connection_transport_type`].
675///
676/// # Examples
677///
678/// ```rust,ignore
679/// let _result = pharos_runtime_core::connection::connection_transport_type(todo!());
680/// ```
681///
682/// # Related
683///
684/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
685pub fn connection_transport_type(connection: &NativeConnection) -> NativeTransportType {
686 connection.transport_type
687}
688
689/// Performs connection transport type name.
690///
691/// # Parameters
692///
693/// - `connection`: Input consumed by [`crate::connection::connection_transport_type_name`].
694///
695/// # Returns
696///
697/// Returns the computed value produced by [`crate::connection::connection_transport_type_name`].
698///
699/// # Examples
700///
701/// ```rust,ignore
702/// let _result = pharos_runtime_core::connection::connection_transport_type_name(todo!());
703/// ```
704///
705/// # Related
706///
707/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
708pub fn connection_transport_type_name(connection: &NativeConnection) -> &'static str {
709 match connection_transport_type(connection) {
710 NativeTransportType::Tcp => "tcp",
711 NativeTransportType::Unix => "unix",
712 NativeTransportType::Unknown => "unknown",
713 }
714}
715
716/// Sends the complete buffer over the attached transport, retrying short writes.
717///
718/// # Parameters
719///
720/// - `connection`: Input consumed by [`crate::connection::connection_send`].
721/// - `buffer`: Input consumed by [`crate::connection::connection_send`].
722///
723/// # Returns
724///
725/// Returns the computed value produced by [`crate::connection::connection_send`].
726///
727/// # Examples
728///
729/// ```rust,ignore
730/// let _result = pharos_runtime_core::connection::connection_send(todo!(), &mut []);
731/// ```
732///
733/// # Related
734///
735/// - [`crate::connection`] for adjacent helpers that share the same runtime surface.
736pub fn connection_send(connection: &mut NativeConnection, buffer: &[u8]) -> i32 {
737 if buffer.is_empty() {
738 return 0;
739 }
740 let mut sent = 0usize;
741 while sent < buffer.len() {
742 let wrote = connection_write(connection, &buffer[sent..]);
743 if wrote <= 0 {
744 return -1;
745 }
746 sent = sent.saturating_add(wrote as usize);
747 }
748 sent as i32
749}