httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <>
Subject Re: filter API spec
Date Thu, 04 Sep 1997 03:57:55 GMT
On Wed, 27 Aug 1997, Alexei Kosut wrote:

> >From a user's point of view stacking/unstacking onto a BUFF:
> typedef struct {
>     void *cookie;
>     int (*read)(BUFF *, void *, char *, int);	/* Read data */
>     int (*write)(BUFF *, void *, char *, int);	/* Write data */
>     void (*flush)(BUFF *, void *);	/* Flush and pass on */
>     void (*close)(BUFF *, void *);	/* Finish up, pass on bclose() */
>     void (*unattach)(BUFF *, void *);	/* Finish up, don't pass on */
> } bfilter;
> Public functions in buff.c:
> int bpush(BUFF **, bfilter);

You should remove the cookie from bfilter, and pass it to bpush
separately.  That way bfilters can be constant globals exported by a
filtering module.  In your above API you would have to make a copy of a
constant global and tweak the cookie. 

> BUFF {
>     BUFF *down;	/* next BUFF down in the stack, NULL if we're at the bottom */
>     BUFF *up;	/* the next one up, NULL if we're at the top */
>     bfilters bf;	/* The filters for this BUFF */
>     int fd;	/* The file descriptor, -1 for all but the bottom BUFF */
>     int fd_in;	/* ditto */
> }

Well, in reality you don't need the fd and fd_in at all ... since the
bottom-most layer can be a filter which is a wrapper for the unix
function calls, and its cookie would include the fds.  All you need
in the BUFF structure is:

struct buff_struct
    int flags;             /* flags */
    unsigned char *inptr;  /* pointer to next location to read */
    int incnt;             /* number of bytes left to read from input buffer;
                            * always 0 if had a read error  */
    int outcnt;            /* number of byte put in output buffer */
    unsigned char *inbase;
    unsigned char *outbase;
    int bufsiz;
    void (*error)(BUFF *fb, int op, void *data);
    void *error_data;
    long int bytes_sent;   /* number of bytes actually written */

    pool *pool;

    BUFF *up;
    BUFF *down;
    void *cookie;
    bfilter filter;

Otherwise it becomes confusing to have a BUFF which is writing into
a palloc()d string ... since there are never any fds involved.  So it makes
sense to abstract out even the lowest layer.

> The internal write()-like function (buff_write()) would look something
> like this:
> int buff_write(BUFF *b, char *c, int l) {
>     /* Are we a stacked filter? */
>     if (b->down) {
> 	if (b->bf.write)
> 	    return bf.write(b->down, bf.cookie, c, l);
> 	else
> 	    return buff_write(b->down, c, l);
>     }
>     /* We're the bottom of the stack:
>      * do what the current buff_write() does right now
>      */
> }

With my above modification it'll always call b->filter.write.

> The internal bclose, bflush, etc... would be similar. The internal bread()
> would have to be backwards (finding the bottom BUFF, and looking at
> previous elements - this is why an up element in BUFF is necessary),
> since reading happens bottom-up, wheras everything else is top-down.

Uhhh ... no this doesn't seem right at all.  A read still occurs on
the top, which might be satisfied from the buffer, if not then it goes
one layer down.  That might be in the buffer, if not it goes one layer
down.  In effect the first read will nest all the way down, and then
come back up filling buffers along the way.  But you only need a down
pointer since this is all recursion.

> bflush {

I'm not sure but we might need two flushing semantics -- one that goes
all the way down and one which goes only one level down.  I haven't
found a good reason for it yet.

> void my_close (BUFF *b, void *) {
>     bclose(b);
> }

I see no reason for a close method in the filter.  bclose is simply
a series of flush, unattach, bpops.

> The problem is the read buffer. If a filter is popped, and there is
> still data in that filter's input buffer, what do you do with it?

This is an application error I say.  Don't do anything complicated at
all here until you actually find this to be a problem in practice.

Overall this looks like a good start.


View raw message