You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Sander Striker <st...@samba-tng.org> on 2001/02/28 11:47:26 UTC

[RFC] Network Abstraction Layer

Hi,

Before I start throwing stuff at you, I'll introduce myself.
I'm Sander Striker, one of the Samba TNG team members. We have
been looking at the APR a bit to find out if we can use it in
our code.

It looks all very promissing and that's why we want to contribute
some ideas to (from our point of view) improve the APR. The first
thing we are going to need is a higher level of abstraction for
the network layer. We have a complicated (to explain to outsiders)
protocol stack in which protocols can be called upon from several
layers.
Example:

 +-------------------+
 |         D         |
 +---------+         |
 |    C    |         |
 |    +----+----+    |
 |    |    B    |    |
 +----+----+---------+
 |         A         |
 +-------------------+

In short:

A <> B
A <> B <> C
A <> B <> C <> D
A <> C
A <> C <> D
A <> D

To make it even more complex B can run over other things than A...

But, I'm boring you guys, so I'll proceed.

Below is a simple draft of the NAL. The goal is to be able to
add transports easily, even when not present in the kernel.
Also this allows an easy way of protocol/transport stacking.
A 'transport' can also do buffering, authentication, filtering.

Ignore name clashes with current APR code please.
Also, I haven't looked into the apr_pool package to understand
how it works quite yet. I want it to be _possible_ to tie transports
to memory management (so we can dump all memory that we used for:
a session, a request, a reply, etc).

I'll post a memory management draft aswell in a few days. It will
be similar to this when it comes abstraction.

Thanks,

Sander


/* typedefs */

typedef struct apr_socket_t apr_socket_t;
typedef struct apr_transport_t apr_transport_t;

typedef int apr_transport_id_t;
/* maybe this should be a string?? So you can
 * do apr_socket_create("smb", &socket, some_pool) */


typedef apr_status_t (*apr_socket_create_fn_t)  (apr_socket_t **socket,
                                                 apr_pool_t *context);

typedef apr_status_t (*apr_socket_bind_fn_t)    (apr_socket_t *socket,
                                                 apr_sockaddr_t *sa);

typedef apr_status_t (*apr_socket_connect_fn_t) (apr_socket_t *socket,
                                                 apr_sockaddr_t *sa);

typedef apr_status_t (*apr_socket_listen_fn_t)  (apr_socket_t *socket,
                                                 apr_int32_t backlog);

typedef apr_status_t (*apr_socket_accept_fn_t)  (apr_socket_t
**client_socket,
                                                 apr_socket_t *socket,
                                                 apr_pool_t
*connection_pool);

typedef apr_status_t (*apr_socket_close_fn_t)   (apr_socket_t *socket);

typedef apr_status_t (*apr_socket_setopt_fn_t)  (apr_socket_t *socket,
                                                 apr_int32_t opt,
                                                 apr_int32_t on);

typedef apr_status_t (*apr_socket_getopt_fn_t)  (apr_socket_t *socket,
                                                 apr_int32_t opt,
                                                 apr_int32_t *on);

typedef apr_status_t (*apr_socket_send_fn_t)    (apr_socket_t *socket,
                                                 const char *buf,
                                                 apr_size_t *len);

typedef apr_status_t (*apr_socket_recv_fn_t)    (apr_socket_t *socket,
                                                 char *buf,
                                                 apr_size_t *len);

typedef apr_status_t (*apr_socket_shutdown_fn_t)(apr_socket_t *socket,
                                                 apr_shutdown_how_e how);


  /* more functions that I possibly left out */



/* structures */

struct apr_transport_t
{
  apr_transport_id_t        transport_id;
  apr_socket_create_fn_t    socket_create;
  apr_socket_bind_fn_t      socket_bind;
  apr_socket_connect_fn_t   socket_connect;
  apr_socket_listen_fn_t    socket_listen;
  apr_socket_accept_fn_t    socket_accept;
  apr_socket_close_fn_t     socket_close;
  apr_socket_setopt_fn_t    socket_setopt;
  apr_socket_getopt_fn_t    socket_getopt;
  apr_socket_send_fn_t      socket_send;
  apr_socket_recv_fn_t      socket_recv;
  apr_socket_shutdown_fn_t  socket_shutdown;
  /* again, more functions that I possibly left out */

};

struct apr_socket_t
{
  apr_transport_t *transport;
  /* transport specific socket implementation follows (should be
     defined by transport implementors) */

};

/* functions */

apr_status_t    apr_transport_add(apr_transport_t *transport);
apr_status_t    apr_transport_remove(apr_transport_t *transport);
apr_transport_t apr_transport_find(apr_transport_id_t transport_id);


/* XXX: maybe do the create using apr_transport_id_t?? */
apr_status_t    apr_socket_create(apr_transport_t *transport,
                                  apr_socket_t **socket,
                                  apr_pool_t *context);

apr_status_t    apr_socket_bind(apr_socket_t *socket,
                                apr_sockaddr_t *sa);

apr_status_t    apr_socket_connect(apr_socket_t *socket,
                                   apr_sockaddr_t *sa);

apr_status_t    apr_socket_listen(apr_socket_t *socket,
                                  apr_int32_t backlog);

apr_status_t    apr_socket_accept(apr_socket_t **client_socket,
                                  apr_socket_t *socket,
                                  apr_pool_t *connection_pool);

apr_status_t    apr_socket_close(apr_socket_t *socket);

apr_status_t    apr_socket_setopt(apr_socket_t *socket,
                                  apr_int32_t opt,
                                  apr_int32_t on);

apr_status_t    apr_socket_getopt(apr_socket_t *socket,
                                  apr_int32_t opt,
                                  apr_int32_t *on);

apr_status_t    apr_socket_send(apr_socket_t *socket,
                                const char *buf,
                                apr_size_t *len);

apr_status_t    apr_socket_recv(apr_socket_t *socket,
                                char *buf,
                                apr_size_t *len);

apr_status_t    apr_socket_shutdown(apr_socket_t *socket,
                                    apr_shutdown_how_e how);


/* implementation */

/* XXX: maybe do the create using apr_transport_id_t?? */
apr_status_t apr_socket_create(apr_transport_t *transport,
                               apr_socket_t **socket,
                               apr_pool_t *context)
{
  assert(transport != NULL);
  assert(transport->apr_socket_create != NULL);

  return transport->apr_socket_create(socket, context);
}

apr_status_t apr_socket_bind(apr_socket_t *socket,
                                apr_sockaddr_t *sa)
{
  assert(socket != NULL);
  assert(socket->transport != NULL);
  assert(socket->transport->socket_bind != NULL);

  return socket->transport->socket_bind(socket, sa);
}

/* rest of high level implementation is trivially the same */


Re: [RFC] Network Abstraction Layer

Posted by Elrond <el...@samba-tng.org>.
On Fri, Mar 02, 2001 at 02:17:05AM -0800, Greg Stein wrote:
[...]
> My personal, uninformed opinion :-) would tend towards adding new
> OS-provided socket types to apr_socket_t (allowing all apps the benefit of
> the new socket types; not just those that can fill in a func table), and
[...]

That gave me a good hint.

I investigate apr_socket_t closely.


I like the _external_ API! It's realy quite good.

It fits quite exactly, what we need.


What I don't like is the "internal" way, because it doesn't
allow an application/library to add apr_socket_ts at
runtime.

I would like something like in the buckets area: Having
some apr_socket_type_t with function pointers and the like.

apr_send() will then mostly only call the appropiate
function pointers and the old "hardcoded" apr_send() will
be that fn-ptr.

Most of this is quite straightforward to implement and it
wont even break any applications (Apache!?), that already
depend on the current API, because most is only internal
rewriting and exposing some things.

The thing, that asks for some proper design is apr_pollfd_t
related stuff:

sockets might have a filedescriptor, that the base
poll()/select() can use, but they might find out, that
there actualy is no data, that they could hand over to the
application.
In the worst case, there might exist sockets, that can't
even provide with a nice filedescriptor, some *arg* polling
or other good means would be needed.

This requires a good thought out API in the
apr_socket_type_t-fn-struct.


BTW: apr already has some "own" sockets: one can convert an
apr_file_t into a socket... I doubt apr_setsockopt (or what
it is named) does any good on it... Having a proper
apr_socket_type_t apr_file_socket_type_t would help here.


    Elrond

Re: [RFC] Network Abstraction Layer

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
> I'd also like to take a moment just to say that I'm describing what we
> currently have.

much appreciate it.  it's all network data, and you['ve basically already
implemented an advanced version of what i was prating-about-with, two and
a half years ago.

> Pick your poison, and if the brigades and filters are not an appropriate
> model for your data, then we can examine how to add an NAL concept to APR.

brigades/filters are _very_ appropriate: see that other message where i
described just how many layers we're having to deal with!

extending those so that you can jump in/out at any point by making it look
like it's terminated with a "socket", when in fact that "socket" is _yet
another_ bucket brigade [on one OS, but not on another], would be a
seriously powerful combination.

luke


 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: [RFC] Network Abstraction Layer

Posted by Greg Stein <gs...@lyra.org>.
On Fri, Mar 02, 2001 at 06:25:56AM +1100, Luke Kenneth Casson Leighton wrote:
> > The issue here is, that the protocols, that are below SMB,
> > are more like sockets. From a clean point of view, they
> > should be implemented in the kernel, but none of us is
> > willing to write kerneldrivers for each OS out there.
> 
> however, on NT, some functions already exist, such as CreateNamedPipe.
> 
> and there is no way in hell i'm writing a kerneldriver for NT when there's
> a perfectly good function already out there.

Yah... that would just suck :-)  Have no fear...

> however, i _am_ prepared to "mirror" that functionality in systems that
> _don't_ have a CreateNamedPipe function.
> 
> so, the implementation of apr_nal_create_socket("namedpipe:foo", ...) on
> NT will call CreateNamedPipe.  which i should imagine will be utterly
> trivial to do.
> 
> and the implementation on non-NT systems will go through hoops and layers
> like there's no tomorrow [i.e. emulating what NT does in the kernel.
> *yuck* :)].
> 
> if the buckets principle can hide this from a developer, so be it.

Yes, you could create a two types of buckets: one for NT using true named
pipes, and one for "those other guys" :-)

The appropriate bucket is inserted into the "input brigade" and the rest of
the input processing is blissfully ignorant. They simply read content from a
bucket.

------------------------

I'd also like to take a moment just to say that I'm describing what we
currently have. I'm not going to try to advocate or force particular choices
on you guys(!)  It's your problem domain, and you know best. I'm just hoping
for a complete description of what we already have, so that you guys can
make an informed decision on the approach to take.

I certainly see no problem with an NAL type concept in APR itself (note that
buckets are "one step higher" in APRUTIL). Or possibly APR just grows more
types of sockets within its existing apr_socket_t public type. It is just
that we may have some other stuff that can help :-)

Pick your poison, and if the brigades and filters are not an appropriate
model for your data, then we can examine how to add an NAL concept to APR.


My personal, uninformed opinion :-) would tend towards adding new
OS-provided socket types to apr_socket_t (allowing all apps the benefit of
the new socket types; not just those that can fill in a func table), and
then building the "selection" mechanisms above that using buckets, brigades,
and filters.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

Re: pool stacking

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
On Fri, 2 Mar 2001, Elrond wrote:

> 
> I've some further notes about pools.
> 
> The reason, why I asked for refcounting:
> 
> An object might want to live in two pools.

under the current impl. of apr_pool.c, it may be possible to modify it to
do that.

but it's currently not set up like that and i would not recommend getting
apr_pool.c to do it.


> Of course it
> should only die, if both pools do not anymore reference
> that object.
> Of course, the object can do the refcounting itself,
> pointing the pools destroy-fn-ptr to its unref-fn.
> 
> Is there a way to remove a object from a pool, without
> knowing the pool it was added to?

no.
 
if you wanted reference counting, then perhaps...


perhaps we could add in some way to extend sms?  or to provide sms-ref as
a wrapper around sms?

sander?

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: pool stacking

Posted by Elrond <el...@samba-tng.org>.
I've some further notes about pools.

The reason, why I asked for refcounting:

An object might want to live in two pools. Of course it
should only die, if both pools do not anymore reference
that object.
Of course, the object can do the refcounting itself,
pointing the pools destroy-fn-ptr to its unref-fn.

Is there a way to remove a object from a pool, without
knowing the pool it was added to?

Pools somewhat resemble, what I once called "rmm -
referencing memory manager", it was somewhat even more
general, apr_pool would have been just another object in
the whole thing and the like... I'm just curious, if most
is there, that I came up with. (it was never implemented,
and I doubt it will ever, nor do I know, if it is actually
necessary)


    Elrond






Re: pool stacking

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
> > i'm going over to sander's at the w/e, we'll see if we can thrash it out.
> 
> Please let us know your result. We've talked about types of pools before.
> One that keeps the current semantics, one that maps straight to malloc/free,
> and one that handled shared memory.
> 
> I didn't know about a GPG memory type :-) Sounds way cool, and I definitely
> bet that we could use that within Apache.

well, it's not so much a GPG memory type as that they have their own
wrappers on memory allocation to make sure that it gets locked (i forget
the system call to do it) and stays in-memory and never swapped to disk.

you don't want your unencrypted private key in a swap file, do you? :)

> We have had some problems with the pool types, however. Consider that you
> pass a function a malloc-based pool. Who calls the free?

ah ha :)

we worked this out.

the sma_mem_sys has pointers to free, destroy, reset, and alloc (which
have corresponding functions - except for free - in apr_pool-ing)

the _users_ of an sma_mem_sys (apache pools, for example), must check if
the parent-sma_mem_sys has either a free or a destroy, and call them if
they exist.



> The function
> doesn't know whether it is a standard pool, or a malloc pool. And inserting
> a bunch of apr_pool_free(ptr) calls (which are noops for some pools) defeats
> the purpose of using pools to avoid carefully tracking free().

...  you still have to call free() in the existing apr_pool code, right???
:) :)

so you call pool->sma_parent->free() instead().

well, actually - implementation of apr_pool_destroy() something like this:

foreach pool alloc'd block:
	if (pool->sma_parent->free != NULL)
		pool->sma_parent->free(pool->sma_parent_data,
		                       pool_alloc'd_block)

followed up by:
if (pool->sma_parent->free_all != NULL)
	pool->sma_parent->free_all(pool->sma_parent_data)

in this way, you cover _both_ cases where the sma_parent instance can
either be capable of doing freeing _or_ is in fact _yet_ another "pool"
allocation system and doesn't have a free at all.

then, you can have an sma_parent which is in fact another apr_pool.

uhm... a little tricky, i know.


> For shared memory, I think we were having some issues with grabbing the
> right amounts of shared memory, then doing the suballocations. I think this
> can be solved, though.

*scared* :)
 
l

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: pool stacking

Posted by Greg Stein <gs...@lyra.org>.
On Fri, Mar 02, 2001 at 09:03:59PM +1100, Luke Kenneth Casson Leighton wrote:
>...
> in xmlvl, i investigated splitting out the pool code into stackable pools.
> sander and i came up with sma_mem_sys as a result.
> 
> imagine that you want to do secure memory stacking, using the gpg
> memory-locking method, but you don't want to have to rewrite entire
> sections of apr and apache to do it.
> 
> passing in a sma_mem_sys (which is an array of parent-pool functions)
> which does gpg-style memory-page-locking into apr_pool_creeate(), you can
> do this.
> 
> the "default" parent-pool sma_mem_sys of course should be one that wraps
> malloc and free.
> 
> you can then define sub-pools to use an apache-pool sma_mem_sys, and in
> fact, the only difference then between a sub-pool and the global pool is
> that the sub-pool uses an apr-sma_mem_sys instance whilst the global pool
> uses a malloc/free-sma_mem_sys.
> 
> i'm going over to sander's at the w/e, we'll see if we can thrash it out.

Please let us know your result. We've talked about types of pools before.
One that keeps the current semantics, one that maps straight to malloc/free,
and one that handled shared memory.

I didn't know about a GPG memory type :-) Sounds way cool, and I definitely
bet that we could use that within Apache.


We have had some problems with the pool types, however. Consider that you
pass a function a malloc-based pool. Who calls the free? The function
doesn't know whether it is a standard pool, or a malloc pool. And inserting
a bunch of apr_pool_free(ptr) calls (which are noops for some pools) defeats
the purpose of using pools to avoid carefully tracking free().

For shared memory, I think we were having some issues with grabbing the
right amounts of shared memory, then doing the suballocations. I think this
can be solved, though.


I do like the idea of pool types, and I know others do, too. At least from
me, there is a big +1 on integrating GPG pools into APR.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

Re: [RFC] Network Abstraction Layer

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
> > so, one bucket can deal with the NetBIOS header.
> 
> Careful. We may be getting some terminology mixed up here.

we?  nahh, just me

> I think we're
> definitely on the same page :-), but I'd like to clarify...

appreciate it.
 
> *) in the above example, the brigade has a HEAP or POOL or some other kind
>    of simple bucket inserted as the first element. It refers to some memory
>    with the appropriate data.
> 
> *) it also has a FILE bucket and an EOS bucket
> 
> *) a filter inserted the bucket into the brigade
> 
> *) in the Samba case, I suspect your NetBIOS header is just another HEAP
>    bucket, inserted by a NetBIOS *filter*

urrrr.... *headache*.  okay.

and the implementation on NT would do NBT but that bypasses IPX, NETBEUI,
TCP/IP, DECnet 3.0, carrier pigeons etc. whilst on samba (or any other
user-level implementation) you have to do it as buckets/filters.

... urr... :)


> > one with the SMB header.
> > 
> > one with the IPC$ layer.
> > 
> > one with the SMBtrans layer.
> > 
> > one with the DCE/RPC pipe layer.
> > 
> > one with the DCE/RPC header layer.
> > 
> > one with the DCE/RPC data.
> 
> Again, I would think *filters* are inserting standard bucket types into the
> brigade. You wouldn't necessarily need to create new bucket types for each
> of the above concepts. You could definitely create filters for each one,
> however.

okay.

getting educated, here.
 
> >...
> > ... we still need an apr_bucket_NAL which can "bounce" in-and-out of
> > buckets, _even though it may actually be implemented as buckets itself,
> > underneath!_ and handle the possibility that on one particular OS - e.g.
> > NT - is in fact a call to a kernel-level function, e.g. CreateNamedPipe().
> 
> Hmm. I'm thinking that a filter would just choose the right kind of bucket
> to insert into the brigade. It could insert a SOCKET bucket, a PIPE bucket,
> or it could read data from the OS over an OS-specific API and then insert a
> HEAP bucket pointing to that memory.

ah ha.  so... a pulling-approach.

... hmmm...

so, you'd be quite happy to educate people that if we want someone to do,
say, the IPC$ and the SMBtrans layer, above (OOPS!  i missed one out!!!
the SMBtrans "named pipe" layer!!! that's 8 layers not 7 :) :) that they
have to know how to deal with three layers and their interactions.  four,
because they're implementing two of them.

what i'd really like to have is that they are told, "you write this
program, it is implemented as a unix-domain-socket, it's a
'NamedPipe'Demon.  to get data to /from the layer below you, call these
functions (SMBipcread, SMBipcwrite, or apr_nal_create("smbipc$")
preferably).  provide _us_ with functions we can call that get data to /
from _you_."

that is a much more obvious, isolated [self-contained], rewarding task,
that i think is... a safer and less daunting task.

now, if apr_nal_create("smbipc$") _happens_ to be implemented in terms of
filters / buckets, and there happens to be a performance-hit because a)
you're doing ux-dom-sock file/io instead of filling in data into the same
memory block, well, i'll take the hit as the payoff is code
maintainability as this project turns from a 300,000 line deal into the
order of millions of lines.

> > or even, later on, let's say that someone decides to provide a linux
> > kernel-level SMB layer or even a NetBIOS kernel API.
> 
> Yup. When this happens, I'd say there are a couple choices:
> 
> 1) write a new bucket type. your "read from network" filter could be
>    configured to insert the new bucket type, rather than a standard type.

> 2) write a new filter which is inserted as the "read from network" filter.
>    it does the job of talking to the new kernel API, and populating the
>    brigade with standard bucket types containing the data.
> 
> 3) a combination of the above two: rather than a configurable filter, you
>    simply insert a new filter which always uses the new custom bucket type.

...

i'm not getting it, then, am i :)

can this be done across several different programs?

i.e. you have one user-space daemon that handles the NetBIOS layer for
you (which is direct-to-kernel if you have linux kernel netbios support,
or you call NT's NBT routines)

and you have one user-space program that _uses_ the NetBIOS layer?

etc.?


> 
> > as you can see, seven levels of buckets like that - all of which a
> 
> Shouldn't this be seven levels of filters?

whoops: sorry :)
 
> In the Apache case, each little black box is a filter. It gets a brigade,
> it operates on that brigade, then it passes it. It doesn't have to know
> where the brigade came from, or who is next in line. It usually doesn't have
> to know anything about the bucket types (just that it can read()).

putting everything into one program, where one program is turing into 10
million lines of code, _that_ scares me.  i dunno about you.

:)

> > what you think?
> 
> It sounds great! I'm encouraged by your interest in the filters, buckets,
> and brigades. It seems to be a matter of some details at the endpoints of
> the filter stack, to determine whether the custom socket is a bucket vs a
> filter, but that should be straightforward.

cool.
 
> 
> Something that I just thought of. Apache operates its I/O in two modes:
> 
> 1) it "pulls" data from an input filter stack
> 
> [ processes it ]
> 
> 2) it "pushes" data into the output filter stack
> 
> 
> I could see a case where the following could be set up:
> 
>               DRIVER
>               /    \
> INPUT-FUNCTION      PROCESS-FILTER -> PROCESS-FILTER -> OUTPUT-FILTER
> 
> The driver sits in a loop, pulling content (a brigade) from (replaceable)
> input function, and then simply shoves that brigade into a processing
> filter. Those filters do all the needed work and just keep moving stuff down
> the line. Eventually, it drops back to the (same) network in the
> output-filter.
> 

and the "input-function" itself could be a process-filter on some OSes but
not on others!

>                                  DRIVER
>                                  /    \
> INPUT_FULTER-PF-PF-INPUT-FUNCTION      PF -> PF -> OUTPUT-FILTER
> 

whoops, that's not exactly right.

the model i am thinking of, the "Driver" is hidden by the apr_nal_* API.
(and is basically the means to decide, on a per-os-basis, whether to use
kernel-level-drivers or another filter-chain).


> Not really sure. Just blue-skying a thought here. It would get complicated a
> bit by certain authentication protocols that need to speak to the output,
> but not run through the filter stack. Ah well...

correct.   which is why we're proposing that the apr_nap_* API contains an
authentication pointer parameter.  thing.

> [ in the Apache case, the filters in the stack are "instantiated" with
>   references to the current connection and request objects. conceivably,
>   Samba would do a similar thing, and it could use the connection object to
>   speak back to the client. ]
> 
> Oh. Silly me. You could set it up such that the processing filters simply
> wouldn't be added until after the authentication occurs. The auth filter
> would simply pass bits-for-the-client to the next filter. More bits will
> arrive at the auth filter, it would verify the auth, and trigger the
> insertion of some processing filters.

oodear :)

... yep: you need to dynamically decide which authentication mechanism
you're going to use, basically.

or better, you say, "stuff this, i'm not going to deal with all that:
we'll define an API that we can do _one_ processing filter that does
'authentication-passing', and you _must_ pre-process and conform to that
filter's API."




> Hoo boy. This is where I step out and let you guys deal with it :-). Just
> ask about Apache's filters, the buckets and brigades, and I (and others
> here!) can handle that... :-)

teehee.

okay.

i didn't mention authentication, did i?  whoops :)

okay.  there are two points at which authentication can occur.  well...
we've only chosen to implement two of the points, however the code we wish
to plug-in can have several more.

there's one authentication point at the SMB level, and another one at the
DCE/RPC level.

so, what i came up with in the TNG architecture was a means to pass unix
uid,gid,unix-groups over a unix domain socket, plus some other
NT-domain-related session / authentication information.

this allows one [isolated] program - smbd - to tell another [isolated]
program - lsarpcd, samrd, netlogond etc. - what the user context is.

smbd in TNG knows absolutely NOTHING about dce/rpc.  zero.

and lsarpcd, samrd and netlogond know zip about SMB.

that kind of isolation, other than security context info, is... well...
kinda important :)


so... we combine best of both approaches, neh?

lukes

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."



Re: [RFC] Network Abstraction Layer

Posted by Greg Stein <gs...@lyra.org>.
On Fri, Mar 02, 2001 at 09:16:27PM +1100, Luke Kenneth Casson Leighton wrote:
> On Fri, 2 Mar 2001, Greg Stein wrote:
>...
> >   BRIGADE = { FILE, EOS }    # FILE bucket and EOS (End Of Stream) bucket
> > 
> > becomes
> > 
> >   BRIGADE = { "packet header bytes", FILE, EOS }
> > 
> > We inserted a header without touching the file. The output filter generates
> > a sendfile which contains an iovec for those header bytes. Blam! Out the
> > network it goes... :-)
>...
> so, one bucket can deal with the NetBIOS header.

Careful. We may be getting some terminology mixed up here. I think we're
definitely on the same page :-), but I'd like to clarify...

*) in the above example, the brigade has a HEAP or POOL or some other kind
   of simple bucket inserted as the first element. It refers to some memory
   with the appropriate data.

*) it also has a FILE bucket and an EOS bucket

*) a filter inserted the bucket into the brigade

*) in the Samba case, I suspect your NetBIOS header is just another HEAP
   bucket, inserted by a NetBIOS *filter*

> one with the SMB header.
> 
> one with the IPC$ layer.
> 
> one with the SMBtrans layer.
> 
> one with the DCE/RPC pipe layer.
> 
> one with the DCE/RPC header layer.
> 
> one with the DCE/RPC data.

Again, I would think *filters* are inserting standard bucket types into the
brigade. You wouldn't necessarily need to create new bucket types for each
of the above concepts. You could definitely create filters for each one,
however.

But I do see a great correlation in the models!

>...
> ... we still need an apr_bucket_NAL which can "bounce" in-and-out of
> buckets, _even though it may actually be implemented as buckets itself,
> underneath!_ and handle the possibility that on one particular OS - e.g.
> NT - is in fact a call to a kernel-level function, e.g. CreateNamedPipe().

Hmm. I'm thinking that a filter would just choose the right kind of bucket
to insert into the brigade. It could insert a SOCKET bucket, a PIPE bucket,
or it could read data from the OS over an OS-specific API and then insert a
HEAP bucket pointing to that memory.

Another approach is a custom bucket that does the OS-specific read. The
filter would then simply insert the custom bucket rather than do the
read-into-HEAP-bucket stuff.

> or even, later on, let's say that someone decides to provide a linux
> kernel-level SMB layer or even a NetBIOS kernel API.

Yup. When this happens, I'd say there are a couple choices:

1) write a new bucket type. your "read from network" filter could be
   configured to insert the new bucket type, rather than a standard type.

2) write a new filter which is inserted as the "read from network" filter.
   it does the job of talking to the new kernel API, and populating the
   brigade with standard bucket types containing the data.

3) a combination of the above two: rather than a configurable filter, you
   simply insert a new filter which always uses the new custom bucket type.

> as you can see, seven levels of buckets like that - all of which a

Shouldn't this be seven levels of filters?

Hmm. I can also see a case where you have a bucket that implements its
read() function by reading from another bucket, performing something on that
data, and returning it. In this sense, the chaining of buckets would be
similar to a chain of filters.

However, I'd think the filters are a slightly better approach, as they
operate on a brigade level rather than a single bucket level. Let's say that
you have a low-level bucket that reads from the network and you get a
partial packet. What should the upper level bucket do? Where should it put
that data while it asks for more data? In the brigade approach, the various
bits of data are accumulated into a brigade until "enough" is available.

> programmer will need to be "aware" of - is exactly what makes me very,
> very wary of introducing "newbie" programmers - no matter _how_ skilled or
> advanced or experienced they are - into this kind of environment.

Agreed. This is why we all try to encapsulate processing between tightly
controlled APIs. Nice little black boxes :-)

In the Apache case, each little black box is a filter. It gets a brigade,
it operates on that brigade, then it passes it. It doesn't have to know
where the brigade came from, or who is next in line. It usually doesn't have
to know anything about the bucket types (just that it can read()).

Then, some "higher level magic" organizes the filters into a useful
sequence, and puts the right data into the filter stack.

> if we can split things out so that an individual programmer only has to
> deal with *at most* two layers - the one they're coming from and the one
> they're going to - i'll be well-happy.

Get a brigade. Muck with it. Send it.   ... nothing more :-)

> and to do _that_, in TNG, i decided to split at the SMBtrans / DCE/RPC
> pipe layer with a unix-domain-socket.  and on NT, that is going to be
> CreateNamedPipe() that will do that for us, bypassing the
> SMBtrans-and-below layers altogether.
> 
> and still get good code reuse / abstraction.
> 
> what you think?

It sounds great! I'm encouraged by your interest in the filters, buckets,
and brigades. It seems to be a matter of some details at the endpoints of
the filter stack, to determine whether the custom socket is a bucket vs a
filter, but that should be straightforward.


Something that I just thought of. Apache operates its I/O in two modes:

1) it "pulls" data from an input filter stack

[ processes it ]

2) it "pushes" data into the output filter stack


I could see a case where the following could be set up:

              DRIVER
              /    \
INPUT-FUNCTION      PROCESS-FILTER -> PROCESS-FILTER -> OUTPUT-FILTER

The driver sits in a loop, pulling content (a brigade) from (replaceable)
input function, and then simply shoves that brigade into a processing
filter. Those filters do all the needed work and just keep moving stuff down
the line. Eventually, it drops back to the (same) network in the
output-filter.

IOW, maybe there isn't an "input filter" so much as a replaceable function
to get brigades of data. All processing is just a matter of shoving the
brigades at an "output" filter stack. But those filters would do things like
decrypt the request, grab a file from the filesystem based on the request,
etc.

Not really sure. Just blue-skying a thought here. It would get complicated a
bit by certain authentication protocols that need to speak to the output,
but not run through the filter stack. Ah well...
[ in the Apache case, the filters in the stack are "instantiated" with
  references to the current connection and request objects. conceivably,
  Samba would do a similar thing, and it could use the connection object to
  speak back to the client. ]

Oh. Silly me. You could set it up such that the processing filters simply
wouldn't be added until after the authentication occurs. The auth filter
would simply pass bits-for-the-client to the next filter. More bits will
arrive at the auth filter, it would verify the auth, and trigger the
insertion of some processing filters.


Hoo boy. This is where I step out and let you guys deal with it :-). Just
ask about Apache's filters, the buckets and brigades, and I (and others
here!) can handle that... :-)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

pool stacking (was Re: [RFC] Network Abstraction Layer)

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
On Fri, 2 Mar 2001, Greg Stein wrote:

> Getting long here. Watch out! :-)

split in two :)

> Even the connection pool is a child of another. The pools can be described
> as a tree of pools, with a single global pool created at startup.

greg,

in xmlvl, i investigated splitting out the pool code into stackable pools.
sander and i came up with sma_mem_sys as a result.

imagine that you want to do secure memory stacking, using the gpg
memory-locking method, but you don't want to have to rewrite entire
sections of apr and apache to do it.

passing in a sma_mem_sys (which is an array of parent-pool functions)
which does gpg-style memory-page-locking into apr_pool_creeate(), you can
do this.

the "default" parent-pool sma_mem_sys of course should be one that wraps
malloc and free.

you can then define sub-pools to use an apache-pool sma_mem_sys, and in
fact, the only difference then between a sub-pool and the global pool is
that the sub-pool uses an apr-sma_mem_sys instance whilst the global pool
uses a malloc/free-sma_mem_sys.

i'm going over to sander's at the w/e, we'll see if we can thrash it out.

luke

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: [RFC] Network Abstraction Layer

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
On Fri, 2 Mar 2001, Greg Stein wrote:

> Getting long here. Watch out! :-)

other-thread.
 
>   BRIGADE = { FILE, EOS }    # FILE bucket and EOS (End Of Stream) bucket
> 
> becomes
> 
>   BRIGADE = { "packet header bytes", FILE, EOS }
> 
> We inserted a header without touching the file. The output filter generates
> a sendfile which contains an iovec for those header bytes. Blam! Out the
> network it goes... :-)

EXCELLENT.  this is exactly the kind of thing that we'll need to do / use.

i started on something like this - memory-based only.  it involved
chaining of bits of memory together, and you didn't have to worry about
how long they each were.

like it a lot.

so, one bucket can deal with the NetBIOS header.

one with the SMB header.

one with the IPC$ layer.

one with the SMBtrans layer.

one with the DCE/RPC pipe layer.

one with the DCE/RPC header layer.

one with the DCE/RPC data.


that's the sort of depth we're going into, here!  and for simplicity, i've
left out all the authentication and encryption stages!

so...

... we still need an apr_bucket_NAL which can "bounce" in-and-out of
buckets, _even though it may actually be implemented as buckets itself,
underneath!_ and handle the possibility that on one particular OS - e.g.
NT - is in fact a call to a kernel-level function, e.g. CreateNamedPipe().

or even, later on, let's say that someone decides to provide a linux
kernel-level SMB layer or even a NetBIOS kernel API.


as you can see, seven levels of buckets like that - all of which a
programmer will need to be "aware" of - is exactly what makes me very,
very wary of introducing "newbie" programmers - no matter _how_ skilled or
advanced or experienced they are - into this kind of environment.

if we can split things out so that an individual programmer only has to
deal with *at most* two layers - the one they're coming from and the one
they're going to - i'll be well-happy.

and to do _that_, in TNG, i decided to split at the SMBtrans / DCE/RPC
pipe layer with a unix-domain-socket.  and on NT, that is going to be
CreateNamedPipe() that will do that for us, bypassing the
SMBtrans-and-below layers altogether.

and still get good code reuse / abstraction.

what you think?

luke

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: [RFC] Network Abstraction Layer

Posted by Greg Stein <gs...@lyra.org>.
Getting long here. Watch out! :-)


On Thu, Mar 01, 2001 at 08:17:10PM +0100, Elrond wrote:
> On Wed, Feb 28, 2001 at 07:40:21AM -0800, Greg Stein wrote:
>...
> > It might be interesting to examine the filters that we have in Apache right
> > now. They provide for the protocol-stacking, buffering, and (hey!)
> > filtering.
> 
> The filters are currently in Apache itself?

Yup.

> That might explain, why I didn't find anything relating to
> filter in apr-util.
> 
> If filters actualy are, what we're looking for, it would be
> nice, if the base of the filters (not the filters
> themselves) be moved into apr-util.
> This might be a good idea anyway.

As I stated elsewhere, there is actually not a lot of stuff related to
filters. Most of the code deals with registration of the filter, rather than
their use. I'm not sure how much has broad utility.

In a nutshell, a filter function has this prototype:

  typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f,
                                             apr_bucket_brigade *bb);

ap_filter_t has a couple pieces of metadata, the filter function pointer,
and a pointer to the "next" filter. A filter function looks something like:

  filter_func(f, bb)
  {
      /* manipulate bb in interesting ways */
      
      return ap_pass_brigade(f->next, bb);
  }

Where ap_pass_brigade is essentially:

  {
      return f->func(f, bb);
  }

The meat of the filter code deals with naming the filters and then creating
the linked list of filters (we insert by name, and filters have an inherent
ordering).

>...
> I've read the complete apr_buckets.h.
> From a _very_ high point of view, bucket brigades are a
> list of buckets, and buckets are simply referring to static
> read-only data, which was (or will be) created.

This is correct. A brigade's contents are read-only, but may be generated
*during* a bucket's read() function (e.g. read the content from a pipe,
socket, or file).

"Manipulating" a brigade involves splitting buckets, inserting or removing
portions, or simply replacing portions. For example, let's say you are a
filter handling server-side-includes (SSI), and you get a brigade with a
single bucket with the string:

  BRIGADE
    \
    BUCKET
     "duration = <!--#var foo --> seconds"

The filter will split this into three buckets:

  BRIGADE
    \
    BUCKET ---------- BUCKET -------------- BUCKET
     "duration = "     "<!--#var foo -->"    " seconds"

It then replaces the middle bucket with a new bucket representing the
request values. Note that the first and last buckets do not copy the value;
they simply point to different parts of the original bucket's value.

> So this is a nice way of moving around data basicaly.

It is a way to do zero-copy of content (presuming that is feasible within
the constraints of the filters' manipulations; a gzip filter simply can't
retain the original data :-)

Since one of the bucket types represents a FILE, you can also inject a file
into the brigade and send that down the output stack. Let's say that nothing
in the chain happens to need the file contents. The file then arrives at the
bottom "filter" of the chain, and sendfile() is used to shove the thing out
onto the network.

This zero-copy is quite feasible when you consider a brigade transform such
as this:

  BRIGADE = { FILE, EOS }    # FILE bucket and EOS (End Of Stream) bucket

becomes

  BRIGADE = { "packet header bytes", FILE, EOS }

We inserted a header without touching the file. The output filter generates
a sendfile which contains an iovec for those header bytes. Blam! Out the
network it goes... :-)

>...
> Some of our protocol layers might be actualy doable as
> filters. (SMB itself quiet likely, at least for the
> fileserving part, SMB does more than fileserving, but it
> probably resembles http in some ways)

Possibly doable. I merely bring it up as something for you to look at. The
brigades are a great way to move around content.

> The part, where Sander's NAL comes in, is the one filter
> that writes stuff to the network:
> 
> In Apache this is most likely a simple unix tcp socket,
> into which you write data.
> NAL tries to abstract sockets.

Right!

> The issue here is, that the protocols, that are below SMB,
> are more like sockets. From a clean point of view, they
> should be implemented in the kernel, but none of us is
> willing to write kerneldrivers for each OS out there.
> 
> If you look through Sander's proposal, nearly all typical
> Unix socket operations are represened as function pointers,
> and actualy nearly each of them needs to be implemented,
> and most of them will actualy do something complex.

Yep, I believe that I understood that part. Note that, in the filter stack
approach, the last "filter" is the thing that delivers to the network. Using
this point, it is possible to define each of those custom "sockets" as one
of these end-point filters.

In Apache, that end-point is a plain socket, as you describe.

In Samba, it could be a filter that delivers to a kernel-level SMB socket.
Or it could be a user-level SMB "socket" that writes to a raw ethernet
device. Depending upon the capabilities of the platform, you insert the
appropriate end-point filter.

The "higher" filters are none-the-wiser... they just pass a brigade to the
next filter. And one of those "next filters" happens to be the last one, and
it happens to get the data onto the network.

> I see one correlation point to filters:
> 
> Maybe there should be an optional
> "append_output_filters_to_filterstack" and
> "prepend_input_filters_to_filterstack". That way, if the
> socket can be represented as filters, and the socket-writer
> has the energy to write those filters, that can be
> optimized. Functions are needed, because the actual used
> filters can be quiet dynamic and could depend on the remote
> system, that we connect to, or if someone actualy
> implemented those sockets in the kernel.

I believe we are describing the same thing :-) ... We probably just have a
bit of terminology differences to come together on.

I think your function names are modelling what we do in Apache, so I'll
explain what we do, and you can see if that matches your thoughts.

In Apache, we have an "MPM" that listens at sockets waiting for connections
to arrive. When one arrives, the MPM creates a "request record" and begins
request processing. The first thing that occurs is that the MPM inserts one
filter onto the input stack, and one filter onto the output stack. The
former is an "input filter" (we've just discussed output filters above)
which knows how to populate a brigade with content from the connection (in
our case, we just put a SOCKET bucket into the brigade and we're done).

For the output filter, it knows how to write a brigade to the socket. It has
some smarts to recognize FILE buckets and sendfile() them. It can use
writev() to write a bunch of plain buckets to the socket. etc.


Now, let's say during request processing, that we want to add a gzip filter
to compress the output, and an SSI filter to process the content. These will
get added with a call such as:

  ap_add_output_filter("GZIP", ctx, request, connection)

Apache looks up the filter from the name, and inserts it into the linked
list. Same goes for the SSI filter.

The missing pieces is that each filter has a self-described ordering. This
allows the SSI filter to handle input first, followed by GZIP, followed by
the network:

output-stack = SSI -> GZIP -> network

As content is fed into the stack, SSI processes it and passes it to "next".
This is the GZIP filter which compresses it and passes it to "next". The
next one is the network filter, which drops it into the socket.


I believe you used the term "append_output_filters_to_filterstack" as a
description of how the network-filter ends up at the end of the above linked
list. We use the self-describe ordering to ensure this since it is simply
too difficult to organize the *timing* of filter insertion in Apache (if all
filters were appended, then you'd have to ensure that SSI went first, then
GZIP was appended, then the network).

For Samba, you may have more control over the timing. Heck, you may not even
need the "linked-list of filters" concept if your output paths are selected
from a pretty rigid set.

> The fallback is more or less clear:
> append_output_filters_to_filterstack defaults to a simple
> filter, that takes the whole brigade and write()s it into
> the socket.

Yes. Our first output filter was like that. Later on, we added more smarts,
so we could use sendfile, TCP_CORK, writev(), etc.

> prepend_input_filters_to_filterstack defaults to the
> opposite.
> Maybe we also might have a apr_bucket_NAL, which is a
> bucket, that reads its data from a NAL socket.

Absolutely! You've got it now :-)

In the Apache case, we simply add a plain old SOCKET bucket to the input
brigade. When the SOCKET finally "empties" itself and the input filter is
called for more, we return an APR_EOF status condition from the filter.

You could add a custom bucket type, or you could keep the complex code in
the filter. Both would work equally well, so it is more of a "design" issue
than a technical one.

Personally, I might choose to implement the NAL bucket so that it could be
used outside of the filter environment.

> I'm not too sure, which of the last ones is actualy the
> right thing to do.
> 
> 
> The next interesting point is, that NALs might have their
> own idea, of how select()/poll() should be handled for
> them.

Right. We have the same issue in Apache, and our "MPM" mechanism is used to
solve this. Some MPMs are single-process and multi-thread, some are
multi-process, etc. Each one defines whether it will select/poll on a bunch
of sockets, or whether it has a thread-per-socket that just does an accept,
or whatever. We have custom MPMs for Windows, BeOS, and OS/2, and then two
or three (styles) for Unix-ish platforms. At the point that a connection and
request arrives, is where the different MPMs come back together to a unified
request-handling system.

> I hope, that explains somewhat the intention behind NAL.

Absolutely! Like I said, we had a similar system at one point, so I saw
exactly where you were going. Here was the structure that we had:

struct ap_iol_methods {
    apr_status_t (*close)(ap_iol *fd);
    apr_status_t (*write)(ap_iol *fd, const char *buf, apr_size_t len,
                          apr_ssize_t *nbytes);
    apr_status_t (*writev)(ap_iol *fd, const struct iovec *vec, apr_size_t nvec,
                           apr_ssize_t *nbytes);
    apr_status_t (*read)(ap_iol *fd, char *buf, apr_size_t len,
                         apr_ssize_t *nbytes);
    apr_status_t (*setopt)(ap_iol *fd, ap_iol_option opt, const void *value);
    apr_status_t (*getopt)(ap_iol *fd, ap_iol_option opt, void *value);
    apr_status_t (*sendfile)(ap_iol *fd, apr_file_t * file, apr_hdtr_t * hdtr, 
                             apr_off_t * offset, apr_size_t * len, 
                             apr_int32_t flags);
    apr_status_t (*shutdown)(ap_iol *fd, int how);
    /* TODO: accept, connect, ... */
};
    
Look familiar? :-)

> Here are some examples of NALs, that are either interesting
> to us, or just fictitious:
> 
> - NetBIOS
> - unix domain sockets (with authentication)
> - NT named Pipes (those are like Unix domain sockets and
>   include authentication already, while the unix side needs
>   to add that)
> - The former two can be wrapped in a single "IPC"-Facility.
> 
> Now some fictitious ones:
> - IPX using raw sockets
> - NetBEUI using raw sockets

All very good examples!

>...
> I haven't looked at pools right now, so if you don't feel
> like answering, simple "RTFM" is okay.

Ask away. You could call us "human doc servers" :-)

> BTW: Do the things in the pool have reference counts? I
> mean, is the pool itself offering refcounting?

No reference counting.

> And I've also seen, that the included objects are included
> with a destroy-function, so one can have pools in pools,
> right?

Yes. For example, we have a connection pool that is created when a
connection first arrives. Various connection-specific stuff is placed in
there. When we begin request processing, a request pool is created as a
child of the connection pool. In many cases during the request processing,
we'll create further child pools of the request pool.

Now, let's say the request is done processing. We just toss the request pool
and everything done during that request is thrown out. No worries throughout
the code of free'ing things (given the comments about "talloc" is sounds
like you guys already know the benefits :-)

On the other hand, let's say the connection drops and we just abort the
request processing. The server will toss the connection pool and it throws
out the connection pool, its (child) request pool, etc.

Even the connection pool is a child of another. The pools can be described
as a tree of pools, with a single global pool created at startup.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

Re: [RFC] Network Abstraction Layer

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
> The issue here is, that the protocols, that are below SMB,
> are more like sockets. From a clean point of view, they
> should be implemented in the kernel, but none of us is
> willing to write kerneldrivers for each OS out there.

however, on NT, some functions already exist, such as CreateNamedPipe.

and there is no way in hell i'm writing a kerneldriver for NT when there's
a perfectly good function already out there.

however, i _am_ prepared to "mirror" that functionality in systems that
_don't_ have a CreateNamedPipe function.

so, the implementation of apr_nal_create_socket("namedpipe:foo", ...) on
NT will call CreateNamedPipe.  which i should imagine will be utterly
trivial to do.

and the implementation on non-NT systems will go through hoops and layers
like there's no tomorrow [i.e. emulating what NT does in the kernel.
*yuck* :)].

if the buckets principle can hide this from a developer, so be it.


> - NT named Pipes (those are like Unix domain sockets and
>   include authentication already, while the unix side needs
>   to add that)

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: [RFC] Network Abstraction Layer

Posted by Elrond <el...@samba-tng.org>.
Hi,

On Wed, Feb 28, 2001 at 07:40:21AM -0800, Greg Stein wrote:
[...]
> >...
> > Below is a simple draft of the NAL. The goal is to be able to
> > add transports easily, even when not present in the kernel.
> > Also this allows an easy way of protocol/transport stacking.
> > A 'transport' can also do buffering, authentication, filtering.
> 
> It might be interesting to examine the filters that we have in Apache right
> now. They provide for the protocol-stacking, buffering, and (hey!)
> filtering.

The filters are currently in Apache itself?
That might explain, why I didn't find anything relating to
filter in apr-util.

If filters actualy are, what we're looking for, it would be
nice, if the base of the filters (not the filters
themselves) be moved into apr-util.
This might be a good idea anyway.


> Apache handles authentication outside of the filter stacks. (two: one stack
> for input, one for output)
> 
> That said: what you outlined is reasonably close to a concept we had a while
> back called IOLs. (Input/Output Layers)  They were tossed about six months
> back in favor of the filter stacks.
> 
> Filters are actually very little code. The heavy lifting is all in the
> buckets and the brigades (see APRUTIL's "buckets" directory). For the most
> part, implementing a filter stack is mostly design policy rather than code.
> What I'm trying to say :-), is that almost everything is already there. If
> there *is* something missing, then we can shove it down from Apache.

I've read the complete apr_buckets.h.
>From a _very_ high point of view, bucket brigades are a
list of buckets, and buckets are simply referring to static
read-only data, which was (or will be) created.

So this is a nice way of moving around data basicaly.

> The essence is that you create a brigade of some data. Then you pass that
> brigade through N functions which each manipulate the brigade in interesting
> ways. Let's take a simple case of generating a file request over an
> encrypted pipe:
> 
> *) Samba creates a brigade containing two buckets: a FILE bucket for the
>    request pipe, and an EOS bucket to signify "end of stream"
> *) the brigade is sent into the "output stack" associated with the current
>    request
> *) the output stack happens to have two filters in it: an encryption filter,
>    and a network filter (the latter places the brigade contents onto the
>    network).
> *) the encryption filter sequences through the brigade, rewriting the
>    contents for the requested encryption. it periodically flushes chunks of
>    work to the next filter in the stack.
> *) the network filter places the content of any brigades passed to right
>    onto the network.
> 
> So... that is the design we happen to be using in Apache, and is emboded in
> the various APR and APRUTIL bits. It might be interesting to determine
> whether a similar design would work for Samba's needs.

Some of our protocol layers might be actualy doable as
filters. (SMB itself quiet likely, at least for the
fileserving part, SMB does more than fileserving, but it
probably resembles http in some ways)

The part, where Sander's NAL comes in, is the one filter
that writes stuff to the network:

In Apache this is most likely a simple unix tcp socket,
into which you write data.
NAL tries to abstract sockets.

The issue here is, that the protocols, that are below SMB,
are more like sockets. From a clean point of view, they
should be implemented in the kernel, but none of us is
willing to write kerneldrivers for each OS out there.

If you look through Sander's proposal, nearly all typical
Unix socket operations are represened as function pointers,
and actualy nearly each of them needs to be implemented,
and most of them will actualy do something complex.

I see one correlation point to filters:

Maybe there should be an optional
"append_output_filters_to_filterstack" and
"prepend_input_filters_to_filterstack". That way, if the
socket can be represented as filters, and the socket-writer
has the energy to write those filters, that can be
optimized. Functions are needed, because the actual used
filters can be quiet dynamic and could depend on the remote
system, that we connect to, or if someone actualy
implemented those sockets in the kernel.

The fallback is more or less clear:
append_output_filters_to_filterstack defaults to a simple
filter, that takes the whole brigade and write()s it into
the socket.

prepend_input_filters_to_filterstack defaults to the
opposite.
Maybe we also might have a apr_bucket_NAL, which is a
bucket, that reads its data from a NAL socket.

I'm not too sure, which of the last ones is actualy the
right thing to do.


The next interesting point is, that NALs might have their
own idea, of how select()/poll() should be handled for
them.


I hope, that explains somewhat the intention behind NAL.


Here are some examples of NALs, that are either interesting
to us, or just fictitious:

- NetBIOS
- unix domain sockets (with authentication)
- NT named Pipes (those are like Unix domain sockets and
  include authentication already, while the unix side needs
  to add that)
- The former two can be wrapped in a single "IPC"-Facility.

Now some fictitious ones:
- IPX using raw sockets
- NetBEUI using raw sockets


> > Ignore name clashes with current APR code please.
> > Also, I haven't looked into the apr_pool package to understand
> > how it works quite yet. I want it to be _possible_ to tie transports
> > to memory management (so we can dump all memory that we used for:
> > a session, a request, a reply, etc).
> 
[... explanation about pools ...]

I haven't looked at pools right now, so if you don't feel
like answering, simple "RTFM" is okay.

BTW: Do the things in the pool have reference counts? I
mean, is the pool itself offering refcounting?

And I've also seen, that the included objects are included
with a destroy-function, so one can have pools in pools,
right?

> > I'll post a memory management draft aswell in a few days. It will
> > be similar to this when it comes abstraction.
> 
> Look forward to it :-)
> 
> Cheers,
> -g


    Elrond


> 
> -- 
> Greg Stein, http://www.lyra.org/

Re: [RFC] Network Abstraction Layer

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
> So... that is the design we happen to be using in Apache, and is emboded in
> the various APR and APRUTIL bits. It might be interesting to determine
> whether a similar design would work for Samba's needs.

samba is an incredibly large monolith.  it is a combination of twelve to
fifteen separate entities, in only two programs, totalling 200,000 lines
of code (the rest is client-side programs).

to introduce some newbie programmer with lots of enthusiasm, or even an
experienced programmer with lots of expertise, into these 350,000 lines,
is asking a lot.

hence the TNG initiative, which subdivides along sensible lines into
separate programs and separate projects.  elrond, for example, has adopted
lsarpcd, which is only 15,000 or so lines (at a guess: he's done a lot of
work on it recently).

the buckets idea sounds like it is very fast, however my impression is
that it is asking programmers to follow some conventions [for decoding]
that an API would impose on them.

the buckets idea sounds similar to what ISS proposed for a redesign of
their RealSecure Engine, which would do multi-layered, multi-threaded
decoding of raw ethernet traffic into first ICMP and UDP, then hand-off to
handlers to do UDP to TCP conversion, then hand-off from the UDP and TCP
"buckets" to protocols such as SSL, http, pop3 etc etc, then hand-off from
SSL to http, pop3 etc etc: you get the idea.

all very fast, all in one program, all very integrated.

the TNG approach is to divide and conquer, which makes for scalability in
project management.


idea.

is it possible to wrap the buckets idea with this  network abstraction
layer idea?

i.e. to implement the NAP using the existing APRUTILS buckets code?

luke

 ----- Luke Kenneth Casson Leighton <lk...@samba-tng.org> -----

"i want a world of dreams, run by near-sighted visionaries"
"good.  that's them sorted out.  now, on _this_ world..."


Re: [RFC] Network Abstraction Layer

Posted by Greg Stein <gs...@lyra.org>.
On Wed, Feb 28, 2001 at 11:47:26AM +0100, Sander Striker wrote:
> Hi,
> 
> Before I start throwing stuff at you, I'll introduce myself.
> I'm Sander Striker, one of the Samba TNG team members. We have
> been looking at the APR a bit to find out if we can use it in
> our code.

Hi! :-)

>...
> Below is a simple draft of the NAL. The goal is to be able to
> add transports easily, even when not present in the kernel.
> Also this allows an easy way of protocol/transport stacking.
> A 'transport' can also do buffering, authentication, filtering.

It might be interesting to examine the filters that we have in Apache right
now. They provide for the protocol-stacking, buffering, and (hey!)
filtering.

Apache handles authentication outside of the filter stacks. (two: one stack
for input, one for output)

That said: what you outlined is reasonably close to a concept we had a while
back called IOLs. (Input/Output Layers)  They were tossed about six months
back in favor of the filter stacks.

Filters are actually very little code. The heavy lifting is all in the
buckets and the brigades (see APRUTIL's "buckets" directory). For the most
part, implementing a filter stack is mostly design policy rather than code.
What I'm trying to say :-), is that almost everything is already there. If
there *is* something missing, then we can shove it down from Apache.

The essence is that you create a brigade of some data. Then you pass that
brigade through N functions which each manipulate the brigade in interesting
ways. Let's take a simple case of generating a file request over an
encrypted pipe:

*) Samba creates a brigade containing two buckets: a FILE bucket for the
   request pipe, and an EOS bucket to signify "end of stream"
*) the brigade is sent into the "output stack" associated with the current
   request
*) the output stack happens to have two filters in it: an encryption filter,
   and a network filter (the latter places the brigade contents onto the
   network).
*) the encryption filter sequences through the brigade, rewriting the
   contents for the requested encryption. it periodically flushes chunks of
   work to the next filter in the stack.
*) the network filter places the content of any brigades passed to right
   onto the network.

So... that is the design we happen to be using in Apache, and is emboded in
the various APR and APRUTIL bits. It might be interesting to determine
whether a similar design would work for Samba's needs.

> Ignore name clashes with current APR code please.
> Also, I haven't looked into the apr_pool package to understand
> how it works quite yet. I want it to be _possible_ to tie transports
> to memory management (so we can dump all memory that we used for:
> a session, a request, a reply, etc).

We use pools within Apache to toss everything associated with a request (and
its response). Same for a connection. I've got to believe they will map very
well onto Samba's needs.

Subversion is using APR, too, and it makes heavy use of pools (no malloc!).
Using pools is so much nicer coding-wise, maintenance-wise, and
understandibility-wise since you don't have to do a bunch of free() calls
everywhere or the nasty "cleanup because an error occurred partway through
this function" series of goto's. At key points, you just toss the pool and
everything goes. In SVN, we have identified key points to partition memory
and to dump when we're done so that a given operation doesn't consume all
memory (e.g. limit the working set). For example, when we recurse into a
directory, we create a pool, use it for everything in the directory, and
then toss it on the way "out" of the directory. Thus, the working set is
proportional to depth rather than everything in a tree.

> I'll post a memory management draft aswell in a few days. It will
> be similar to this when it comes abstraction.

Look forward to it :-)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

Re: [RFC] Network Abstraction Layer - redux

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
On Wed, Jun 13, 2001 at 09:59:57AM -0400, Bill Stoddard wrote:
> Spent a bit of time reviewing the thread and I still think the Samba team proposal 

hiya bill,

quick reality-check, please consider this as independent from
the NAL proposal, and also that i don't speak for sander or elrond.

just to let you know: we're nothing to do with the samba team.

we're the people who are responsible for creating samba's DCE/RPC
capability.  they then decided they could do a better job
['surely it can't be as complicated as all that????'].

i shan't go in to detail: for me, working with APR represents a
clean break from a complete nightmare.


it's past.  history.  time to move on, and working with APR
is how i'd like to do that.

thanks,

luke


Re: [RFC] Network Abstraction Layer - redux

Posted by Bill Stoddard <bi...@wstoddard.com>.
> From: "Bill Stoddard" <bi...@wstoddard.com>
> Sent: Wednesday, June 13, 2001 8:59 AM
>
>
> > Spent a bit of time reviewing the thread and I still think the Samba team proposal
looks
> > very worthwhile (and it scratches a couple of itches for me :-). The NAL enables an
> > architecturally clean solution to a whole class of problems. +1 on implementing
against
> > the API posted by Sander. I expect we will tweak things as we begin to use the API but
it
> > is an excellent start. And I agree with the concensus that we not commit code untill
after
> > Apache 2.0 is released.
>
> You misssed it :-)  Commit code to apr.  That's not the issue.
>
> Until we can prove an overwhelming requirement, and begin Apache 2.1 tree developement,
> simply _don't__use__the__code__in__httpd_.  That's all I'm asking.  If this is a useful
> library, we will introduce things.
>
> Perhaps we need to keep in STATUS a list of 'release' features, 'beta' features, and
> 'under development-experimental' features.  So parts of apr and apr-util can evolve, but
> avoid pi$$ing people off that we keep 'breaking' it.
>
> Just a suggestion, any comments?
>

Only that getting NAL into APR -could- break the API (maybe I'm wrong about that) and that
would impact Apache 2.0. Yea, I am being httpd centric :-) But your point is taken and I
generally agree.

Bill


Re: [RFC] Network Abstraction Layer - redux

Posted by "William A. Rowe, Jr." <ad...@rowe-clan.net>.
From: "Bill Stoddard" <bi...@wstoddard.com>
Sent: Wednesday, June 13, 2001 8:59 AM


> Spent a bit of time reviewing the thread and I still think the Samba team proposal looks
> very worthwhile (and it scratches a couple of itches for me :-). The NAL enables an
> architecturally clean solution to a whole class of problems. +1 on implementing against
> the API posted by Sander. I expect we will tweak things as we begin to use the API but it
> is an excellent start. And I agree with the concensus that we not commit code untill after
> Apache 2.0 is released.

You misssed it :-)  Commit code to apr.  That's not the issue.

Until we can prove an overwhelming requirement, and begin Apache 2.1 tree developement,
simply _don't__use__the__code__in__httpd_.  That's all I'm asking.  If this is a useful
library, we will introduce things.

Perhaps we need to keep in STATUS a list of 'release' features, 'beta' features, and
'under development-experimental' features.  So parts of apr and apr-util can evolve, but
avoid pi$$ing people off that we keep 'breaking' it.

Just a suggestion, any comments?

Bill



Re: [RFC] Network Abstraction Layer - redux

Posted by rb...@covalent.net.
I have read and reviewed the entire thread.  I read and reviewed it when
it was first posted, and I still agree with the decision that was reached
the first time.  Please, post specifics about what itches you are trying
to scratch.  What does this solve?  Without specifics, this is just
hand-waving.

Ryan

On Wed, 13 Jun 2001, Bill Stoddard wrote:

> Spent a bit of time reviewing the thread and I still think the Samba team proposal looks
> very worthwhile (and it scratches a couple of itches for me :-). The NAL enables an
> architecturally clean solution to a whole class of problems. +1 on implementing against
> the API posted by Sander. I expect we will tweak things as we begin to use the API but it
> is an excellent start. And I agree with the concensus that we not commit code untill after
> Apache 2.0 is released.
>
> Bill
>
> >
> > I was under the impression that we had already decided, the last time this
> > thread surfaced, that all of this was possible with filters.  We can
> > redirect to different kinds of network primitives with a different "core"
> > filter.  The "core" filters don't even need to use sockets, they can store
> > their own communication medium in the conn_rec, and just use that.  The
> > only drawback, is that Apache will still require a single socket to
> > operate, but I am not sure that can't be worked around.  A REALLY QUICK
> > grep through the source has us referencing the client socket 28 times
> > directly from the conn_rec.  I am not convinced that some of those can't
> > just be moved to inside a filter.
> >
> > I guess I am asking what this is supposed to accomplish.
> >
> > Ryan
> >
> > On Tue, 12 Jun 2001, Bill Stoddard wrote:
> >
> > > Missed this thread earlier.  I am quite interested in this proposal.  It is similar to
> > > Dean Gaudet's iol work in early Apache 2.0 and is pretty much in line with what I was
> > > needing/thinking as well.  Any interest in reviving this?  The implementation should
> be
> > > quite straightforward. I'll start working on pieces if there is general agreement this
> is
> > > a good thing to do (I think it is).
> > >
> > > Bill Stoddard
> > >
> > > ----- Original Message -----
> > > From: "Sander Striker" <st...@samba-tng.org>
> > > To: <de...@apr.apache.org>
> > > Cc: <lk...@samba-tng.org>; <el...@samba-tng.org>
> > > Sent: Wednesday, February 28, 2001 6:47 AM
> > > Subject: [RFC] Network Abstraction Layer
> > >
> > >
> > > > Hi,
> > > >
> > > > Before I start throwing stuff at you, I'll introduce myself.
> > > > I'm Sander Striker, one of the Samba TNG team members. We have
> > > > been looking at the APR a bit to find out if we can use it in
> > > > our code.
> > > >
> > > > It looks all very promissing and that's why we want to contribute
> > > > some ideas to (from our point of view) improve the APR. The first
> > > > thing we are going to need is a higher level of abstraction for
> > > > the network layer. We have a complicated (to explain to outsiders)
> > > > protocol stack in which protocols can be called upon from several
> > > > layers.
> > > > Example:
> > > >
> > > >  +-------------------+
> > > >  |         D         |
> > > >  +---------+         |
> > > >  |    C    |         |
> > > >  |    +----+----+    |
> > > >  |    |    B    |    |
> > > >  +----+----+---------+
> > > >  |         A         |
> > > >  +-------------------+
> > > >
> > > > In short:
> > > >
> > > > A <> B
> > > > A <> B <> C
> > > > A <> B <> C <> D
> > > > A <> C
> > > > A <> C <> D
> > > > A <> D
> > > >
> > > > To make it even more complex B can run over other things than A...
> > > >
> > > > But, I'm boring you guys, so I'll proceed.
> > > >
> > > > Below is a simple draft of the NAL. The goal is to be able to
> > > > add transports easily, even when not present in the kernel.
> > > > Also this allows an easy way of protocol/transport stacking.
> > > > A 'transport' can also do buffering, authentication, filtering.
> > > >
> > > > Ignore name clashes with current APR code please.
> > > > Also, I haven't looked into the apr_pool package to understand
> > > > how it works quite yet. I want it to be _possible_ to tie transports
> > > > to memory management (so we can dump all memory that we used for:
> > > > a session, a request, a reply, etc).
> > > >
> > > > I'll post a memory management draft aswell in a few days. It will
> > > > be similar to this when it comes abstraction.
> > > >
> > > > Thanks,
> > > >
> > > > Sander
> > > >
> > > >
> > > > /* typedefs */
> > > >
> > > > typedef struct apr_socket_t apr_socket_t;
> > > > typedef struct apr_transport_t apr_transport_t;
> > > >
> > > > typedef int apr_transport_id_t;
> > > > /* maybe this should be a string?? So you can
> > > >  * do apr_socket_create("smb", &socket, some_pool) */
> > > >
> > > >
> > > > typedef apr_status_t (*apr_socket_create_fn_t)  (apr_socket_t **socket,
> > > >                                                  apr_pool_t *context);
> > > >
> > > > typedef apr_status_t (*apr_socket_bind_fn_t)    (apr_socket_t *socket,
> > > >                                                  apr_sockaddr_t *sa);
> > > >
> > > > typedef apr_status_t (*apr_socket_connect_fn_t) (apr_socket_t *socket,
> > > >                                                  apr_sockaddr_t *sa);
> > > >
> > > > typedef apr_status_t (*apr_socket_listen_fn_t)  (apr_socket_t *socket,
> > > >                                                  apr_int32_t backlog);
> > > >
> > > > typedef apr_status_t (*apr_socket_accept_fn_t)  (apr_socket_t
> > > > **client_socket,
> > > >                                                  apr_socket_t *socket,
> > > >                                                  apr_pool_t
> > > > *connection_pool);
> > > >
> > > > typedef apr_status_t (*apr_socket_close_fn_t)   (apr_socket_t *socket);
> > > >
> > > > typedef apr_status_t (*apr_socket_setopt_fn_t)  (apr_socket_t *socket,
> > > >                                                  apr_int32_t opt,
> > > >                                                  apr_int32_t on);
> > > >
> > > > typedef apr_status_t (*apr_socket_getopt_fn_t)  (apr_socket_t *socket,
> > > >                                                  apr_int32_t opt,
> > > >                                                  apr_int32_t *on);
> > > >
> > > > typedef apr_status_t (*apr_socket_send_fn_t)    (apr_socket_t *socket,
> > > >                                                  const char *buf,
> > > >                                                  apr_size_t *len);
> > > >
> > > > typedef apr_status_t (*apr_socket_recv_fn_t)    (apr_socket_t *socket,
> > > >                                                  char *buf,
> > > >                                                  apr_size_t *len);
> > > >
> > > > typedef apr_status_t (*apr_socket_shutdown_fn_t)(apr_socket_t *socket,
> > > >                                                  apr_shutdown_how_e how);
> > > >
> > > >
> > > >   /* more functions that I possibly left out */
> > > >
> > > >
> > > >
> > > > /* structures */
> > > >
> > > > struct apr_transport_t
> > > > {
> > > >   apr_transport_id_t        transport_id;
> > > >   apr_socket_create_fn_t    socket_create;
> > > >   apr_socket_bind_fn_t      socket_bind;
> > > >   apr_socket_connect_fn_t   socket_connect;
> > > >   apr_socket_listen_fn_t    socket_listen;
> > > >   apr_socket_accept_fn_t    socket_accept;
> > > >   apr_socket_close_fn_t     socket_close;
> > > >   apr_socket_setopt_fn_t    socket_setopt;
> > > >   apr_socket_getopt_fn_t    socket_getopt;
> > > >   apr_socket_send_fn_t      socket_send;
> > > >   apr_socket_recv_fn_t      socket_recv;
> > > >   apr_socket_shutdown_fn_t  socket_shutdown;
> > > >   /* again, more functions that I possibly left out */
> > > >
> > > > };
> > > >
> > > > struct apr_socket_t
> > > > {
> > > >   apr_transport_t *transport;
> > > >   /* transport specific socket implementation follows (should be
> > > >      defined by transport implementors) */
> > > >
> > > > };
> > > >
> > > > /* functions */
> > > >
> > > > apr_status_t    apr_transport_add(apr_transport_t *transport);
> > > > apr_status_t    apr_transport_remove(apr_transport_t *transport);
> > > > apr_transport_t apr_transport_find(apr_transport_id_t transport_id);
> > > >
> > > >
> > > > /* XXX: maybe do the create using apr_transport_id_t?? */
> > > > apr_status_t    apr_socket_create(apr_transport_t *transport,
> > > >                                   apr_socket_t **socket,
> > > >                                   apr_pool_t *context);
> > > >
> > > > apr_status_t    apr_socket_bind(apr_socket_t *socket,
> > > >                                 apr_sockaddr_t *sa);
> > > >
> > > > apr_status_t    apr_socket_connect(apr_socket_t *socket,
> > > >                                    apr_sockaddr_t *sa);
> > > >
> > > > apr_status_t    apr_socket_listen(apr_socket_t *socket,
> > > >                                   apr_int32_t backlog);
> > > >
> > > > apr_status_t    apr_socket_accept(apr_socket_t **client_socket,
> > > >                                   apr_socket_t *socket,
> > > >                                   apr_pool_t *connection_pool);
> > > >
> > > > apr_status_t    apr_socket_close(apr_socket_t *socket);
> > > >
> > > > apr_status_t    apr_socket_setopt(apr_socket_t *socket,
> > > >                                   apr_int32_t opt,
> > > >                                   apr_int32_t on);
> > > >
> > > > apr_status_t    apr_socket_getopt(apr_socket_t *socket,
> > > >                                   apr_int32_t opt,
> > > >                                   apr_int32_t *on);
> > > >
> > > > apr_status_t    apr_socket_send(apr_socket_t *socket,
> > > >                                 const char *buf,
> > > >                                 apr_size_t *len);
> > > >
> > > > apr_status_t    apr_socket_recv(apr_socket_t *socket,
> > > >                                 char *buf,
> > > >                                 apr_size_t *len);
> > > >
> > > > apr_status_t    apr_socket_shutdown(apr_socket_t *socket,
> > > >                                     apr_shutdown_how_e how);
> > > >
> > > >
> > > > /* implementation */
> > > >
> > > > /* XXX: maybe do the create using apr_transport_id_t?? */
> > > > apr_status_t apr_socket_create(apr_transport_t *transport,
> > > >                                apr_socket_t **socket,
> > > >                                apr_pool_t *context)
> > > > {
> > > >   assert(transport != NULL);
> > > >   assert(transport->apr_socket_create != NULL);
> > > >
> > > >   return transport->apr_socket_create(socket, context);
> > > > }
> > > >
> > > > apr_status_t apr_socket_bind(apr_socket_t *socket,
> > > >                                 apr_sockaddr_t *sa)
> > > > {
> > > >   assert(socket != NULL);
> > > >   assert(socket->transport != NULL);
> > > >   assert(socket->transport->socket_bind != NULL);
> > > >
> > > >   return socket->transport->socket_bind(socket, sa);
> > > > }
> > > >
> > > > /* rest of high level implementation is trivially the same */
> > > >
> > >
> > >
> >
> >
> > _______________________________________________________________________________
> > Ryan Bloom                        rbb@apache.org
> > 406 29th St.
> > San Francisco, CA 94131
> > -------------------------------------------------------------------------------
> >
>
>


_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [RFC] Network Abstraction Layer - redux

Posted by Bill Stoddard <bi...@wstoddard.com>.
Spent a bit of time reviewing the thread and I still think the Samba team proposal looks
very worthwhile (and it scratches a couple of itches for me :-). The NAL enables an
architecturally clean solution to a whole class of problems. +1 on implementing against
the API posted by Sander. I expect we will tweak things as we begin to use the API but it
is an excellent start. And I agree with the concensus that we not commit code untill after
Apache 2.0 is released.

Bill

>
> I was under the impression that we had already decided, the last time this
> thread surfaced, that all of this was possible with filters.  We can
> redirect to different kinds of network primitives with a different "core"
> filter.  The "core" filters don't even need to use sockets, they can store
> their own communication medium in the conn_rec, and just use that.  The
> only drawback, is that Apache will still require a single socket to
> operate, but I am not sure that can't be worked around.  A REALLY QUICK
> grep through the source has us referencing the client socket 28 times
> directly from the conn_rec.  I am not convinced that some of those can't
> just be moved to inside a filter.
>
> I guess I am asking what this is supposed to accomplish.
>
> Ryan
>
> On Tue, 12 Jun 2001, Bill Stoddard wrote:
>
> > Missed this thread earlier.  I am quite interested in this proposal.  It is similar to
> > Dean Gaudet's iol work in early Apache 2.0 and is pretty much in line with what I was
> > needing/thinking as well.  Any interest in reviving this?  The implementation should
be
> > quite straightforward. I'll start working on pieces if there is general agreement this
is
> > a good thing to do (I think it is).
> >
> > Bill Stoddard
> >
> > ----- Original Message -----
> > From: "Sander Striker" <st...@samba-tng.org>
> > To: <de...@apr.apache.org>
> > Cc: <lk...@samba-tng.org>; <el...@samba-tng.org>
> > Sent: Wednesday, February 28, 2001 6:47 AM
> > Subject: [RFC] Network Abstraction Layer
> >
> >
> > > Hi,
> > >
> > > Before I start throwing stuff at you, I'll introduce myself.
> > > I'm Sander Striker, one of the Samba TNG team members. We have
> > > been looking at the APR a bit to find out if we can use it in
> > > our code.
> > >
> > > It looks all very promissing and that's why we want to contribute
> > > some ideas to (from our point of view) improve the APR. The first
> > > thing we are going to need is a higher level of abstraction for
> > > the network layer. We have a complicated (to explain to outsiders)
> > > protocol stack in which protocols can be called upon from several
> > > layers.
> > > Example:
> > >
> > >  +-------------------+
> > >  |         D         |
> > >  +---------+         |
> > >  |    C    |         |
> > >  |    +----+----+    |
> > >  |    |    B    |    |
> > >  +----+----+---------+
> > >  |         A         |
> > >  +-------------------+
> > >
> > > In short:
> > >
> > > A <> B
> > > A <> B <> C
> > > A <> B <> C <> D
> > > A <> C
> > > A <> C <> D
> > > A <> D
> > >
> > > To make it even more complex B can run over other things than A...
> > >
> > > But, I'm boring you guys, so I'll proceed.
> > >
> > > Below is a simple draft of the NAL. The goal is to be able to
> > > add transports easily, even when not present in the kernel.
> > > Also this allows an easy way of protocol/transport stacking.
> > > A 'transport' can also do buffering, authentication, filtering.
> > >
> > > Ignore name clashes with current APR code please.
> > > Also, I haven't looked into the apr_pool package to understand
> > > how it works quite yet. I want it to be _possible_ to tie transports
> > > to memory management (so we can dump all memory that we used for:
> > > a session, a request, a reply, etc).
> > >
> > > I'll post a memory management draft aswell in a few days. It will
> > > be similar to this when it comes abstraction.
> > >
> > > Thanks,
> > >
> > > Sander
> > >
> > >
> > > /* typedefs */
> > >
> > > typedef struct apr_socket_t apr_socket_t;
> > > typedef struct apr_transport_t apr_transport_t;
> > >
> > > typedef int apr_transport_id_t;
> > > /* maybe this should be a string?? So you can
> > >  * do apr_socket_create("smb", &socket, some_pool) */
> > >
> > >
> > > typedef apr_status_t (*apr_socket_create_fn_t)  (apr_socket_t **socket,
> > >                                                  apr_pool_t *context);
> > >
> > > typedef apr_status_t (*apr_socket_bind_fn_t)    (apr_socket_t *socket,
> > >                                                  apr_sockaddr_t *sa);
> > >
> > > typedef apr_status_t (*apr_socket_connect_fn_t) (apr_socket_t *socket,
> > >                                                  apr_sockaddr_t *sa);
> > >
> > > typedef apr_status_t (*apr_socket_listen_fn_t)  (apr_socket_t *socket,
> > >                                                  apr_int32_t backlog);
> > >
> > > typedef apr_status_t (*apr_socket_accept_fn_t)  (apr_socket_t
> > > **client_socket,
> > >                                                  apr_socket_t *socket,
> > >                                                  apr_pool_t
> > > *connection_pool);
> > >
> > > typedef apr_status_t (*apr_socket_close_fn_t)   (apr_socket_t *socket);
> > >
> > > typedef apr_status_t (*apr_socket_setopt_fn_t)  (apr_socket_t *socket,
> > >                                                  apr_int32_t opt,
> > >                                                  apr_int32_t on);
> > >
> > > typedef apr_status_t (*apr_socket_getopt_fn_t)  (apr_socket_t *socket,
> > >                                                  apr_int32_t opt,
> > >                                                  apr_int32_t *on);
> > >
> > > typedef apr_status_t (*apr_socket_send_fn_t)    (apr_socket_t *socket,
> > >                                                  const char *buf,
> > >                                                  apr_size_t *len);
> > >
> > > typedef apr_status_t (*apr_socket_recv_fn_t)    (apr_socket_t *socket,
> > >                                                  char *buf,
> > >                                                  apr_size_t *len);
> > >
> > > typedef apr_status_t (*apr_socket_shutdown_fn_t)(apr_socket_t *socket,
> > >                                                  apr_shutdown_how_e how);
> > >
> > >
> > >   /* more functions that I possibly left out */
> > >
> > >
> > >
> > > /* structures */
> > >
> > > struct apr_transport_t
> > > {
> > >   apr_transport_id_t        transport_id;
> > >   apr_socket_create_fn_t    socket_create;
> > >   apr_socket_bind_fn_t      socket_bind;
> > >   apr_socket_connect_fn_t   socket_connect;
> > >   apr_socket_listen_fn_t    socket_listen;
> > >   apr_socket_accept_fn_t    socket_accept;
> > >   apr_socket_close_fn_t     socket_close;
> > >   apr_socket_setopt_fn_t    socket_setopt;
> > >   apr_socket_getopt_fn_t    socket_getopt;
> > >   apr_socket_send_fn_t      socket_send;
> > >   apr_socket_recv_fn_t      socket_recv;
> > >   apr_socket_shutdown_fn_t  socket_shutdown;
> > >   /* again, more functions that I possibly left out */
> > >
> > > };
> > >
> > > struct apr_socket_t
> > > {
> > >   apr_transport_t *transport;
> > >   /* transport specific socket implementation follows (should be
> > >      defined by transport implementors) */
> > >
> > > };
> > >
> > > /* functions */
> > >
> > > apr_status_t    apr_transport_add(apr_transport_t *transport);
> > > apr_status_t    apr_transport_remove(apr_transport_t *transport);
> > > apr_transport_t apr_transport_find(apr_transport_id_t transport_id);
> > >
> > >
> > > /* XXX: maybe do the create using apr_transport_id_t?? */
> > > apr_status_t    apr_socket_create(apr_transport_t *transport,
> > >                                   apr_socket_t **socket,
> > >                                   apr_pool_t *context);
> > >
> > > apr_status_t    apr_socket_bind(apr_socket_t *socket,
> > >                                 apr_sockaddr_t *sa);
> > >
> > > apr_status_t    apr_socket_connect(apr_socket_t *socket,
> > >                                    apr_sockaddr_t *sa);
> > >
> > > apr_status_t    apr_socket_listen(apr_socket_t *socket,
> > >                                   apr_int32_t backlog);
> > >
> > > apr_status_t    apr_socket_accept(apr_socket_t **client_socket,
> > >                                   apr_socket_t *socket,
> > >                                   apr_pool_t *connection_pool);
> > >
> > > apr_status_t    apr_socket_close(apr_socket_t *socket);
> > >
> > > apr_status_t    apr_socket_setopt(apr_socket_t *socket,
> > >                                   apr_int32_t opt,
> > >                                   apr_int32_t on);
> > >
> > > apr_status_t    apr_socket_getopt(apr_socket_t *socket,
> > >                                   apr_int32_t opt,
> > >                                   apr_int32_t *on);
> > >
> > > apr_status_t    apr_socket_send(apr_socket_t *socket,
> > >                                 const char *buf,
> > >                                 apr_size_t *len);
> > >
> > > apr_status_t    apr_socket_recv(apr_socket_t *socket,
> > >                                 char *buf,
> > >                                 apr_size_t *len);
> > >
> > > apr_status_t    apr_socket_shutdown(apr_socket_t *socket,
> > >                                     apr_shutdown_how_e how);
> > >
> > >
> > > /* implementation */
> > >
> > > /* XXX: maybe do the create using apr_transport_id_t?? */
> > > apr_status_t apr_socket_create(apr_transport_t *transport,
> > >                                apr_socket_t **socket,
> > >                                apr_pool_t *context)
> > > {
> > >   assert(transport != NULL);
> > >   assert(transport->apr_socket_create != NULL);
> > >
> > >   return transport->apr_socket_create(socket, context);
> > > }
> > >
> > > apr_status_t apr_socket_bind(apr_socket_t *socket,
> > >                                 apr_sockaddr_t *sa)
> > > {
> > >   assert(socket != NULL);
> > >   assert(socket->transport != NULL);
> > >   assert(socket->transport->socket_bind != NULL);
> > >
> > >   return socket->transport->socket_bind(socket, sa);
> > > }
> > >
> > > /* rest of high level implementation is trivially the same */
> > >
> >
> >
>
>
> _______________________________________________________________________________
> Ryan Bloom                        rbb@apache.org
> 406 29th St.
> San Francisco, CA 94131
> -------------------------------------------------------------------------------
>


Re: [RFC] Network Abstraction Layer - redux

Posted by Elrond <el...@samba-tng.org>.
On Wed, Jun 13, 2001 at 01:35:18AM -0400, Bill Stoddard wrote:
> I need to catch up on the other messages in this thread

Yes, please do!

The last message I posted on this thread contains even some
important info for apr_socket_t (which gets near the NAL,
but not as far). I even pointed out some problems in
apr_socket_t.
I haven't gotten a response to this posting till now (I'm
not on the list!)

> so I conceed you may be right,

>From a performance point of view, filters are probably the
right way to do this.

We (the Samba TNG people) asked for NAL, because we
currently don't need performance but _extremely clean_
design and abstraction.


> but one thing I -think- this proposal helps us avoid is
> replicating a lot of code in the core_filters (in and
> out) just to access a different network i/o primitive. 
> Mucking with the core filters seems a clunky way to do
> what the NAL does.

Cool... so someone sees a use outside our goals! :)


> Bill
> 
> ----- Original Message -----
> From: <rb...@covalent.net>
[...]


    Elrond

Re: [RFC] Network Abstraction Layer - redux

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
the purpose of adding a NAL is to be able to farm out 
responsibility for dealing with other transports to
other programs, as proxies for those transports.

given that the filter code is designed to be in-memory,
the only way to achieve inter-process communication
is to use sh-mem, and that's a path i forsee as tricky,
at best.

it also ties in with the proposed apr_namedpipe_xxx() API.

that's _another_ type of communication / transport
that can be added to the list in the NALs.

do you _really_ want to write special filters to have to
deal with each and every single one of these transports?

if i can possibly explain this well enough, i think you
may agree that being able to bounce in-and-out of
separate programs at well-defined boundaries, with one
program being responsible for part of a message [a
header, for example], and treating the rest as opaque
data, makes a lot of sense.

TNG and NT are chock full of such things, and i _know_
that NT has a fully featured implementation of
bucket brigages / filters _and_ a NAL that is extensively
used to provide transport independence and processing of
TCP, UDP, IPX, SPX, NetBIOS, DECNet, SMB, DCE/RPC, Pipes,
LANMAN, IPC$, the whole lot.

luke

> ----- Original Message -----
> From: <rb...@covalent.net>
> To: "Bill Stoddard" <bi...@wstoddard.com>
> Cc: <st...@samba-tng.org>; <de...@apr.apache.org>; <lk...@samba-tng.org>;
> <el...@samba-tng.org>
> Sent: Tuesday, June 12, 2001 11:41 PM
> Subject: Re: [RFC] Network Abstraction Layer - redux
> 
> 
> >
> > I was under the impression that we had already decided, the last time this
> > thread surfaced, that all of this was possible with filters.  We can
> > redirect to different kinds of network primitives with a different "core"
> > filter.  The "core" filters don't even need to use sockets, they can store
> > their own communication medium in the conn_rec, and just use that.  The
> > only drawback, is that Apache will still require a single socket to
> > operate, but I am not sure that can't be worked around.  A REALLY QUICK
> > grep through the source has us referencing the client socket 28 times
> > directly from the conn_rec.  I am not convinced that some of those can't
> > just be moved to inside a filter.

> > > > Before I start throwing stuff at you, I'll introduce myself.
> > > > I'm Sander Striker, one of the Samba TNG team members. We have
> > > > been looking at the APR a bit to find out if we can use it in
> > > > our code.
> > > >
> > > > It looks all very promissing and that's why we want to contribute
> > > > some ideas to (from our point of view) improve the APR. The first
> > > > thing we are going to need is a higher level of abstraction for
> > > > the network layer. We have a complicated (to explain to outsiders)
> > > > protocol stack in which protocols can be called upon from several
> > > > layers.
> > > > Example:

Re: [RFC] Network Abstraction Layer - redux

Posted by Bill Stoddard <bi...@wstoddard.com>.
I need to catch up on the other messages in this thread so I conceed you may be right, but
one thing I -think- this proposal helps us avoid is replicating a lot of code in the
core_filters (in and out) just to access a different network i/o primitive.  Mucking with
the core filters seems a clunky way to do what the NAL does.

Bill

----- Original Message -----
From: <rb...@covalent.net>
To: "Bill Stoddard" <bi...@wstoddard.com>
Cc: <st...@samba-tng.org>; <de...@apr.apache.org>; <lk...@samba-tng.org>;
<el...@samba-tng.org>
Sent: Tuesday, June 12, 2001 11:41 PM
Subject: Re: [RFC] Network Abstraction Layer - redux


>
> I was under the impression that we had already decided, the last time this
> thread surfaced, that all of this was possible with filters.  We can
> redirect to different kinds of network primitives with a different "core"
> filter.  The "core" filters don't even need to use sockets, they can store
> their own communication medium in the conn_rec, and just use that.  The
> only drawback, is that Apache will still require a single socket to
> operate, but I am not sure that can't be worked around.  A REALLY QUICK
> grep through the source has us referencing the client socket 28 times
> directly from the conn_rec.  I am not convinced that some of those can't
> just be moved to inside a filter.
>
> I guess I am asking what this is supposed to accomplish.
>
> Ryan
>
> On Tue, 12 Jun 2001, Bill Stoddard wrote:
>
> > Missed this thread earlier.  I am quite interested in this proposal.  It is similar to
> > Dean Gaudet's iol work in early Apache 2.0 and is pretty much in line with what I was
> > needing/thinking as well.  Any interest in reviving this?  The implementation should
be
> > quite straightforward. I'll start working on pieces if there is general agreement this
is
> > a good thing to do (I think it is).
> >
> > Bill Stoddard
> >
> > ----- Original Message -----
> > From: "Sander Striker" <st...@samba-tng.org>
> > To: <de...@apr.apache.org>
> > Cc: <lk...@samba-tng.org>; <el...@samba-tng.org>
> > Sent: Wednesday, February 28, 2001 6:47 AM
> > Subject: [RFC] Network Abstraction Layer
> >
> >
> > > Hi,
> > >
> > > Before I start throwing stuff at you, I'll introduce myself.
> > > I'm Sander Striker, one of the Samba TNG team members. We have
> > > been looking at the APR a bit to find out if we can use it in
> > > our code.
> > >
> > > It looks all very promissing and that's why we want to contribute
> > > some ideas to (from our point of view) improve the APR. The first
> > > thing we are going to need is a higher level of abstraction for
> > > the network layer. We have a complicated (to explain to outsiders)
> > > protocol stack in which protocols can be called upon from several
> > > layers.
> > > Example:
> > >
> > >  +-------------------+
> > >  |         D         |
> > >  +---------+         |
> > >  |    C    |         |
> > >  |    +----+----+    |
> > >  |    |    B    |    |
> > >  +----+----+---------+
> > >  |         A         |
> > >  +-------------------+
> > >
> > > In short:
> > >
> > > A <> B
> > > A <> B <> C
> > > A <> B <> C <> D
> > > A <> C
> > > A <> C <> D
> > > A <> D
> > >
> > > To make it even more complex B can run over other things than A...
> > >
> > > But, I'm boring you guys, so I'll proceed.
> > >
> > > Below is a simple draft of the NAL. The goal is to be able to
> > > add transports easily, even when not present in the kernel.
> > > Also this allows an easy way of protocol/transport stacking.
> > > A 'transport' can also do buffering, authentication, filtering.
> > >
> > > Ignore name clashes with current APR code please.
> > > Also, I haven't looked into the apr_pool package to understand
> > > how it works quite yet. I want it to be _possible_ to tie transports
> > > to memory management (so we can dump all memory that we used for:
> > > a session, a request, a reply, etc).
> > >
> > > I'll post a memory management draft aswell in a few days. It will
> > > be similar to this when it comes abstraction.
> > >
> > > Thanks,
> > >
> > > Sander
> > >
> > >
> > > /* typedefs */
> > >
> > > typedef struct apr_socket_t apr_socket_t;
> > > typedef struct apr_transport_t apr_transport_t;
> > >
> > > typedef int apr_transport_id_t;
> > > /* maybe this should be a string?? So you can
> > >  * do apr_socket_create("smb", &socket, some_pool) */
> > >
> > >
> > > typedef apr_status_t (*apr_socket_create_fn_t)  (apr_socket_t **socket,
> > >                                                  apr_pool_t *context);
> > >
> > > typedef apr_status_t (*apr_socket_bind_fn_t)    (apr_socket_t *socket,
> > >                                                  apr_sockaddr_t *sa);
> > >
> > > typedef apr_status_t (*apr_socket_connect_fn_t) (apr_socket_t *socket,
> > >                                                  apr_sockaddr_t *sa);
> > >
> > > typedef apr_status_t (*apr_socket_listen_fn_t)  (apr_socket_t *socket,
> > >                                                  apr_int32_t backlog);
> > >
> > > typedef apr_status_t (*apr_socket_accept_fn_t)  (apr_socket_t
> > > **client_socket,
> > >                                                  apr_socket_t *socket,
> > >                                                  apr_pool_t
> > > *connection_pool);
> > >
> > > typedef apr_status_t (*apr_socket_close_fn_t)   (apr_socket_t *socket);
> > >
> > > typedef apr_status_t (*apr_socket_setopt_fn_t)  (apr_socket_t *socket,
> > >                                                  apr_int32_t opt,
> > >                                                  apr_int32_t on);
> > >
> > > typedef apr_status_t (*apr_socket_getopt_fn_t)  (apr_socket_t *socket,
> > >                                                  apr_int32_t opt,
> > >                                                  apr_int32_t *on);
> > >
> > > typedef apr_status_t (*apr_socket_send_fn_t)    (apr_socket_t *socket,
> > >                                                  const char *buf,
> > >                                                  apr_size_t *len);
> > >
> > > typedef apr_status_t (*apr_socket_recv_fn_t)    (apr_socket_t *socket,
> > >                                                  char *buf,
> > >                                                  apr_size_t *len);
> > >
> > > typedef apr_status_t (*apr_socket_shutdown_fn_t)(apr_socket_t *socket,
> > >                                                  apr_shutdown_how_e how);
> > >
> > >
> > >   /* more functions that I possibly left out */
> > >
> > >
> > >
> > > /* structures */
> > >
> > > struct apr_transport_t
> > > {
> > >   apr_transport_id_t        transport_id;
> > >   apr_socket_create_fn_t    socket_create;
> > >   apr_socket_bind_fn_t      socket_bind;
> > >   apr_socket_connect_fn_t   socket_connect;
> > >   apr_socket_listen_fn_t    socket_listen;
> > >   apr_socket_accept_fn_t    socket_accept;
> > >   apr_socket_close_fn_t     socket_close;
> > >   apr_socket_setopt_fn_t    socket_setopt;
> > >   apr_socket_getopt_fn_t    socket_getopt;
> > >   apr_socket_send_fn_t      socket_send;
> > >   apr_socket_recv_fn_t      socket_recv;
> > >   apr_socket_shutdown_fn_t  socket_shutdown;
> > >   /* again, more functions that I possibly left out */
> > >
> > > };
> > >
> > > struct apr_socket_t
> > > {
> > >   apr_transport_t *transport;
> > >   /* transport specific socket implementation follows (should be
> > >      defined by transport implementors) */
> > >
> > > };
> > >
> > > /* functions */
> > >
> > > apr_status_t    apr_transport_add(apr_transport_t *transport);
> > > apr_status_t    apr_transport_remove(apr_transport_t *transport);
> > > apr_transport_t apr_transport_find(apr_transport_id_t transport_id);
> > >
> > >
> > > /* XXX: maybe do the create using apr_transport_id_t?? */
> > > apr_status_t    apr_socket_create(apr_transport_t *transport,
> > >                                   apr_socket_t **socket,
> > >                                   apr_pool_t *context);
> > >
> > > apr_status_t    apr_socket_bind(apr_socket_t *socket,
> > >                                 apr_sockaddr_t *sa);
> > >
> > > apr_status_t    apr_socket_connect(apr_socket_t *socket,
> > >                                    apr_sockaddr_t *sa);
> > >
> > > apr_status_t    apr_socket_listen(apr_socket_t *socket,
> > >                                   apr_int32_t backlog);
> > >
> > > apr_status_t    apr_socket_accept(apr_socket_t **client_socket,
> > >                                   apr_socket_t *socket,
> > >                                   apr_pool_t *connection_pool);
> > >
> > > apr_status_t    apr_socket_close(apr_socket_t *socket);
> > >
> > > apr_status_t    apr_socket_setopt(apr_socket_t *socket,
> > >                                   apr_int32_t opt,
> > >                                   apr_int32_t on);
> > >
> > > apr_status_t    apr_socket_getopt(apr_socket_t *socket,
> > >                                   apr_int32_t opt,
> > >                                   apr_int32_t *on);
> > >
> > > apr_status_t    apr_socket_send(apr_socket_t *socket,
> > >                                 const char *buf,
> > >                                 apr_size_t *len);
> > >
> > > apr_status_t    apr_socket_recv(apr_socket_t *socket,
> > >                                 char *buf,
> > >                                 apr_size_t *len);
> > >
> > > apr_status_t    apr_socket_shutdown(apr_socket_t *socket,
> > >                                     apr_shutdown_how_e how);
> > >
> > >
> > > /* implementation */
> > >
> > > /* XXX: maybe do the create using apr_transport_id_t?? */
> > > apr_status_t apr_socket_create(apr_transport_t *transport,
> > >                                apr_socket_t **socket,
> > >                                apr_pool_t *context)
> > > {
> > >   assert(transport != NULL);
> > >   assert(transport->apr_socket_create != NULL);
> > >
> > >   return transport->apr_socket_create(socket, context);
> > > }
> > >
> > > apr_status_t apr_socket_bind(apr_socket_t *socket,
> > >                                 apr_sockaddr_t *sa)
> > > {
> > >   assert(socket != NULL);
> > >   assert(socket->transport != NULL);
> > >   assert(socket->transport->socket_bind != NULL);
> > >
> > >   return socket->transport->socket_bind(socket, sa);
> > > }
> > >
> > > /* rest of high level implementation is trivially the same */
> > >
> >
> >
>
>
> _______________________________________________________________________________
> Ryan Bloom                        rbb@apache.org
> 406 29th St.
> San Francisco, CA 94131
> -------------------------------------------------------------------------------
>


Re: [RFC] Network Abstraction Layer - redux

Posted by Luke Kenneth Casson Leighton <lk...@samba-tng.org>.
> But can we, absolutely, postively, table any change that affects an httpd 2.0
> release?  

ack! agree! :)


Re: [RFC] Network Abstraction Layer - redux

Posted by rb...@covalent.net.
> > 2. I gave a pitch about IBM's Fast Response Cache Accelerator (aka AFPA) at ApacheCon a
> > few years back. The AFPA implementation on Windows uses it's own socket API (afpa_read,
> > afpa_accept, afpa_send, et. al.).  Again, the NAL provides a clean way for my Apache
> > module to hook the right NAL implementing my specific network io primitives with the
> > minimum amount of shuffleing httpd code.
> >
> > Can I do both of these with filters? Sure, but the code architecturally ugly as sin.
> > Allan Edwards solved both of these problems cleanly in early Apache 2.0 iterations using
> > Dean Gaudet's IOLs. NAL is essentially a scaled back version of Dean's IOLs (NAL is
> > focused just on network i/o, not filtering). And I know what Luke is talking about as
> > well.  Windows NT does implement filters (AFPA uses file system filters) in addition to a
> > network io abstraction layer.  NAL is a great compliment to filters.
>
> So ... why did we drop IOL? :-)

Because they were complex, and couldn't do what they were supposed to do,
namely implement filtering.  They just weren't necessary anymore.  Maybe
they are now, I don't think so, but I am willing to be wrong.  If we do
re-implement them, I would appreciate it if IOL's were easier to debug
this time.  The original IOL's were almost impossible to debug, because
you couldn't get to the underlying transport mechanism.

Ryan

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [RFC] Network Abstraction Layer - redux

Posted by Ben Laurie <be...@algroup.co.uk>.
Bill Stoddard wrote:
> I would argue that we do not have a good (read architecturally clean) way to abstract
> network io with filters. The NAL is a perfect compliment to the filter code. Here are my
> specific itches:
> 
> 1.  My SSL library API uses a different model than OpenSSL. Specifically, it uses uses
> secure_socket calls (e.g., secure_read(), secure_write(), etc.).  I -could- integrate SSL
> into Apache 2.0 using filters, but I would have to replace core_inout_filter and
> core_output_filter with my own filters, possibly implement special bucket types
> (apr_bucket_secure_socket_t, etc.)  With NAL, I can just hook the network io primitives
> with my own calls and use the filters already in Apache. I hope to use OpenSSL but that is
> just not a possibility now. My itch is real to me even if you don;t feel it :-)

FWIW you can also run OpenSSL in this mode, but I elected not to (coz
then SSL will work automagically over other transports).

> 2. I gave a pitch about IBM's Fast Response Cache Accelerator (aka AFPA) at ApacheCon a
> few years back. The AFPA implementation on Windows uses it's own socket API (afpa_read,
> afpa_accept, afpa_send, et. al.).  Again, the NAL provides a clean way for my Apache
> module to hook the right NAL implementing my specific network io primitives with the
> minimum amount of shuffleing httpd code.
> 
> Can I do both of these with filters? Sure, but the code architecturally ugly as sin.
> Allan Edwards solved both of these problems cleanly in early Apache 2.0 iterations using
> Dean Gaudet's IOLs. NAL is essentially a scaled back version of Dean's IOLs (NAL is
> focused just on network i/o, not filtering). And I know what Luke is talking about as
> well.  Windows NT does implement filters (AFPA uses file system filters) in addition to a
> network io abstraction layer.  NAL is a great compliment to filters.

So ... why did we drop IOL? :-)

Cheers,

Ben.

--
http://www.apache-ssl.org/ben.html

"There is no limit to what a man can do or how far he can go if he
doesn't mind who gets the credit." - Robert Woodruff

Re: [RFC] Network Abstraction Layer - redux

Posted by Ben Laurie <be...@algroup.co.uk>.
Bill Stoddard wrote:
> Third, all the network io is done via apr_socket_t structs which are created in the MPMs
> and propogated to other parts of Apache.  By definition, I am not interested in dealing
> with apr_socket_t structs (slightly modfied apr_socket_t structs maybe).  How do we handle
> each place in the Apache code where we frob (look at, call an API with, whatever) an
> apr_socket_t and expect a real 'socket'?  Where do I store my custom structure I use for
> networkio? I would like to be able to use the apr_socket_t structure and tweak it slightly
> for my custom calls, but that structure is opaque to Apache.

Gleep! Tell me we don't do this!

Cheers,

Ben.

--
http://www.apache-ssl.org/ben.html

"There is no limit to what a man can do or how far he can go if he
doesn't mind who gets the credit." - Robert Woodruff

Re: [RFC] Network Abstraction Layer - redux

Posted by Bill Stoddard <bi...@wstoddard.com>.
> > > The problem I have with this code idea isn't that it isn't useful to
> > > httpd.  It is that we have been down this road once, and the model wasn't
> > > flexible enough.  What problem are we trying to solve that the filter
> > > mechanism doesn't solve?  If the answer to that question is "filters are
> > > in Apache, and we want this out of Apache", then move filters out of
> > > Apache.
> >
> > No way man :-)
>
> Why not?

"No way man" is my answer to your question about possibly removing filters from Apache.
Filters are good. :-)

>
> > > If the answer is, "We need a better way to abstract the network
> > > for x, y, and z", then cool let's do it.
> >
> > I would argue that we do not have a good (read architecturally clean) way to abstract
> > network io with filters. The NAL is a perfect compliment to the filter code. Here are
my
> > specific itches:
> >
> > 1.  My SSL library API uses a different model than OpenSSL. Specifically, it uses uses
> > secure_socket calls (e.g., secure_read(), secure_write(), etc.).  I -could- integrate
SSL
> > into Apache 2.0 using filters, but I would have to replace core_inout_filter and
> > core_output_filter with my own filters, possibly implement special bucket types
> > (apr_bucket_secure_socket_t, etc.)  With NAL, I can just hook the network io
primitives
> > with my own calls and use the filters already in Apache. I hope to use OpenSSL but
that is
> > just not a possibility now. My itch is real to me even if you don;t feel it :-)
>
> I'm not saying your itch isn't real, I'm saying I disagree with how you
> want to scratch it.  :-)
>
> > 2. I gave a pitch about IBM's Fast Response Cache Accelerator (aka AFPA) at ApacheCon
a
> > few years back. The AFPA implementation on Windows uses it's own socket API
(afpa_read,
> > afpa_accept, afpa_send, et. al.).  Again, the NAL provides a clean way for my Apache
> > module to hook the right NAL implementing my specific network io primitives with the
> > minimum amount of shuffleing httpd code.
> >
> > Can I do both of these with filters? Sure, but the code architecturally ugly as sin.
> > Allan Edwards solved both of these problems cleanly in early Apache 2.0 iterations
using
> > Dean Gaudet's IOLs. NAL is essentially a scaled back version of Dean's IOLs (NAL is
> > focused just on network i/o, not filtering). And I know what Luke is talking about as
> > well.  Windows NT does implement filters (AFPA uses file system filters) in addition
to a
> > network io abstraction layer.  NAL is a great compliment to filters.
>
> I'm saying that the code doesn't need to be architecturally ugly.  The
> problem, is that our core filters are big and do too much, IMNSHO.  Break
> out the core filters to smaller chunks that are available to other
> filters, and I believe this will solve your problem completely.
>

I think you are saying that you believe it is possible to make the 'last filter'
(currently the core_[input|output]_filter) a very thin filter whose primary purpose is to
do network io; either via an apr_network_io interface, or via a custom interface? Is that
about right?   If so, I think that has some problems (perhaps solvable in a clean way).

First problem is with where the network abstraction occurs. In the NAL, the abstraction is
at the lowest possible level, at the core network io primitive level.  With your solution,
the abstraction occurs at the apr_network_io level. This means that my primitives will
have to reimplement a lot of the buffering/locking/whatever code that is currently
implemented in the apr_network_io code.  Custom network io primitives must be semantically
identical to the network io primitives they are replacing. It is much easier to do this at
the socket level than at the apr_network_io level.

Second, not all the network i/o we do is in the core filters.  MPMs do network operations
(accept, lingering close, etc.).

Third, all the network io is done via apr_socket_t structs which are created in the MPMs
and propogated to other parts of Apache.  By definition, I am not interested in dealing
with apr_socket_t structs (slightly modfied apr_socket_t structs maybe).  How do we handle
each place in the Apache code where we frob (look at, call an API with, whatever) an
apr_socket_t and expect a real 'socket'?  Where do I store my custom structure I use for
networkio? I would like to be able to use the apr_socket_t structure and tweak it slightly
for my custom calls, but that structure is opaque to Apache.

Bill




Re: [RFC] Network Abstraction Layer - redux

Posted by rb...@covalent.net.
> > The problem I have with this code idea isn't that it isn't useful to
> > httpd.  It is that we have been down this road once, and the model wasn't
> > flexible enough.  What problem are we trying to solve that the filter
> > mechanism doesn't solve?  If the answer to that question is "filters are
> > in Apache, and we want this out of Apache", then move filters out of
> > Apache.
>
> No way man :-)

Why not?

> > If the answer is, "We need a better way to abstract the network
> > for x, y, and z", then cool let's do it.
>
> I would argue that we do not have a good (read architecturally clean) way to abstract
> network io with filters. The NAL is a perfect compliment to the filter code. Here are my
> specific itches:
>
> 1.  My SSL library API uses a different model than OpenSSL. Specifically, it uses uses
> secure_socket calls (e.g., secure_read(), secure_write(), etc.).  I -could- integrate SSL
> into Apache 2.0 using filters, but I would have to replace core_inout_filter and
> core_output_filter with my own filters, possibly implement special bucket types
> (apr_bucket_secure_socket_t, etc.)  With NAL, I can just hook the network io primitives
> with my own calls and use the filters already in Apache. I hope to use OpenSSL but that is
> just not a possibility now. My itch is real to me even if you don;t feel it :-)

I'm not saying your itch isn't real, I'm saying I disagree with how you
want to scratch it.  :-)

> 2. I gave a pitch about IBM's Fast Response Cache Accelerator (aka AFPA) at ApacheCon a
> few years back. The AFPA implementation on Windows uses it's own socket API (afpa_read,
> afpa_accept, afpa_send, et. al.).  Again, the NAL provides a clean way for my Apache
> module to hook the right NAL implementing my specific network io primitives with the
> minimum amount of shuffleing httpd code.
>
> Can I do both of these with filters? Sure, but the code architecturally ugly as sin.
> Allan Edwards solved both of these problems cleanly in early Apache 2.0 iterations using
> Dean Gaudet's IOLs. NAL is essentially a scaled back version of Dean's IOLs (NAL is
> focused just on network i/o, not filtering). And I know what Luke is talking about as
> well.  Windows NT does implement filters (AFPA uses file system filters) in addition to a
> network io abstraction layer.  NAL is a great compliment to filters.

I'm saying that the code doesn't need to be architecturally ugly.  The
problem, is that our core filters are big and do too much, IMNSHO.  Break
out the core filters to smaller chunks that are available to other
filters, and I believe this will solve your problem completely.

Ryan

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [RFC] Network Abstraction Layer - redux

Posted by Bill Stoddard <bi...@wstoddard.com>.
> On Tue, 12 Jun 2001, William A. Rowe, Jr. wrote:
>
> > From: <rb...@covalent.net>
> > Sent: Tuesday, June 12, 2001 10:41 PM
> >
> >
> > > I was under the impression that we had already decided, the last time this
> > > thread surfaced, that all of this was possible with filters.  We can
> > > redirect to different kinds of network primitives with a different "core"
> > > filter.  The "core" filters don't even need to use sockets, they can store
> > > their own communication medium in the conn_rec, and just use that.  The
> > > only drawback, is that Apache will still require a single socket to
> > > operate, but I am not sure that can't be worked around.  A REALLY QUICK
> > > grep through the source has us referencing the client socket 28 times
> > > directly from the conn_rec.  I am not convinced that some of those can't
> > > just be moved to inside a filter.
> > >
> > > I guess I am asking what this is supposed to accomplish.
> >
> > In all fairness,
> >
> > APR does bucket brigades.  It does socket management.  I think this would be a fine
> > addition to our APR arsenal.
> >
> > But can we, absolutely, postively, table any change that affects an httpd 2.0
> > release?  IOW, no samba-team iol into Apache 2.0.  Develop the API, impement the
> > code, go to town.  But I think we've reached a juncture...
> >
> >     not everything in apr exists for or is even used by Apache
> >
> > If what results can improve httpd 2.1, then fantastic!  If not, it's still fantastic
:-)
> > There's alot more to do on the net beyond Apache, if we can fuel those directions,
then
> > we really have a worthwhile library project, and not just an adjunct of httpd.
>
> The problem I have with this code idea isn't that it isn't useful to
> httpd.  It is that we have been down this road once, and the model wasn't
> flexible enough.  What problem are we trying to solve that the filter
> mechanism doesn't solve?  If the answer to that question is "filters are
> in Apache, and we want this out of Apache", then move filters out of
> Apache.

No way man :-)

> If the answer is, "We need a better way to abstract the network
> for x, y, and z", then cool let's do it.

I would argue that we do not have a good (read architecturally clean) way to abstract
network io with filters. The NAL is a perfect compliment to the filter code. Here are my
specific itches:

1.  My SSL library API uses a different model than OpenSSL. Specifically, it uses uses
secure_socket calls (e.g., secure_read(), secure_write(), etc.).  I -could- integrate SSL
into Apache 2.0 using filters, but I would have to replace core_inout_filter and
core_output_filter with my own filters, possibly implement special bucket types
(apr_bucket_secure_socket_t, etc.)  With NAL, I can just hook the network io primitives
with my own calls and use the filters already in Apache. I hope to use OpenSSL but that is
just not a possibility now. My itch is real to me even if you don;t feel it :-)

2. I gave a pitch about IBM's Fast Response Cache Accelerator (aka AFPA) at ApacheCon a
few years back. The AFPA implementation on Windows uses it's own socket API (afpa_read,
afpa_accept, afpa_send, et. al.).  Again, the NAL provides a clean way for my Apache
module to hook the right NAL implementing my specific network io primitives with the
minimum amount of shuffleing httpd code.

Can I do both of these with filters? Sure, but the code architecturally ugly as sin.
Allan Edwards solved both of these problems cleanly in early Apache 2.0 iterations using
Dean Gaudet's IOLs. NAL is essentially a scaled back version of Dean's IOLs (NAL is
focused just on network i/o, not filtering). And I know what Luke is talking about as
well.  Windows NT does implement filters (AFPA uses file system filters) in addition to a
network io abstraction layer.  NAL is a great compliment to filters.

Bill


Re: [RFC] Network Abstraction Layer - redux

Posted by rb...@covalent.net.
On Tue, 12 Jun 2001, William A. Rowe, Jr. wrote:

> From: <rb...@covalent.net>
> Sent: Tuesday, June 12, 2001 10:41 PM
>
>
> > I was under the impression that we had already decided, the last time this
> > thread surfaced, that all of this was possible with filters.  We can
> > redirect to different kinds of network primitives with a different "core"
> > filter.  The "core" filters don't even need to use sockets, they can store
> > their own communication medium in the conn_rec, and just use that.  The
> > only drawback, is that Apache will still require a single socket to
> > operate, but I am not sure that can't be worked around.  A REALLY QUICK
> > grep through the source has us referencing the client socket 28 times
> > directly from the conn_rec.  I am not convinced that some of those can't
> > just be moved to inside a filter.
> >
> > I guess I am asking what this is supposed to accomplish.
>
> In all fairness,
>
> APR does bucket brigades.  It does socket management.  I think this would be a fine
> addition to our APR arsenal.
>
> But can we, absolutely, postively, table any change that affects an httpd 2.0
> release?  IOW, no samba-team iol into Apache 2.0.  Develop the API, impement the
> code, go to town.  But I think we've reached a juncture...
>
>     not everything in apr exists for or is even used by Apache
>
> If what results can improve httpd 2.1, then fantastic!  If not, it's still fantastic :-)
> There's alot more to do on the net beyond Apache, if we can fuel those directions, then
> we really have a worthwhile library project, and not just an adjunct of httpd.

The problem I have with this code idea isn't that it isn't useful to
httpd.  It is that we have been down this road once, and the model wasn't
flexible enough.  What problem are we trying to solve that the filter
mechanism doesn't solve?  If the answer to that question is "filters are
in Apache, and we want this out of Apache", then move filters out of
Apache.  If the answer is, "We need a better way to abstract the network
for x, y, and z", then cool let's do it.  I haven't heard x, y, and z yet,
and the last time we talked about this, filters could solve any problem
that this model was trying to solve.

Ryan

_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [RFC] Network Abstraction Layer - redux

Posted by "William A. Rowe, Jr." <ad...@rowe-clan.net>.
From: <rb...@covalent.net>
Sent: Tuesday, June 12, 2001 10:41 PM


> I was under the impression that we had already decided, the last time this
> thread surfaced, that all of this was possible with filters.  We can
> redirect to different kinds of network primitives with a different "core"
> filter.  The "core" filters don't even need to use sockets, they can store
> their own communication medium in the conn_rec, and just use that.  The
> only drawback, is that Apache will still require a single socket to
> operate, but I am not sure that can't be worked around.  A REALLY QUICK
> grep through the source has us referencing the client socket 28 times
> directly from the conn_rec.  I am not convinced that some of those can't
> just be moved to inside a filter.
> 
> I guess I am asking what this is supposed to accomplish.

In all fairness,

APR does bucket brigades.  It does socket management.  I think this would be a fine
addition to our APR arsenal.

But can we, absolutely, postively, table any change that affects an httpd 2.0
release?  IOW, no samba-team iol into Apache 2.0.  Develop the API, impement the
code, go to town.  But I think we've reached a juncture...

    not everything in apr exists for or is even used by Apache

If what results can improve httpd 2.1, then fantastic!  If not, it's still fantastic :-)
There's alot more to do on the net beyond Apache, if we can fuel those directions, then
we really have a worthwhile library project, and not just an adjunct of httpd.

> On Tue, 12 Jun 2001, Bill Stoddard wrote:
> 
> > Missed this thread earlier.  I am quite interested in this proposal.  It is similar to
> > Dean Gaudet's iol work in early Apache 2.0 and is pretty much in line with what I was
> > needing/thinking as well.  Any interest in reviving this?  The implementation should be
> > quite straightforward. I'll start working on pieces if there is general agreement this is
> > a good thing to do (I think it is).
> >
> > From: "Sander Striker" <st...@samba-tng.org>
> > Sent: Wednesday, February 28, 2001 6:47 AM
> >
> > > It looks all very promissing and that's why we want to contribute
> > > some ideas to (from our point of view) improve the APR. The first
> > > thing we are going to need is a higher level of abstraction for
> > > the network layer. We have a complicated (to explain to outsiders)
> > > protocol stack in which protocols can be called upon from several
> > > layers.



Re: [RFC] Network Abstraction Layer - redux

Posted by rb...@covalent.net.
I was under the impression that we had already decided, the last time this
thread surfaced, that all of this was possible with filters.  We can
redirect to different kinds of network primitives with a different "core"
filter.  The "core" filters don't even need to use sockets, they can store
their own communication medium in the conn_rec, and just use that.  The
only drawback, is that Apache will still require a single socket to
operate, but I am not sure that can't be worked around.  A REALLY QUICK
grep through the source has us referencing the client socket 28 times
directly from the conn_rec.  I am not convinced that some of those can't
just be moved to inside a filter.

I guess I am asking what this is supposed to accomplish.

Ryan

On Tue, 12 Jun 2001, Bill Stoddard wrote:

> Missed this thread earlier.  I am quite interested in this proposal.  It is similar to
> Dean Gaudet's iol work in early Apache 2.0 and is pretty much in line with what I was
> needing/thinking as well.  Any interest in reviving this?  The implementation should be
> quite straightforward. I'll start working on pieces if there is general agreement this is
> a good thing to do (I think it is).
>
> Bill Stoddard
>
> ----- Original Message -----
> From: "Sander Striker" <st...@samba-tng.org>
> To: <de...@apr.apache.org>
> Cc: <lk...@samba-tng.org>; <el...@samba-tng.org>
> Sent: Wednesday, February 28, 2001 6:47 AM
> Subject: [RFC] Network Abstraction Layer
>
>
> > Hi,
> >
> > Before I start throwing stuff at you, I'll introduce myself.
> > I'm Sander Striker, one of the Samba TNG team members. We have
> > been looking at the APR a bit to find out if we can use it in
> > our code.
> >
> > It looks all very promissing and that's why we want to contribute
> > some ideas to (from our point of view) improve the APR. The first
> > thing we are going to need is a higher level of abstraction for
> > the network layer. We have a complicated (to explain to outsiders)
> > protocol stack in which protocols can be called upon from several
> > layers.
> > Example:
> >
> >  +-------------------+
> >  |         D         |
> >  +---------+         |
> >  |    C    |         |
> >  |    +----+----+    |
> >  |    |    B    |    |
> >  +----+----+---------+
> >  |         A         |
> >  +-------------------+
> >
> > In short:
> >
> > A <> B
> > A <> B <> C
> > A <> B <> C <> D
> > A <> C
> > A <> C <> D
> > A <> D
> >
> > To make it even more complex B can run over other things than A...
> >
> > But, I'm boring you guys, so I'll proceed.
> >
> > Below is a simple draft of the NAL. The goal is to be able to
> > add transports easily, even when not present in the kernel.
> > Also this allows an easy way of protocol/transport stacking.
> > A 'transport' can also do buffering, authentication, filtering.
> >
> > Ignore name clashes with current APR code please.
> > Also, I haven't looked into the apr_pool package to understand
> > how it works quite yet. I want it to be _possible_ to tie transports
> > to memory management (so we can dump all memory that we used for:
> > a session, a request, a reply, etc).
> >
> > I'll post a memory management draft aswell in a few days. It will
> > be similar to this when it comes abstraction.
> >
> > Thanks,
> >
> > Sander
> >
> >
> > /* typedefs */
> >
> > typedef struct apr_socket_t apr_socket_t;
> > typedef struct apr_transport_t apr_transport_t;
> >
> > typedef int apr_transport_id_t;
> > /* maybe this should be a string?? So you can
> >  * do apr_socket_create("smb", &socket, some_pool) */
> >
> >
> > typedef apr_status_t (*apr_socket_create_fn_t)  (apr_socket_t **socket,
> >                                                  apr_pool_t *context);
> >
> > typedef apr_status_t (*apr_socket_bind_fn_t)    (apr_socket_t *socket,
> >                                                  apr_sockaddr_t *sa);
> >
> > typedef apr_status_t (*apr_socket_connect_fn_t) (apr_socket_t *socket,
> >                                                  apr_sockaddr_t *sa);
> >
> > typedef apr_status_t (*apr_socket_listen_fn_t)  (apr_socket_t *socket,
> >                                                  apr_int32_t backlog);
> >
> > typedef apr_status_t (*apr_socket_accept_fn_t)  (apr_socket_t
> > **client_socket,
> >                                                  apr_socket_t *socket,
> >                                                  apr_pool_t
> > *connection_pool);
> >
> > typedef apr_status_t (*apr_socket_close_fn_t)   (apr_socket_t *socket);
> >
> > typedef apr_status_t (*apr_socket_setopt_fn_t)  (apr_socket_t *socket,
> >                                                  apr_int32_t opt,
> >                                                  apr_int32_t on);
> >
> > typedef apr_status_t (*apr_socket_getopt_fn_t)  (apr_socket_t *socket,
> >                                                  apr_int32_t opt,
> >                                                  apr_int32_t *on);
> >
> > typedef apr_status_t (*apr_socket_send_fn_t)    (apr_socket_t *socket,
> >                                                  const char *buf,
> >                                                  apr_size_t *len);
> >
> > typedef apr_status_t (*apr_socket_recv_fn_t)    (apr_socket_t *socket,
> >                                                  char *buf,
> >                                                  apr_size_t *len);
> >
> > typedef apr_status_t (*apr_socket_shutdown_fn_t)(apr_socket_t *socket,
> >                                                  apr_shutdown_how_e how);
> >
> >
> >   /* more functions that I possibly left out */
> >
> >
> >
> > /* structures */
> >
> > struct apr_transport_t
> > {
> >   apr_transport_id_t        transport_id;
> >   apr_socket_create_fn_t    socket_create;
> >   apr_socket_bind_fn_t      socket_bind;
> >   apr_socket_connect_fn_t   socket_connect;
> >   apr_socket_listen_fn_t    socket_listen;
> >   apr_socket_accept_fn_t    socket_accept;
> >   apr_socket_close_fn_t     socket_close;
> >   apr_socket_setopt_fn_t    socket_setopt;
> >   apr_socket_getopt_fn_t    socket_getopt;
> >   apr_socket_send_fn_t      socket_send;
> >   apr_socket_recv_fn_t      socket_recv;
> >   apr_socket_shutdown_fn_t  socket_shutdown;
> >   /* again, more functions that I possibly left out */
> >
> > };
> >
> > struct apr_socket_t
> > {
> >   apr_transport_t *transport;
> >   /* transport specific socket implementation follows (should be
> >      defined by transport implementors) */
> >
> > };
> >
> > /* functions */
> >
> > apr_status_t    apr_transport_add(apr_transport_t *transport);
> > apr_status_t    apr_transport_remove(apr_transport_t *transport);
> > apr_transport_t apr_transport_find(apr_transport_id_t transport_id);
> >
> >
> > /* XXX: maybe do the create using apr_transport_id_t?? */
> > apr_status_t    apr_socket_create(apr_transport_t *transport,
> >                                   apr_socket_t **socket,
> >                                   apr_pool_t *context);
> >
> > apr_status_t    apr_socket_bind(apr_socket_t *socket,
> >                                 apr_sockaddr_t *sa);
> >
> > apr_status_t    apr_socket_connect(apr_socket_t *socket,
> >                                    apr_sockaddr_t *sa);
> >
> > apr_status_t    apr_socket_listen(apr_socket_t *socket,
> >                                   apr_int32_t backlog);
> >
> > apr_status_t    apr_socket_accept(apr_socket_t **client_socket,
> >                                   apr_socket_t *socket,
> >                                   apr_pool_t *connection_pool);
> >
> > apr_status_t    apr_socket_close(apr_socket_t *socket);
> >
> > apr_status_t    apr_socket_setopt(apr_socket_t *socket,
> >                                   apr_int32_t opt,
> >                                   apr_int32_t on);
> >
> > apr_status_t    apr_socket_getopt(apr_socket_t *socket,
> >                                   apr_int32_t opt,
> >                                   apr_int32_t *on);
> >
> > apr_status_t    apr_socket_send(apr_socket_t *socket,
> >                                 const char *buf,
> >                                 apr_size_t *len);
> >
> > apr_status_t    apr_socket_recv(apr_socket_t *socket,
> >                                 char *buf,
> >                                 apr_size_t *len);
> >
> > apr_status_t    apr_socket_shutdown(apr_socket_t *socket,
> >                                     apr_shutdown_how_e how);
> >
> >
> > /* implementation */
> >
> > /* XXX: maybe do the create using apr_transport_id_t?? */
> > apr_status_t apr_socket_create(apr_transport_t *transport,
> >                                apr_socket_t **socket,
> >                                apr_pool_t *context)
> > {
> >   assert(transport != NULL);
> >   assert(transport->apr_socket_create != NULL);
> >
> >   return transport->apr_socket_create(socket, context);
> > }
> >
> > apr_status_t apr_socket_bind(apr_socket_t *socket,
> >                                 apr_sockaddr_t *sa)
> > {
> >   assert(socket != NULL);
> >   assert(socket->transport != NULL);
> >   assert(socket->transport->socket_bind != NULL);
> >
> >   return socket->transport->socket_bind(socket, sa);
> > }
> >
> > /* rest of high level implementation is trivially the same */
> >
>
>


_______________________________________________________________________________
Ryan Bloom                        	rbb@apache.org
406 29th St.
San Francisco, CA 94131
-------------------------------------------------------------------------------


Re: [RFC] Network Abstraction Layer - redux

Posted by Bill Stoddard <bi...@wstoddard.com>.
Missed this thread earlier.  I am quite interested in this proposal.  It is similar to
Dean Gaudet's iol work in early Apache 2.0 and is pretty much in line with what I was
needing/thinking as well.  Any interest in reviving this?  The implementation should be
quite straightforward. I'll start working on pieces if there is general agreement this is
a good thing to do (I think it is).

Bill Stoddard

----- Original Message -----
From: "Sander Striker" <st...@samba-tng.org>
To: <de...@apr.apache.org>
Cc: <lk...@samba-tng.org>; <el...@samba-tng.org>
Sent: Wednesday, February 28, 2001 6:47 AM
Subject: [RFC] Network Abstraction Layer


> Hi,
>
> Before I start throwing stuff at you, I'll introduce myself.
> I'm Sander Striker, one of the Samba TNG team members. We have
> been looking at the APR a bit to find out if we can use it in
> our code.
>
> It looks all very promissing and that's why we want to contribute
> some ideas to (from our point of view) improve the APR. The first
> thing we are going to need is a higher level of abstraction for
> the network layer. We have a complicated (to explain to outsiders)
> protocol stack in which protocols can be called upon from several
> layers.
> Example:
>
>  +-------------------+
>  |         D         |
>  +---------+         |
>  |    C    |         |
>  |    +----+----+    |
>  |    |    B    |    |
>  +----+----+---------+
>  |         A         |
>  +-------------------+
>
> In short:
>
> A <> B
> A <> B <> C
> A <> B <> C <> D
> A <> C
> A <> C <> D
> A <> D
>
> To make it even more complex B can run over other things than A...
>
> But, I'm boring you guys, so I'll proceed.
>
> Below is a simple draft of the NAL. The goal is to be able to
> add transports easily, even when not present in the kernel.
> Also this allows an easy way of protocol/transport stacking.
> A 'transport' can also do buffering, authentication, filtering.
>
> Ignore name clashes with current APR code please.
> Also, I haven't looked into the apr_pool package to understand
> how it works quite yet. I want it to be _possible_ to tie transports
> to memory management (so we can dump all memory that we used for:
> a session, a request, a reply, etc).
>
> I'll post a memory management draft aswell in a few days. It will
> be similar to this when it comes abstraction.
>
> Thanks,
>
> Sander
>
>
> /* typedefs */
>
> typedef struct apr_socket_t apr_socket_t;
> typedef struct apr_transport_t apr_transport_t;
>
> typedef int apr_transport_id_t;
> /* maybe this should be a string?? So you can
>  * do apr_socket_create("smb", &socket, some_pool) */
>
>
> typedef apr_status_t (*apr_socket_create_fn_t)  (apr_socket_t **socket,
>                                                  apr_pool_t *context);
>
> typedef apr_status_t (*apr_socket_bind_fn_t)    (apr_socket_t *socket,
>                                                  apr_sockaddr_t *sa);
>
> typedef apr_status_t (*apr_socket_connect_fn_t) (apr_socket_t *socket,
>                                                  apr_sockaddr_t *sa);
>
> typedef apr_status_t (*apr_socket_listen_fn_t)  (apr_socket_t *socket,
>                                                  apr_int32_t backlog);
>
> typedef apr_status_t (*apr_socket_accept_fn_t)  (apr_socket_t
> **client_socket,
>                                                  apr_socket_t *socket,
>                                                  apr_pool_t
> *connection_pool);
>
> typedef apr_status_t (*apr_socket_close_fn_t)   (apr_socket_t *socket);
>
> typedef apr_status_t (*apr_socket_setopt_fn_t)  (apr_socket_t *socket,
>                                                  apr_int32_t opt,
>                                                  apr_int32_t on);
>
> typedef apr_status_t (*apr_socket_getopt_fn_t)  (apr_socket_t *socket,
>                                                  apr_int32_t opt,
>                                                  apr_int32_t *on);
>
> typedef apr_status_t (*apr_socket_send_fn_t)    (apr_socket_t *socket,
>                                                  const char *buf,
>                                                  apr_size_t *len);
>
> typedef apr_status_t (*apr_socket_recv_fn_t)    (apr_socket_t *socket,
>                                                  char *buf,
>                                                  apr_size_t *len);
>
> typedef apr_status_t (*apr_socket_shutdown_fn_t)(apr_socket_t *socket,
>                                                  apr_shutdown_how_e how);
>
>
>   /* more functions that I possibly left out */
>
>
>
> /* structures */
>
> struct apr_transport_t
> {
>   apr_transport_id_t        transport_id;
>   apr_socket_create_fn_t    socket_create;
>   apr_socket_bind_fn_t      socket_bind;
>   apr_socket_connect_fn_t   socket_connect;
>   apr_socket_listen_fn_t    socket_listen;
>   apr_socket_accept_fn_t    socket_accept;
>   apr_socket_close_fn_t     socket_close;
>   apr_socket_setopt_fn_t    socket_setopt;
>   apr_socket_getopt_fn_t    socket_getopt;
>   apr_socket_send_fn_t      socket_send;
>   apr_socket_recv_fn_t      socket_recv;
>   apr_socket_shutdown_fn_t  socket_shutdown;
>   /* again, more functions that I possibly left out */
>
> };
>
> struct apr_socket_t
> {
>   apr_transport_t *transport;
>   /* transport specific socket implementation follows (should be
>      defined by transport implementors) */
>
> };
>
> /* functions */
>
> apr_status_t    apr_transport_add(apr_transport_t *transport);
> apr_status_t    apr_transport_remove(apr_transport_t *transport);
> apr_transport_t apr_transport_find(apr_transport_id_t transport_id);
>
>
> /* XXX: maybe do the create using apr_transport_id_t?? */
> apr_status_t    apr_socket_create(apr_transport_t *transport,
>                                   apr_socket_t **socket,
>                                   apr_pool_t *context);
>
> apr_status_t    apr_socket_bind(apr_socket_t *socket,
>                                 apr_sockaddr_t *sa);
>
> apr_status_t    apr_socket_connect(apr_socket_t *socket,
>                                    apr_sockaddr_t *sa);
>
> apr_status_t    apr_socket_listen(apr_socket_t *socket,
>                                   apr_int32_t backlog);
>
> apr_status_t    apr_socket_accept(apr_socket_t **client_socket,
>                                   apr_socket_t *socket,
>                                   apr_pool_t *connection_pool);
>
> apr_status_t    apr_socket_close(apr_socket_t *socket);
>
> apr_status_t    apr_socket_setopt(apr_socket_t *socket,
>                                   apr_int32_t opt,
>                                   apr_int32_t on);
>
> apr_status_t    apr_socket_getopt(apr_socket_t *socket,
>                                   apr_int32_t opt,
>                                   apr_int32_t *on);
>
> apr_status_t    apr_socket_send(apr_socket_t *socket,
>                                 const char *buf,
>                                 apr_size_t *len);
>
> apr_status_t    apr_socket_recv(apr_socket_t *socket,
>                                 char *buf,
>                                 apr_size_t *len);
>
> apr_status_t    apr_socket_shutdown(apr_socket_t *socket,
>                                     apr_shutdown_how_e how);
>
>
> /* implementation */
>
> /* XXX: maybe do the create using apr_transport_id_t?? */
> apr_status_t apr_socket_create(apr_transport_t *transport,
>                                apr_socket_t **socket,
>                                apr_pool_t *context)
> {
>   assert(transport != NULL);
>   assert(transport->apr_socket_create != NULL);
>
>   return transport->apr_socket_create(socket, context);
> }
>
> apr_status_t apr_socket_bind(apr_socket_t *socket,
>                                 apr_sockaddr_t *sa)
> {
>   assert(socket != NULL);
>   assert(socket->transport != NULL);
>   assert(socket->transport->socket_bind != NULL);
>
>   return socket->transport->socket_bind(socket, sa);
> }
>
> /* rest of high level implementation is trivially the same */
>