xref: /plan9/sys/src/libsunrpc/fd.c (revision fb7f0c934c48abaed6040d054ef636408c3c522d)
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <sunrpc.h>
5 
6 enum
7 {
8 	MaxRead = 17000,
9 };
10 
11 typedef struct SunMsgFd SunMsgFd;
12 struct SunMsgFd
13 {
14 	SunMsg msg;
15 	int fd;
16 };
17 
18 typedef struct Arg Arg;
19 struct Arg
20 {
21 	SunSrv *srv;
22 	Channel *creply;
23 	Channel *csync;
24 	int fd;
25 };
26 
27 static void
sunFdRead(void * v)28 sunFdRead(void *v)
29 {
30 	uint n, tot;
31 	int done;
32 	uchar buf[4], *p;
33 	Arg arg = *(Arg*)v;
34 	SunMsgFd *msg;
35 
36 	sendp(arg.csync, 0);
37 
38 	p = nil;
39 	tot = 0;
40 	for(;;){
41 		n = readn(arg.fd, buf, 4);
42 		if(n != 4)
43 			break;
44 		n = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3];
45 if(arg.srv->chatty) fprint(2, "%.8ux...", n);
46 		done = n&0x80000000;
47 		n &= ~0x80000000;
48 		p = erealloc(p, tot+n);
49 		if(readn(arg.fd, p+tot, n) != n)
50 			break;
51 		tot += n;
52 		if(done){
53 			msg = emalloc(sizeof(SunMsgFd));
54 			msg->msg.data = p;
55 			msg->msg.count = tot;
56 			msg->msg.creply = arg.creply;
57 			sendp(arg.srv->crequest, msg);
58 			p = nil;
59 			tot = 0;
60 		}
61 	}
62 }
63 
64 static void
sunFdWrite(void * v)65 sunFdWrite(void *v)
66 {
67 	uchar buf[4];
68 	u32int n;
69 	Arg arg = *(Arg*)v;
70 	SunMsgFd *msg;
71 
72 	sendp(arg.csync, 0);
73 
74 	while((msg = recvp(arg.creply)) != nil){
75 		n = msg->msg.count;
76 		buf[0] = (n>>24)|0x80;
77 		buf[1] = n>>16;
78 		buf[2] = n>>8;
79 		buf[3] = n;
80 		if(write(arg.fd, buf, 4) != 4
81 		|| write(arg.fd, msg->msg.data, msg->msg.count) != msg->msg.count)
82 			fprint(2, "sunFdWrite: %r\n");
83 		free(msg->msg.data);
84 		free(msg);
85 	}
86 }
87 
88 int
sunSrvFd(SunSrv * srv,int fd)89 sunSrvFd(SunSrv *srv, int fd)
90 {
91 	Arg *arg;
92 
93 	arg = emalloc(sizeof(Arg));
94 	arg->fd = fd;
95 	arg->srv = srv;
96 	arg->csync = chancreate(sizeof(void*), 0);
97 	arg->creply = chancreate(sizeof(SunMsg*), 10);
98 
99 	proccreate(sunFdRead, arg, SunStackSize);
100 	proccreate(sunFdWrite, arg, SunStackSize);
101 	recvp(arg->csync);
102 	recvp(arg->csync);
103 
104 	chanfree(arg->csync);
105 	free(arg);
106 	return 0;
107 }
108