ort_openrouter_cli/net/
socket.rs1use core::ffi::{c_int, c_void};
8use core::mem::size_of;
9use core::net::{Ipv4Addr, SocketAddrV4};
10
11use crate::{ErrorKind, OrtResult, Read, Write, libc, ort_error};
12
13pub struct TcpSocket {
14 fd: i32,
15}
16
17impl TcpSocket {
18 pub fn new() -> OrtResult<Self> {
19 let fd = unsafe { libc::socket(libc::AF_INET, libc::SOCK_STREAM | libc::SOCK_CLOEXEC, 0) };
20 if fd == -1 {
21 return Err(ort_error(ErrorKind::SocketCreateFailed, ""));
22 }
23 set_tcp_fastopen(fd);
24 Ok(TcpSocket { fd })
25 }
26
27 pub fn connect(&self, addr: &SocketAddrV4) -> OrtResult<()> {
28 let c_addr = socket_addr_v4_to_c(addr);
29 let len = size_of::<libc::sockaddr_in>() as libc::socklen_t;
30 let res =
31 unsafe { libc::connect(self.fd, &c_addr as *const _ as *const libc::sockaddr, len) };
32 if res == -1 {
33 return Err(ort_error(ErrorKind::SocketConnectFailed, ""));
34 }
35 Ok(())
36 }
37}
38
39impl Read for TcpSocket {
40 fn read(&mut self, buf: &mut [u8]) -> OrtResult<usize> {
41 let bytes_read = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, buf.len()) };
42 if bytes_read < 0 {
43 Err(ort_error(ErrorKind::SocketReadFailed, "syscall read error"))
44 } else {
45 Ok(bytes_read as usize)
46 }
47 }
48}
49
50impl Write for TcpSocket {
51 fn write(&mut self, buf: &[u8]) -> OrtResult<usize> {
52 let bytes_written =
53 unsafe { libc::write(self.fd, buf.as_ptr() as *const c_void, buf.len()) };
54 if bytes_written < 0 {
55 Err(ort_error(
56 ErrorKind::SocketWriteFailed,
57 "syscall write error",
58 ))
59 } else {
60 Ok(bytes_written as usize)
61 }
62 }
63
64 fn flush(&mut self) -> OrtResult<()> {
65 Ok(())
66 }
67}
68
69fn set_tcp_fastopen(fd: i32) {
70 let optval: c_int = 1; unsafe {
72 libc::setsockopt(
73 fd,
74 libc::IPPROTO_TCP,
75 libc::TCP_FASTOPEN,
76 &optval as *const _ as *const core::ffi::c_void,
77 size_of::<i32>() as u32,
78 );
79 }
80}
81
82fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> libc::sockaddr_in {
83 libc::sockaddr_in {
84 sin_family: libc::AF_INET as libc::sa_family_t,
85 sin_port: addr.port().to_be(),
86 sin_addr: ip_v4_addr_to_c(addr.ip()),
87 ..unsafe { core::mem::zeroed() }
88 }
89}
90fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> libc::in_addr {
91 libc::in_addr {
94 s_addr: u32::from_ne_bytes(addr.octets()),
95 }
96}