[openbeosnetteam] Re: Unix Sockets

  • From: Philippe Houdoin <philippe.houdoin@xxxxxxx>
  • To: openbeosnetteam@xxxxxxxxxxxxx
  • Date: Mon, 10 Oct 2005 11:45:30 +0200

Hi Sylvain,

> i think to implement unix sockets (AF_UNIX domain) in the following fashion
> :
>
> socket() : allocate a file descriptor
>
> bind() : associate the file descriptor with a file (with fopen())
>
> accept() : returns the file descriptor or dup()
>
> for unnamed socket, create a pipe with mkfifo
>
> For block/non_block options, set the corresponding options on the file.
>
> Do you think this should be allright ?

For the proposed behaviour behind each sockets calls, I agree: using anonymous
or named pipes is a way to do it. Another way is to use your own ring buffers
(Axel wrote a great ring buffers support for... pipefs and keyboard driver
IIRC), but let's start with the simplest way, pipes.

> Other questions :
> -where can i find the source of the ioctl() function in the source tree ? It
> seems to do all the work in the socket() function.

The libnet.so/libsocket.so communicates with the network stack thru the
/dev/net/stack pseudo-device published by net_stack_driver.
The source of this pseudo driver is located under
src/add-ons/kernel/drivers/network/stack/net_stack_driver.c

Give a look at this design graphic:
http://philippe.houdoin.free.fr/phil/beos/openbeos/network_kit/obos_net_stack_design_1.gif

But you SHOULD NOT change this gateway just for Unix sockets!
Nor should you tweak net_stack_driver.c:net_stack_control().
The net_stack_driver.c and the network core module are (or should, at least) be
as much as possible protocols agnostic.

What you need to do is writing a protocol module that handle the AF_UNIX/PF_UNIX
addresses/protocom domain. The current stack code only have AF_INET domain
implemented. I know, the inner details of our stack protocol modules are very
hard to get, mostly because that's a plain port of BSD protocols source code
turned into modular design. :-(

So, it won't be that easy to integrate even a very simple feature like UNIX
sockets into our stack current design.

Anyway, I guess the simple UDP module could be of good inspiration for you here:
src/add-ons/kernel/network/protocols/udp/udp.c
If you look at bottom, you'll see it's a regular (kernel) module, which besides
the classical std_opts() module load/unload callback publish udp_module_init()
and udp_module_stop() callbacks.

These two callbacks will be called by the stack's core at module load/unload
time to allow the protocol to (un)register itself:

You needs to mimic these steps to register UNIX/LOCAL protocol domain

static struct protosw unix_protocol = {
        "UNIX sockets module",
        NET_UNIX_MODULE_NAME,
        SOCK_DGRAM | SOCK_STREAM,
        NULL,
        0,
        PR_ATOMIC | PR_ADDR,
        NET_LAYER3,

        &unix_init,
        &unix_input,
        NULL,                  /* pr_output */
        &unix_userreq,
        NULL,                  /* pr_sysctl */
        &unix_ctlinput,
        NULL,                  /* pr_ctloutput */

        NULL,
        NULL
};


At init:
        core->add_domain(NULL, AF_UNIX);
        core->add_protocol(&unix_protocol, AF_UNIX);

At stop:
        core->remove_protocol(&unix_protocol);
        core->remove_domain(AF_UNIX);

Then, all the inner details seems to be in this protosw struct you should
pass to (un)register a protocol to the stack code.
I barely myself understand how it's supposed to works. For example, I'm not sure
one protosw could support both SOCK_DGRAM and SOCK_STREAM modes. Otherwise, two
structures should be registered from the same module, to support both datagram
and stream UNIX sockets.

Maybe we could both work this out?

- Philippe

Other related posts: