diff options
Diffstat (limited to 'src/libsunrpc/fd.c')
-rw-r--r-- | src/libsunrpc/fd.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/src/libsunrpc/fd.c b/src/libsunrpc/fd.c new file mode 100644 index 00000000..23cfb401 --- /dev/null +++ b/src/libsunrpc/fd.c @@ -0,0 +1,107 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <sunrpc.h> + +enum +{ + MaxRead = 17000, +}; + +typedef struct SunMsgFd SunMsgFd; +struct SunMsgFd +{ + SunMsg msg; + int fd; +}; + +typedef struct Arg Arg; +struct Arg +{ + SunSrv *srv; + Channel *creply; + Channel *csync; + int fd; +}; + +static void +sunfdread(void *v) +{ + uint n, tot; + int done; + uchar buf[4], *p; + Arg arg = *(Arg*)v; + SunMsgFd *msg; + + sendp(arg.csync, 0); + + p = nil; + tot = 0; + for(;;){ + n = readn(arg.fd, buf, 4); + if(n != 4) + break; + n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; +if(arg.srv->chatty) fprint(2, "%.8ux...", n); + done = n&0x80000000; + n &= ~0x80000000; + p = erealloc(p, tot+n); + if(readn(arg.fd, p+tot, n) != n) + break; + tot += n; + if(done){ + msg = emalloc(sizeof(SunMsgFd)); + msg->msg.data = p; + msg->msg.count = tot; + msg->msg.creply = arg.creply; + sendp(arg.srv->crequest, msg); + p = nil; + tot = 0; + } + } +} + +static void +sunfdwrite(void *v) +{ + uchar buf[4]; + u32int n; + Arg arg = *(Arg*)v; + SunMsgFd *msg; + + sendp(arg.csync, 0); + + while((msg = recvp(arg.creply)) != nil){ + n = msg->msg.count; + buf[0] = (n>>24)|0x80; + buf[1] = n>>16; + buf[2] = n>>8; + buf[3] = n; + if(write(arg.fd, buf, 4) != 4 + || write(arg.fd, msg->msg.data, msg->msg.count) != msg->msg.count) + fprint(2, "sunfdwrite: %r\n"); + free(msg->msg.data); + free(msg); + } +} + +int +sunsrvfd(SunSrv *srv, int fd) +{ + Arg *arg; + + arg = emalloc(sizeof(Arg)); + arg->fd = fd; + arg->srv = srv; + arg->csync = chancreate(sizeof(void*), 0); + arg->creply = chancreate(sizeof(SunMsg*), 10); + + proccreate(sunfdread, arg, SunStackSize); + proccreate(sunfdwrite, arg, SunStackSize); + recvp(arg->csync); + recvp(arg->csync); + + chanfree(arg->csync); + free(arg); + return 0; +} |