| #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; | 
 | } |