From 3724ee33c5ef1eaa214e000ca9459230ec99bda7 Mon Sep 17 00:00:00 2001 From: IshanGrover2004 Date: Sun, 25 Aug 2024 09:50:31 +0530 Subject: [PATCH] feat: Add C equivalent code in `libccxr_exports` & use in `networking.c` --- src/lib_ccx/networking.c | 46 +++++ src/rust/src/libccxr_exports/net.rs | 286 ++++++++++++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 src/rust/src/libccxr_exports/net.rs diff --git a/src/lib_ccx/networking.c b/src/lib_ccx/networking.c index 4cafdb7fd..2ecd25e0e 100644 --- a/src/lib_ccx/networking.c +++ b/src/lib_ccx/networking.c @@ -45,6 +45,24 @@ const char *srv_pwd; unsigned char *srv_header; size_t srv_header_len; +#ifndef DISABLE_RUST +extern void ccxr_connect_to_srv(const char *addr, const char *port, const char *cc_desc, const char *pwd); +extern void ccxr_net_send_header(const unsigned char *data, size_t len); +extern int ccxr_net_send_cc(const unsigned char *data, int length, void *private_data, struct cc_subtitle *sub); +extern void ccxr_net_check_conn(); +extern void ccxr_net_send_epg( + const char *start, + const char *stop, + const char *title, + const char *desc, + const char *lang, + const char *category); +extern int ccxr_net_tcp_read(int socket, void *buffer, size_t length); +extern int ccxr_net_udp_read(int socket, void *buffer, size_t length, const char *src_str, const char *addr_str); +extern int ccxr_start_tcp_srv(const char *port, const char *pwd); +extern int ccxr_start_udp_srv(const char *src, const char *addr, unsigned port); +#endif + /* * Established connection to specified address. * Returns socked id @@ -84,6 +102,9 @@ int set_nonblocking(int fd); void connect_to_srv(const char *addr, const char *port, const char *cc_desc, const char *pwd) { +#ifndef DISABLE_RUST + return ccxr_connect_to_srv(addr, port, cc_desc, pwd); +#endif if (NULL == addr) { mprint("Server address is not set\n"); @@ -115,6 +136,9 @@ void connect_to_srv(const char *addr, const char *port, const char *cc_desc, con void net_send_header(const unsigned char *data, size_t len) { +#ifndef DISABLE_RUST + return ccxr_net_send_header(data, len); +#endif assert(srv_sd > 0); #if DEBUG_OUT @@ -141,6 +165,9 @@ void net_send_header(const unsigned char *data, size_t len) int net_send_cc(const unsigned char *data, int len, void *private_data, struct cc_subtitle *sub) { +#ifndef DISABLE_RUST + return ccxr_net_send_cc(data, len, private_data, sub); +#endif assert(srv_sd > 0); #if DEBUG_OUT @@ -160,6 +187,9 @@ int net_send_cc(const unsigned char *data, int len, void *private_data, struct c void net_check_conn() { +#ifndef DISABLE_RUST + return ccxr_net_check_conn(); +#endif time_t now; static time_t last_ping = 0; char c = 0; @@ -221,6 +251,9 @@ void net_send_epg( const char *lang, const char *category) { +#ifndef DISABLE_RUST + return ccxr_net_send_epg(start, stop, title, desc, lang, category); +#endif size_t st; size_t sp; size_t t; @@ -301,6 +334,9 @@ void net_send_epg( int net_tcp_read(int socket, void *buffer, size_t length) { +#ifndef DISABLE_RUST + return ccxr_net_tcp_read(socket, buffer, length); +#endif assert(buffer != NULL); assert(length > 0); @@ -333,6 +369,9 @@ int net_tcp_read(int socket, void *buffer, size_t length) int net_udp_read(int socket, void *buffer, size_t length, const char *src_str, const char *addr_str) { +#ifndef DISABLE_RUST + return ccxr_net_udp_read(socket, buffer, length, src_str, addr_str); +#endif assert(buffer != NULL); assert(length > 0); @@ -519,6 +558,9 @@ int tcp_connect(const char *host, const char *port) int start_tcp_srv(const char *port, const char *pwd) { +#ifndef DISABLE_RUST + return ccxr_start_tcp_srv(port, pwd); +#endif if (NULL == port) port = DFT_PORT; @@ -974,6 +1016,10 @@ ssize_t read_byte(int fd, char *ch) int start_upd_srv(const char *src_str, const char *addr_str, unsigned port) { +#ifndef DISABLE_RUST + return ccxr_start_udp_srv(src_str, addr_str, port); +#endif + init_sockets(); in_addr_t src; diff --git a/src/rust/src/libccxr_exports/net.rs b/src/rust/src/libccxr_exports/net.rs new file mode 100644 index 000000000..b32e1339f --- /dev/null +++ b/src/rust/src/libccxr_exports/net.rs @@ -0,0 +1,286 @@ +use crate::bindings::*; + +use std::convert::TryInto; +use std::ffi::CStr; +use std::os::raw::{c_char, c_int, c_uchar, c_uint, c_void}; + +use lib_ccxr::net::c_functions::*; + +/// Rust equivalent for `connect_to_srv` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `addr` must not be null. All the strings must end with a nul character. +#[no_mangle] +pub unsafe extern "C" fn ccxr_connect_to_srv( + addr: *const c_char, + port: *const c_char, + cc_desc: *const c_char, + pwd: *const c_char, +) { + let addr = CStr::from_ptr(addr) + .to_str() + .expect("Unable to convert Cstr to &str"); + + let port = if !port.is_null() { + Some( + CStr::from_ptr(port) + .to_str() + .expect("Unable to convert Cstr to &str") + .parse() + .expect("Unable to parse into u16"), + ) + } else { + None + }; + + let cc_desc = if !cc_desc.is_null() { + Some( + CStr::from_ptr(cc_desc) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + let pwd = if !pwd.is_null() { + Some( + CStr::from_ptr(pwd) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + connect_to_srv(addr, port, cc_desc, pwd); +} + +/// Rust equivalent for `net_send_header` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `data` must not be null and should have a length of `len`. +/// [`ccxr_connect_to_srv`] or `connect_to_srv` must have been called before this function. +#[no_mangle] +pub unsafe extern "C" fn ccxr_net_send_header(data: *const c_uchar, len: usize) { + let buffer = std::slice::from_raw_parts(data, len); + net_send_header(buffer); +} + +/// Rust equivalent for `net_send_cc` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `data` must not be null and should have a length of `len`. +/// [`ccxr_connect_to_srv`] or `connect_to_srv` must have been called before this function. +#[no_mangle] +pub unsafe extern "C" fn ccxr_net_send_cc( + data: *const c_uchar, + len: usize, + _private_data: *const c_void, + _sub: *const cc_subtitle, +) -> c_int { + let buffer = std::slice::from_raw_parts(data, len); + if net_send_cc(buffer) { + 1 + } else { + -1 + } +} + +/// Rust equivalent for `net_check_conn` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// [`ccxr_connect_to_srv`] or `connect_to_srv` must have been called before this function. +#[no_mangle] +pub unsafe extern "C" fn ccxr_net_check_conn() { + net_check_conn() +} + +/// Rust equivalent for `net_send_epg` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `start` and `stop` must not be null. All the strings must end with a nul character. +/// [`ccxr_connect_to_srv`] or `connect_to_srv` must have been called before this function. +#[no_mangle] +pub unsafe extern "C" fn ccxr_net_send_epg( + start: *const c_char, + stop: *const c_char, + title: *const c_char, + desc: *const c_char, + lang: *const c_char, + category: *const c_char, +) { + let start = CStr::from_ptr(start) + .to_str() + .expect("Unable to convert Cstr to &str"); + let stop = CStr::from_ptr(stop) + .to_str() + .expect("Unable to convert Cstr to &str"); + + let title = if !title.is_null() { + Some( + CStr::from_ptr(title) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + let desc = if !desc.is_null() { + Some( + CStr::from_ptr(desc) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + let lang = if !lang.is_null() { + Some( + CStr::from_ptr(lang) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + let category = if !category.is_null() { + Some( + CStr::from_ptr(category) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + net_send_epg(start, stop, title, desc, lang, category) +} + +/// Rust equivalent for `net_tcp_read` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `buffer` should not be null. it should be of size `length`. +/// [`ccxr_start_tcp_srv`] or `start_tcp_srv` must have been called before this function. +#[no_mangle] +pub unsafe extern "C" fn ccxr_net_tcp_read( + _socket: c_int, + buffer: *mut c_void, + length: usize, +) -> c_int { + let buffer = std::slice::from_raw_parts_mut(buffer as *mut u8, length); + let ans = net_tcp_read(buffer); + match ans { + Some(x) => x.try_into().unwrap(), + None => -1, + } +} + +/// Rust equivalent for `net_udp_read` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `buffer` should not be null. it should be of size `length`. +/// [`ccxr_start_udp_srv`] or `start_udp_srv` must have been called before this function. +#[no_mangle] +pub unsafe extern "C" fn ccxr_net_udp_read( + _socket: c_int, + buffer: *mut c_void, + length: usize, + _src_str: *const c_char, + _addr_str: *const c_char, +) -> c_int { + let buffer = std::slice::from_raw_parts_mut(buffer as *mut u8, length); + let ans = net_udp_read(buffer); + match ans { + Some(x) => x.try_into().unwrap(), + None => -1, + } +} + +/// Rust equivalent for `start_tcp_srv` function in C. Uses C-native types as input and output. +/// +/// Note that this function always returns 1 as an fd, since it will not be used anyway. +/// +/// # Safety +/// +/// `port` should be a numerical 16-bit value. All the strings must end with a nul character. +/// The output file desciptor should not be used. +#[no_mangle] +pub unsafe extern "C" fn ccxr_start_tcp_srv(port: *const c_char, pwd: *const c_char) -> c_int { + let port = if !port.is_null() { + Some( + CStr::from_ptr(port) + .to_str() + .expect("Unable to convert Cstr to &str") + .parse() + .expect("Unable to parse into u16"), + ) + } else { + None + }; + + let pwd = if !pwd.is_null() { + Some( + CStr::from_ptr(pwd) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + start_tcp_srv(port, pwd); + + 1 +} + +/// Rust equivalent for `start_udp_srv` function in C. Uses C-native types as input and output. +/// +/// Note that this function always returns 1 as an fd, since it will not be used anyway. +/// +/// # Safety +/// +/// `port` should be a 16-bit value. All the strings must end with a nul character. +/// The output file desciptor should not be used. +#[no_mangle] +pub unsafe extern "C" fn ccxr_start_udp_srv( + src: *const c_char, + addr: *const c_char, + port: c_uint, +) -> c_int { + let src = if !src.is_null() { + Some( + CStr::from_ptr(src) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + let addr = if !addr.is_null() { + Some( + CStr::from_ptr(addr) + .to_str() + .expect("Unable to convert Cstr to &str"), + ) + } else { + None + }; + + let port = port.try_into().unwrap(); + + start_udp_srv(src, addr, port); + + 1 +}