aboutsummaryrefslogtreecommitdiff
path: root/src/libsunrpc/fd.c
blob: a808ad553b7fba5ccaccb552d67a0718df70854a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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;
}