smoltcp icon indicating copy to clipboard operation
smoltcp copied to clipboard

Abstract SocketSet to AnySocketSet trait

Open cavivie opened this issue 1 year ago • 3 comments

cavivie avatar Jul 01 '24 12:07 cavivie

I'm concerned about the extra complexity caused by having to pass the generic param through everywhere. What's the intended use case of the SocketSet trait?

There are pending possible improvements to SocketSet. For example make packet dispatch more efficient than O(n). However, this makes the trait interface only capable of iteration, which locks us into O(n) more.

Dirbaio avatar Jul 01 '24 18:07 Dirbaio

I am considering customizing the socket set, the addition of socket, query and iteration are closely related, such as the order of socket, etc. I have some cases such as the coexistence of any port and bound port, and tcp and udp should be in different sets. Zone rapid retrieval and iteration, etc., they rely more or less on the order of socket in the set. If you want to complete some complex tasks, it is necessary to do complex processing work in the core dispatcher, and add a custom socket set trait to meet the upper dispatching requirements. I am encapsulating the upper application network protocol stack, and I have been hindered by the socket set to varying degrees. This PR will alleviate a lot of effects, which is also my original intention to do something in rust-managed.

cavivie avatar Jul 02 '24 03:07 cavivie

Anyway, if the above arguments are agreed, then this socket set trait should define other public api other than iteration, which is worth considering. So what do you think you need to consider about this PR?

cavivie avatar Jul 02 '24 03:07 cavivie

@Dirbaio would there be any interest in merging a SocketSet abstraction if the concerns you raised were addressed ? I'm in the same boat where the current implementation is a bit of a hindrance cause I'd want more fine grained locking for multi-threaded std targets, and having better dispatch performance when using a lot of sockets would also be nice.

raftario avatar Jul 09 '25 18:07 raftario

Something like this maybe ?

pub trait SocketSet {
    fn for_each<R, F>(&self, f: F) -> Option<R>
    where
        F: FnMut(&SocketStorage<'_>) -> ControlFlow<R>;
    fn for_each_mut<R, F>(&mut self, f: &mut F) -> Option<R>
    where
        F: FnMut(&mut SocketStorage<'_>) -> ControlFlow<R>;

    fn for_each_accepting<R, F>(&self, ip: &IpRepr, f: &mut F) -> Option<R>
    where
        F: FnMut(&SocketStorage<'_>) -> ControlFlow<R>
    {
        let _ = ip;
        self.for_each(f)
    }
    fn for_each_accepting<R, F>(&mut self, ip: &IpRepr, f: &mut F) -> Option<R>
    where
        F: FnMut(&mut SocketStorage<'_>) -> ControlFlow<R>
    {
        let _ = ip;
        self.for_each_mut(f)
    }
}

impl SocketSet for [SocketStorage<'_>] {
    fn for_each<R, F>(&self, f: F) -> Option<R>
    where
        F: FnMut(&SocketStorage<'_>) -> ControlFlow<R>
    {
        for storage in self {
            match f(storage) {
                ControlFlow::Break(result) => return Some(result),
                ControlFlow::Continue(()) => continue,
            }
        }
        None
    }
    fn for_each_mut<R, F>(&mut self, f: &mut F) -> Option<R>
    where
        F: FnMut(&mut SocketStorage<'_>) -> ControlFlow<R>
    {
        for storage in self {
            match f(storage) {
                ControlFlow::Break(result) => return Some(result),
                ControlFlow::Continue(()) => continue,
            }
        }
        None
    }
}

raftario avatar Jul 10 '25 04:07 raftario