[pve-devel] [PATCH conntrack-tool v2 5/5] replace C callback with closures

Mira Limbeck m.limbeck at proxmox.com
Wed Feb 3 15:25:35 CET 2021


Internally we still have to use a C callback, but all it does is forward
to the closure we pass to it.

Signed-off-by: Mira Limbeck <m.limbeck at proxmox.com>
---
v2:
 - new addition

 src/main.rs | 208 +++++++++++++++++++++++++++-------------------------
 1 file changed, 109 insertions(+), 99 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 79779ff..0930f92 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -83,24 +83,6 @@ fn main() -> Result<()> {
     Ok(())
 }
 
-extern "C" fn query_cts_cb(nlh: *const libc::nlmsghdr, data_ptr: *mut libc::c_void) -> libc::c_int {
-    let ct = unsafe { nfct_new() };
-    unsafe {
-        nfct_nlmsg_parse(nlh, ct);
-    }
-
-    if let Some(conntrack) = parse_conntrack(ct) {
-        let cts: &mut Vec<Conntrack> = unsafe { &mut *(data_ptr as *mut Vec<Conntrack>) };
-        cts.push(conntrack);
-    }
-
-    unsafe {
-        nfct_destroy(ct);
-    }
-
-    MNL_CB_OK
-}
-
 const CONNTRACK_QUERY_MSG_TYPE: u16 =
     ((libc::NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET) as u16;
 const CONNTRACK_QUERY_FLAGS: u16 =
@@ -169,7 +151,20 @@ impl Socket {
             seq,
             proto,
         );
-        self.send_and_receive(hdr, 0, Some(query_cts_cb), cts as *mut Vec<Conntrack> as _)
+        self.send_and_receive(hdr, 0, |nlh| {
+            let ct = unsafe { nfct_new() };
+            unsafe {
+                nfct_nlmsg_parse(nlh, ct);
+            }
+
+            if let Some(conntrack) = parse_conntrack(ct) {
+                cts.push(conntrack);
+            }
+
+            unsafe {
+                nfct_destroy(ct);
+            }
+        })
     }
 
     fn insert_conntrack(&mut self, ct: Conntrack) -> Result<()> {
@@ -195,7 +190,7 @@ impl Socket {
             nfct_destroy(cth);
         }
 
-        self.send_and_receive(hdr, 0, None, std::ptr::null_mut())?;
+        self.send_and_receive(hdr, 0, |_| {})?;
 
         Ok(())
     }
@@ -208,7 +203,12 @@ impl Socket {
         Ok(())
     }
 
-    fn query_expects_impl(&mut self, exps: &mut Vec<Expect>, seq: u32, proto: u8) -> Result<()> {
+    fn query_expects_impl(
+        &mut self,
+        exps: &mut Vec<Expect>,
+        seq: u32,
+        proto: u8,
+    ) -> Result<()> {
         let mut buf = [0u8; MNL_SOCKET_DUMP_SIZE as _];
         let hdr = build_msg_header(
             buf.as_mut_ptr() as _,
@@ -217,7 +217,75 @@ impl Socket {
             seq,
             proto,
         );
-        self.send_and_receive(hdr, 0, Some(query_exp_cb), exps as *mut Vec<Expect> as _)
+        self.send_and_receive(hdr, 0, |nlh| {
+            let exp = unsafe { nfexp_new() };
+            unsafe {
+                nfexp_nlmsg_parse(nlh, exp);
+            }
+
+            let mut attributes = Vec::new();
+            for (attr, ty) in EXPECT_ALL_ATTRIBUTES {
+                if unsafe { nfexp_attr_is_set(exp, *attr) } == 0 {
+                    continue;
+                }
+                match ty {
+                    ExpectAttrType::CT => {
+                        let ct = unsafe { nfexp_get_attr(exp, *attr) };
+                        if let Some(ct) = parse_conntrack(ct as _) {
+                            attributes.push(ExpectAttr {
+                                key: *attr,
+                                value: ExpectAttrValue::CT(ct),
+                            });
+                        }
+                    }
+                    ExpectAttrType::U8 => {
+                        let val = unsafe { nfexp_get_attr_u8(exp, *attr) };
+                        attributes.push(ExpectAttr {
+                            key: *attr,
+                            value: ExpectAttrValue::U8(val),
+                        });
+                    }
+                    ExpectAttrType::U16 => {
+                        let val = unsafe { nfexp_get_attr_u16(exp, *attr) };
+                        attributes.push(ExpectAttr {
+                            key: *attr,
+                            value: ExpectAttrValue::U16(val),
+                        });
+                    }
+                    ExpectAttrType::U32 => {
+                        let val = unsafe { nfexp_get_attr_u32(exp, *attr) };
+                        attributes.push(ExpectAttr {
+                            key: *attr,
+                            value: ExpectAttrValue::U32(val),
+                        });
+                    }
+                    ExpectAttrType::String(Some(len)) => {
+                        let ptr = unsafe { nfexp_get_attr(exp, *attr) };
+                        let cstr = unsafe { std::ffi::CStr::from_ptr(ptr as _) };
+                        let s = cstr.to_bytes();
+                        let s = unsafe {
+                            CString::from_vec_unchecked(s[0..s.len().min((*len) as _)].to_vec())
+                        };
+                        attributes.push(ExpectAttr {
+                            key: *attr,
+                            value: ExpectAttrValue::String(s),
+                        });
+                    }
+                    ExpectAttrType::String(None) => {
+                        let ptr = unsafe { nfexp_get_attr(exp, *attr) };
+                        let cstr = unsafe { std::ffi::CStr::from_ptr(ptr as _) };
+                        let s = cstr.to_bytes();
+                        let s = unsafe { CString::from_vec_unchecked(s.to_vec()) };
+                        attributes.push(ExpectAttr {
+                            key: *attr,
+                            value: ExpectAttrValue::String(s),
+                        });
+                    }
+                }
+            }
+
+            exps.push(Expect { attributes });
+        })
     }
 
     fn insert_expect(&mut self, exp: Expect) -> Result<()> {
@@ -277,17 +345,16 @@ impl Socket {
             }
         }
 
-        self.send_and_receive(hdr, 0, None, std::ptr::null_mut())?;
+        self.send_and_receive(hdr, 0, |_| {})?;
 
         Ok(())
     }
 
-    fn send_and_receive(
+    fn send_and_receive<CB: FnMut(*const libc::nlmsghdr)>(
         &mut self,
         msg: *const libc::nlmsghdr,
         seq: u32,
-        cb: Option<mnl_cb_t>,
-        data: *mut libc::c_void,
+        mut cb: CB,
     ) -> Result<()> {
         let res =
             unsafe { mnl_socket_sendto(self.socket.as_ptr(), msg as _, (*msg).nlmsg_len as _) };
@@ -312,7 +379,16 @@ impl Socket {
                 bail!("Failed to read message: {}", err);
             }
 
-            let res = unsafe { mnl_cb_run(buffer.as_ptr() as _, res as _, seq, portid, cb, data) };
+            let res = unsafe {
+                mnl_cb_run(
+                    buffer.as_ptr() as _,
+                    res as _,
+                    seq,
+                    portid,
+                    Some(callback),
+                    &mut &mut cb as *mut &mut CB as _,
+                )
+            };
             if res == -1 {
                 let err = std::io::Error::last_os_error();
                 bail!("Failed to run callback: {}", err);
@@ -333,6 +409,12 @@ impl Drop for Socket {
     }
 }
 
+extern "C" fn callback(nlh: *const libc::nlmsghdr, data_ptr: *mut libc::c_void) -> libc::c_int {
+    let cb = unsafe { *(data_ptr as *mut &dyn Fn(*const libc::nlmsghdr)) };
+    cb(nlh);
+    MNL_CB_OK
+}
+
 fn build_msg_header(
     buf: *mut libc::c_void,
     ty: u16,
@@ -594,78 +676,6 @@ const ALL_ATTRIBUTES: &[(CTAttr, AttrType)] = &[
     (CTAttr::SYNPROXY_TSOFF, AttrType::U32),       /* u32 bits */
 ];
 
-extern "C" fn query_exp_cb(nlh: *const libc::nlmsghdr, data_ptr: *mut libc::c_void) -> libc::c_int {
-    let exp = unsafe { nfexp_new() };
-    unsafe {
-        nfexp_nlmsg_parse(nlh, exp);
-    }
-
-    let mut attributes = Vec::new();
-    for (attr, ty) in EXPECT_ALL_ATTRIBUTES {
-        if unsafe { nfexp_attr_is_set(exp, *attr) } == 0 {
-            continue;
-        }
-        match ty {
-            ExpectAttrType::CT => {
-                let ct = unsafe { nfexp_get_attr(exp, *attr) };
-                if let Some(ct) = parse_conntrack(ct as _) {
-                    attributes.push(ExpectAttr {
-                        key: *attr,
-                        value: ExpectAttrValue::CT(ct),
-                    });
-                }
-            }
-            ExpectAttrType::U8 => {
-                let val = unsafe { nfexp_get_attr_u8(exp, *attr) };
-                attributes.push(ExpectAttr {
-                    key: *attr,
-                    value: ExpectAttrValue::U8(val),
-                });
-            }
-            ExpectAttrType::U16 => {
-                let val = unsafe { nfexp_get_attr_u16(exp, *attr) };
-                attributes.push(ExpectAttr {
-                    key: *attr,
-                    value: ExpectAttrValue::U16(val),
-                });
-            }
-            ExpectAttrType::U32 => {
-                let val = unsafe { nfexp_get_attr_u32(exp, *attr) };
-                attributes.push(ExpectAttr {
-                    key: *attr,
-                    value: ExpectAttrValue::U32(val),
-                });
-            }
-            ExpectAttrType::String(Some(len)) => {
-                let ptr = unsafe { nfexp_get_attr(exp, *attr) };
-                let cstr = unsafe { std::ffi::CStr::from_ptr(ptr as _) };
-                let s = cstr.to_bytes();
-                let s =
-                    unsafe { CString::from_vec_unchecked(s[0..s.len().min((*len) as _)].to_vec()) };
-                attributes.push(ExpectAttr {
-                    key: *attr,
-                    value: ExpectAttrValue::String(s),
-                });
-            }
-            ExpectAttrType::String(None) => {
-                let ptr = unsafe { nfexp_get_attr(exp, *attr) };
-                let cstr = unsafe { std::ffi::CStr::from_ptr(ptr as _) };
-                let s = cstr.to_bytes();
-                let s = unsafe { CString::from_vec_unchecked(s.to_vec()) };
-                attributes.push(ExpectAttr {
-                    key: *attr,
-                    value: ExpectAttrValue::String(s),
-                });
-            }
-        }
-    }
-
-    let exps: &mut Vec<Expect> = unsafe { &mut *(data_ptr as *mut Vec<Expect>) };
-    exps.push(Expect { attributes });
-
-    MNL_CB_OK
-}
-
 #[derive(Debug, Serialize, Deserialize)]
 struct Expect {
     attributes: Vec<ExpectAttr>,
-- 
2.20.1





More information about the pve-devel mailing list