1#![allow(clippy::not_unsafe_ptr_arg_deref)]
5
6use std::net::{
7 TcpStream as StdTcpStream, TcpListener as StdTcpListener,
8 UdpSocket as StdUdpSocket, SocketAddr as StdSocketAddr,
9 Ipv4Addr as StdIpv4Addr, Ipv6Addr as StdIpv6Addr,
10 ToSocketAddrs, Shutdown as StdShutdown,
11};
12use std::io::{Read, Write};
13use std::time::Duration;
14
15#[repr(C)]
17pub struct SocketHandle {
18 socket_type: SocketType,
19 handle: SocketData,
20}
21
22#[repr(C)]
23#[derive(Debug, Clone, Copy)]
24enum SocketType {
25 TcpStream = 0,
26 TcpListener = 1,
27 UdpSocket = 2,
28}
29
30enum SocketData {
31 TcpStream(StdTcpStream),
32 TcpListener(StdTcpListener),
33 UdpSocket(StdUdpSocket),
34}
35
36#[repr(C)]
38pub struct SocketAddr {
39 family: u8, port: u16,
41 addr: [u8; 16], flowinfo: u32, scope_id: u32, }
45
46impl SocketAddr {
47 fn to_std(&self) -> Option<StdSocketAddr> {
48 match self.family {
49 4 => {
50 let addr = StdIpv4Addr::new(self.addr[0], self.addr[1], self.addr[2], self.addr[3]);
51 Some(StdSocketAddr::from((addr, self.port)))
52 }
53 6 => {
54 let addr = StdIpv6Addr::new(
55 u16::from_be_bytes([self.addr[0], self.addr[1]]),
56 u16::from_be_bytes([self.addr[2], self.addr[3]]),
57 u16::from_be_bytes([self.addr[4], self.addr[5]]),
58 u16::from_be_bytes([self.addr[6], self.addr[7]]),
59 u16::from_be_bytes([self.addr[8], self.addr[9]]),
60 u16::from_be_bytes([self.addr[10], self.addr[11]]),
61 u16::from_be_bytes([self.addr[12], self.addr[13]]),
62 u16::from_be_bytes([self.addr[14], self.addr[15]]),
63 );
64 Some(StdSocketAddr::from((addr, self.port)))
65 }
66 _ => None,
67 }
68 }
69
70 fn from_std(addr: &StdSocketAddr) -> SocketAddr {
71 match addr {
72 StdSocketAddr::V4(v4) => {
73 let octets = v4.ip().octets();
74 let mut addr_bytes = [0u8; 16];
75 addr_bytes[0..4].copy_from_slice(&octets);
76
77 SocketAddr {
78 family: 4,
79 port: v4.port(),
80 addr: addr_bytes,
81 flowinfo: 0,
82 scope_id: 0,
83 }
84 }
85 StdSocketAddr::V6(v6) => {
86 let segments = v6.ip().segments();
87 let mut addr_bytes = [0u8; 16];
88 for (i, &seg) in segments.iter().enumerate() {
89 let bytes = seg.to_be_bytes();
90 addr_bytes[i * 2] = bytes[0];
91 addr_bytes[i * 2 + 1] = bytes[1];
92 }
93
94 SocketAddr {
95 family: 6,
96 port: v6.port(),
97 addr: addr_bytes,
98 flowinfo: v6.flowinfo(),
99 scope_id: v6.scope_id(),
100 }
101 }
102 }
103 }
104}
105
106#[no_mangle]
109pub extern "C" fn pd_tcp_connect(addr: *const SocketAddr) -> *mut SocketHandle {
110 if addr.is_null() {
111 return std::ptr::null_mut();
112 }
113
114 unsafe {
115 let addr = &*addr;
116 if let Some(std_addr) = addr.to_std() {
117 match StdTcpStream::connect(std_addr) {
118 Ok(stream) => {
119 let handle = Box::new(SocketHandle {
120 socket_type: SocketType::TcpStream,
121 handle: SocketData::TcpStream(stream),
122 });
123 Box::into_raw(handle)
124 }
125 Err(_) => std::ptr::null_mut(),
126 }
127 } else {
128 std::ptr::null_mut()
129 }
130 }
131}
132
133#[no_mangle]
134pub extern "C" fn pd_tcp_connect_timeout(addr: *const SocketAddr, timeout_ms: u64) -> *mut SocketHandle {
135 if addr.is_null() {
136 return std::ptr::null_mut();
137 }
138
139 unsafe {
140 let addr = &*addr;
141 if let Some(std_addr) = addr.to_std() {
142 let timeout = Duration::from_millis(timeout_ms);
143 match StdTcpStream::connect_timeout(&std_addr, timeout) {
144 Ok(stream) => {
145 let handle = Box::new(SocketHandle {
146 socket_type: SocketType::TcpStream,
147 handle: SocketData::TcpStream(stream),
148 });
149 Box::into_raw(handle)
150 }
151 Err(_) => std::ptr::null_mut(),
152 }
153 } else {
154 std::ptr::null_mut()
155 }
156 }
157}
158
159#[no_mangle]
160pub extern "C" fn pd_tcp_read(handle: *mut SocketHandle, buffer: *mut u8, len: usize) -> i64 {
161 if handle.is_null() || buffer.is_null() {
162 return -1;
163 }
164
165 unsafe {
166 let handle = &mut *handle;
167 match &mut handle.handle {
168 SocketData::TcpStream(stream) => {
169 let buffer_slice = std::slice::from_raw_parts_mut(buffer, len);
170 match stream.read(buffer_slice) {
171 Ok(n) => n as i64,
172 Err(_) => -1,
173 }
174 }
175 _ => -1,
176 }
177 }
178}
179
180#[no_mangle]
181pub extern "C" fn pd_tcp_write(handle: *mut SocketHandle, buffer: *const u8, len: usize) -> i64 {
182 if handle.is_null() || buffer.is_null() {
183 return -1;
184 }
185
186 unsafe {
187 let handle = &mut *handle;
188 match &mut handle.handle {
189 SocketData::TcpStream(stream) => {
190 let buffer_slice = std::slice::from_raw_parts(buffer, len);
191 match stream.write(buffer_slice) {
192 Ok(n) => n as i64,
193 Err(_) => -1,
194 }
195 }
196 _ => -1,
197 }
198 }
199}
200
201#[no_mangle]
202pub extern "C" fn pd_tcp_shutdown(handle: *mut SocketHandle, how: u8) -> i32 {
203 if handle.is_null() {
204 return -1;
205 }
206
207 unsafe {
208 let handle = &mut *handle;
209 match &handle.handle {
210 SocketData::TcpStream(stream) => {
211 let shutdown = match how {
212 0 => StdShutdown::Read,
213 1 => StdShutdown::Write,
214 2 => StdShutdown::Both,
215 _ => return -1,
216 };
217 match stream.shutdown(shutdown) {
218 Ok(_) => 0,
219 Err(_) => -1,
220 }
221 }
222 _ => -1,
223 }
224 }
225}
226
227#[no_mangle]
228pub extern "C" fn pd_tcp_peer_addr(handle: *mut SocketHandle, addr: *mut SocketAddr) -> i32 {
229 if handle.is_null() || addr.is_null() {
230 return -1;
231 }
232
233 unsafe {
234 let handle = &*handle;
235 match &handle.handle {
236 SocketData::TcpStream(stream) => {
237 match stream.peer_addr() {
238 Ok(peer) => {
239 *addr = SocketAddr::from_std(&peer);
240 0
241 }
242 Err(_) => -1,
243 }
244 }
245 _ => -1,
246 }
247 }
248}
249
250#[no_mangle]
251pub extern "C" fn pd_tcp_local_addr(handle: *mut SocketHandle, addr: *mut SocketAddr) -> i32 {
252 if handle.is_null() || addr.is_null() {
253 return -1;
254 }
255
256 unsafe {
257 let handle = &*handle;
258 match &handle.handle {
259 SocketData::TcpStream(stream) => {
260 match stream.local_addr() {
261 Ok(local) => {
262 *addr = SocketAddr::from_std(&local);
263 0
264 }
265 Err(_) => -1,
266 }
267 }
268 _ => -1,
269 }
270 }
271}
272
273#[no_mangle]
274pub extern "C" fn pd_tcp_set_nodelay(handle: *mut SocketHandle, nodelay: u8) -> i32 {
275 if handle.is_null() {
276 return -1;
277 }
278
279 unsafe {
280 let handle = &*handle;
281 match &handle.handle {
282 SocketData::TcpStream(stream) => {
283 match stream.set_nodelay(nodelay != 0) {
284 Ok(_) => 0,
285 Err(_) => -1,
286 }
287 }
288 _ => -1,
289 }
290 }
291}
292
293#[no_mangle]
294pub extern "C" fn pd_tcp_set_ttl(handle: *mut SocketHandle, ttl: u32) -> i32 {
295 if handle.is_null() {
296 return -1;
297 }
298
299 unsafe {
300 let handle = &*handle;
301 match &handle.handle {
302 SocketData::TcpStream(stream) => {
303 match stream.set_ttl(ttl) {
304 Ok(_) => 0,
305 Err(_) => -1,
306 }
307 }
308 _ => -1,
309 }
310 }
311}
312
313#[no_mangle]
316pub extern "C" fn pd_tcp_bind(addr: *const SocketAddr) -> *mut SocketHandle {
317 if addr.is_null() {
318 return std::ptr::null_mut();
319 }
320
321 unsafe {
322 let addr = &*addr;
323 if let Some(std_addr) = addr.to_std() {
324 match StdTcpListener::bind(std_addr) {
325 Ok(listener) => {
326 let handle = Box::new(SocketHandle {
327 socket_type: SocketType::TcpListener,
328 handle: SocketData::TcpListener(listener),
329 });
330 Box::into_raw(handle)
331 }
332 Err(_) => std::ptr::null_mut(),
333 }
334 } else {
335 std::ptr::null_mut()
336 }
337 }
338}
339
340#[no_mangle]
341pub extern "C" fn pd_tcp_accept(handle: *mut SocketHandle, client_addr: *mut SocketAddr) -> *mut SocketHandle {
342 if handle.is_null() {
343 return std::ptr::null_mut();
344 }
345
346 unsafe {
347 let handle = &*handle;
348 match &handle.handle {
349 SocketData::TcpListener(listener) => {
350 match listener.accept() {
351 Ok((stream, addr)) => {
352 if !client_addr.is_null() {
353 *client_addr = SocketAddr::from_std(&addr);
354 }
355
356 let client_handle = Box::new(SocketHandle {
357 socket_type: SocketType::TcpStream,
358 handle: SocketData::TcpStream(stream),
359 });
360 Box::into_raw(client_handle)
361 }
362 Err(_) => std::ptr::null_mut(),
363 }
364 }
365 _ => std::ptr::null_mut(),
366 }
367 }
368}
369
370#[no_mangle]
373pub extern "C" fn pd_udp_bind(addr: *const SocketAddr) -> *mut SocketHandle {
374 if addr.is_null() {
375 return std::ptr::null_mut();
376 }
377
378 unsafe {
379 let addr = &*addr;
380 if let Some(std_addr) = addr.to_std() {
381 match StdUdpSocket::bind(std_addr) {
382 Ok(socket) => {
383 let handle = Box::new(SocketHandle {
384 socket_type: SocketType::UdpSocket,
385 handle: SocketData::UdpSocket(socket),
386 });
387 Box::into_raw(handle)
388 }
389 Err(_) => std::ptr::null_mut(),
390 }
391 } else {
392 std::ptr::null_mut()
393 }
394 }
395}
396
397#[no_mangle]
398pub extern "C" fn pd_udp_send_to(handle: *mut SocketHandle, buffer: *const u8, len: usize, addr: *const SocketAddr) -> i64 {
399 if handle.is_null() || buffer.is_null() || addr.is_null() {
400 return -1;
401 }
402
403 unsafe {
404 let handle = &*handle;
405 let addr = &*addr;
406
407 match &handle.handle {
408 SocketData::UdpSocket(socket) => {
409 if let Some(std_addr) = addr.to_std() {
410 let buffer_slice = std::slice::from_raw_parts(buffer, len);
411 match socket.send_to(buffer_slice, std_addr) {
412 Ok(n) => n as i64,
413 Err(_) => -1,
414 }
415 } else {
416 -1
417 }
418 }
419 _ => -1,
420 }
421 }
422}
423
424#[no_mangle]
425pub extern "C" fn pd_udp_recv_from(handle: *mut SocketHandle, buffer: *mut u8, len: usize, addr: *mut SocketAddr) -> i64 {
426 if handle.is_null() || buffer.is_null() || addr.is_null() {
427 return -1;
428 }
429
430 unsafe {
431 let handle = &*handle;
432 match &handle.handle {
433 SocketData::UdpSocket(socket) => {
434 let buffer_slice = std::slice::from_raw_parts_mut(buffer, len);
435 match socket.recv_from(buffer_slice) {
436 Ok((n, src_addr)) => {
437 *addr = SocketAddr::from_std(&src_addr);
438 n as i64
439 }
440 Err(_) => -1,
441 }
442 }
443 _ => -1,
444 }
445 }
446}
447
448#[no_mangle]
449pub extern "C" fn pd_udp_connect(handle: *mut SocketHandle, addr: *const SocketAddr) -> i32 {
450 if handle.is_null() || addr.is_null() {
451 return -1;
452 }
453
454 unsafe {
455 let handle = &*handle;
456 let addr = &*addr;
457
458 match &handle.handle {
459 SocketData::UdpSocket(socket) => {
460 if let Some(std_addr) = addr.to_std() {
461 match socket.connect(std_addr) {
462 Ok(_) => 0,
463 Err(_) => -1,
464 }
465 } else {
466 -1
467 }
468 }
469 _ => -1,
470 }
471 }
472}
473
474#[no_mangle]
475pub extern "C" fn pd_udp_send(handle: *mut SocketHandle, buffer: *const u8, len: usize) -> i64 {
476 if handle.is_null() || buffer.is_null() {
477 return -1;
478 }
479
480 unsafe {
481 let handle = &*handle;
482 match &handle.handle {
483 SocketData::UdpSocket(socket) => {
484 let buffer_slice = std::slice::from_raw_parts(buffer, len);
485 match socket.send(buffer_slice) {
486 Ok(n) => n as i64,
487 Err(_) => -1,
488 }
489 }
490 _ => -1,
491 }
492 }
493}
494
495#[no_mangle]
496pub extern "C" fn pd_udp_recv(handle: *mut SocketHandle, buffer: *mut u8, len: usize) -> i64 {
497 if handle.is_null() || buffer.is_null() {
498 return -1;
499 }
500
501 unsafe {
502 let handle = &*handle;
503 match &handle.handle {
504 SocketData::UdpSocket(socket) => {
505 let buffer_slice = std::slice::from_raw_parts_mut(buffer, len);
506 match socket.recv(buffer_slice) {
507 Ok(n) => n as i64,
508 Err(_) => -1,
509 }
510 }
511 _ => -1,
512 }
513 }
514}
515
516#[no_mangle]
519pub extern "C" fn pd_socket_close(handle: *mut SocketHandle) -> i32 {
520 if handle.is_null() {
521 return -1;
522 }
523
524 unsafe {
525 let _ = Box::from_raw(handle);
526 0
527 }
528}
529
530#[no_mangle]
533pub extern "C" fn pd_lookup_host(host: *const u8, host_len: usize, addrs: *mut *mut SocketAddr, count: *mut usize) -> i32 {
534 if host.is_null() || addrs.is_null() || count.is_null() {
535 return -1;
536 }
537
538 unsafe {
539 let host_slice = std::slice::from_raw_parts(host, host_len);
540 let host_str = match std::str::from_utf8(host_slice) {
541 Ok(s) => s,
542 Err(_) => return -1,
543 };
544
545 match (host_str, 0).to_socket_addrs() {
546 Ok(iter) => {
547 let addr_vec: Vec<SocketAddr> = iter
548 .map(|addr| SocketAddr::from_std(&addr))
549 .collect();
550
551 *count = addr_vec.len();
552 let addrs_array = addr_vec.into_boxed_slice();
553 *addrs = Box::into_raw(addrs_array) as *mut SocketAddr;
554
555 0
556 }
557 Err(_) => -1,
558 }
559 }
560}
561
562#[no_mangle]
563pub extern "C" fn pd_parse_socket_addr(addr_str: *const u8, addr_len: usize, addr: *mut SocketAddr) -> i32 {
564 if addr_str.is_null() || addr.is_null() {
565 return -1;
566 }
567
568 unsafe {
569 let addr_slice = std::slice::from_raw_parts(addr_str, addr_len);
570 let addr_string = match std::str::from_utf8(addr_slice) {
571 Ok(s) => s,
572 Err(_) => return -1,
573 };
574
575 if let Ok(parsed) = addr_string.parse::<StdSocketAddr>() {
577 *addr = SocketAddr::from_std(&parsed);
578 0
579 } else {
580 -1
581 }
582 }
583}
584
585#[no_mangle]
586pub extern "C" fn pd_free_socket_addrs(addrs: *mut SocketAddr, count: usize) {
587 if addrs.is_null() {
588 return;
589 }
590
591 unsafe {
592 let _ = Box::from_raw(std::slice::from_raw_parts_mut(addrs, count));
593 }
594}