Skip to main content

palladium/runtime/
net.rs

1// Runtime support for networking operations
2// "Connecting Palladium to the world"
3
4#![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/// Socket handle wrapper
16#[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/// Socket address representation
37#[repr(C)]
38pub struct SocketAddr {
39    family: u8,  // 4 for IPv4, 6 for IPv6
40    port: u16,
41    addr: [u8; 16], // IPv4 uses first 4 bytes, IPv6 uses all 16
42    flowinfo: u32,  // IPv6 only
43    scope_id: u32,  // IPv6 only
44}
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// TCP Stream operations
107
108#[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// TCP Listener operations
314
315#[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// UDP Socket operations
371
372#[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// Common socket operations
517
518#[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// DNS and address resolution
531
532#[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        // Try to parse as socket address
576        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}