1use anyhow::Result;
2use std::{
3 net::{SocketAddr, ToSocketAddrs},
4 time::Duration,
5};
6use thiserror::Error;
7use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
8
9pub mod certs;
10pub mod http;
11pub mod udp;
12
13#[derive(Debug)]
14pub struct HelloPacket {
15 pub hp_type: HelloPacketType,
16 pub token: u128,
18 pub own_ssl: bool,
19 pub tunnel_id: u128,
20}
21
22#[derive(Debug, PartialEq)]
23pub enum HelloPacketType {
24 Connector = 0,
25 Tunnel = 1,
26
27 Invalid,
28}
29
30impl HelloPacketType {
31 pub fn to_u8(&self) -> u8 {
32 match self {
33 HelloPacketType::Connector => 0,
34 HelloPacketType::Tunnel => 1,
35 HelloPacketType::Invalid => u8::MAX,
36 }
37 }
38
39 pub fn from_u8(val: u8) -> Self {
40 match val {
41 0 => HelloPacketType::Connector,
42 1 => HelloPacketType::Tunnel,
43 _ => HelloPacketType::Invalid,
44 }
45 }
46}
47
48impl HelloPacket {
49 pub const fn buf_size() -> usize {
50 80
51 }
52
53 pub fn to_buf(&self) -> [u8; 80] {
54 let mut tmp = [0; 80];
55 tmp[0] = self.hp_type.to_u8();
56 tmp[10..26].copy_from_slice(&self.token.to_be_bytes());
58 tmp[26] = self.own_ssl as u8;
59 tmp[27..43].copy_from_slice(&self.tunnel_id.to_be_bytes());
60
61 tmp
62 }
63
64 pub fn from_buf(buf: &[u8; 80]) -> Self {
65 Self {
66 hp_type: HelloPacketType::from_u8(buf[0]),
67 token: u128::from_be_bytes(buf[10..26].try_into().unwrap()),
69 own_ssl: buf[26] != 0,
70 tunnel_id: u128::from_be_bytes(buf[27..43].try_into().unwrap()),
71 }
72 }
73}
74
75#[derive(Debug, PartialEq)]
76pub enum ConnectorPacketType {
77 Ping = 0,
78 TunnelRequest = 1,
79 Close = 2,
80
81 Invalid,
82}
83
84impl ConnectorPacketType {
85 pub fn to_u8(&self) -> u8 {
86 match self {
87 ConnectorPacketType::Ping => 0,
88 ConnectorPacketType::TunnelRequest => 1,
89 ConnectorPacketType::Close => 2,
90 ConnectorPacketType::Invalid => u8::MAX,
91 }
92 }
93
94 pub fn from_u8(val: u8) -> Self {
95 match val {
96 0 => ConnectorPacketType::Ping,
97 1 => ConnectorPacketType::TunnelRequest,
98 2 => ConnectorPacketType::Close,
99 _ => ConnectorPacketType::Invalid,
100 }
101 }
102}
103
104#[derive(Debug)]
105pub struct ConnectorPacket {
106 pub packet_type: ConnectorPacketType,
107 pub tunnel_id: u128,
108 pub ssl: bool,
109 pub http3: bool,
110}
111
112impl ConnectorPacket {
113 pub const fn buf_size() -> usize {
114 20
115 }
116
117 pub fn to_buf(&self) -> [u8; 20] {
118 let mut tmp = [0; 20];
119 tmp[0] = self.packet_type.to_u8();
120 tmp[1..17].copy_from_slice(&self.tunnel_id.to_be_bytes());
121 tmp[17] = self.ssl as u8;
122 tmp[18] = self.http3 as u8;
123
124 tmp
125 }
126
127 pub fn from_buf(buf: &[u8; 20]) -> Self {
128 Self {
129 packet_type: ConnectorPacketType::from_u8(buf[0]),
130 tunnel_id: u128::from_be_bytes(buf[1..17].try_into().unwrap()),
131 ssl: buf[17] != 0,
132 http3: buf[18] != 0,
133 }
134 }
135}
136
137pub fn parse_socketaddr(arg: &str) -> Result<SocketAddr> {
138 for i in 0..10 {
139 let res = arg.to_socket_addrs();
140
141 match res {
142 Ok(addrs) => {
143 for addr in addrs {
144 if addr.is_ipv4() {
145 return Ok(addr);
146 }
147 }
148 }
149 Err(e) => {
150 println!("[clap parse_socketaddr] (Try: {}) {e:?}", i + 1);
151 std::thread::sleep(Duration::from_millis(5000));
152 }
153 }
154 }
155
156 Err(anyhow::anyhow!("No ipv4 socketaddr found!"))
157}
158
159pub fn generate_string_packet(string: &str) -> Result<Vec<u8>> {
160 let mut bytes = string.as_bytes().to_vec();
161 bytes.push(0); Ok(bytes)
164}
165
166pub async fn send_string_to_stream<T>(stream: &mut T, string: &str) -> Result<()>
167where
168 T: AsyncWrite + Unpin,
169{
170 let bytes = generate_string_packet(string)?;
171 stream.write_all(&bytes).await?;
172
173 Ok(())
174}
175
176pub async fn read_string_from_stream<T>(stream: &mut T) -> Result<String>
177where
178 T: AsyncRead + Unpin,
179{
180 let mut buffer = Vec::new();
181 loop {
182 let byte = stream.read_u8().await?;
183 if byte == 0 {
184 break;
185 }
186
187 buffer.push(byte);
188 }
189
190 Ok(String::from_utf8(buffer)?)
191}
192
193#[derive(Error, Debug)]
194pub enum HelloPacketError {
195 #[error("Token mismatch!")]
196 TokenMismatch,
197
198 #[error(transparent)]
199 TryFromSlice(#[from] std::array::TryFromSliceError),
200
201 #[error(transparent)]
202 Anyhow(#[from] anyhow::Error),
203}
204
205pub fn read_http_host(in_buffer: &[u8]) -> Result<String> {
206 let mut lines = in_buffer.split(|&x| x == b'\n');
207 let host = lines
208 .find(|x| x.to_ascii_lowercase().starts_with(b"host:"))
209 .ok_or_else(|| anyhow::anyhow!("No host"))?;
210
211 let host = String::from_utf8_lossy(&host[5..]).trim().to_string();
212 Ok(host)
213}