aboutsummaryrefslogtreecommitdiff
path: root/src/libsunrpc/fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsunrpc/fd.c')
-rw-r--r--src/libsunrpc/fd.c107
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;
+}