Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <venti.h>
4
#include <thread.h>
5
#include "queue.h"
6
 
7
enum
8
{
9
	STACK = 8192
10
};
11
 
12
typedef struct VtSconn VtSconn;
13
struct VtSconn
14
{
15
	int ctl;
16
	int ref;
17
	QLock lk;
18
	char dir[NETPATHLEN];
19
	VtSrv *srv;
20
	VtConn *c;
21
};
22
 
23
struct VtSrv
24
{
25
	int afd;
26
	int dead;
27
	char adir[NETPATHLEN];
28
	Queue *q;	/* Queue(VtReq*) */
29
};
30
 
31
static void listenproc(void*);
32
static void connproc(void*);
33
 
34
static void
35
scincref(VtSconn *sc)
36
{
37
	qlock(&sc->lk);
38
	sc->ref++;
39
	qunlock(&sc->lk);
40
}
41
 
42
static void
43
scdecref(VtSconn *sc)
44
{
45
	qlock(&sc->lk);
46
	if(--sc->ref > 0){
47
		qunlock(&sc->lk);
48
		return;
49
	}
50
	if(sc->c)
51
		vtfreeconn(sc->c);
52
	vtfree(sc);
53
}
54
 
55
VtSrv*
56
vtlisten(char *addr)
57
{
58
	VtSrv *s;
59
 
60
	s = vtmallocz(sizeof(VtSrv));
61
	s->afd = announce(addr, s->adir);
62
	if(s->afd < 0){
63
		free(s);
64
		return nil;
65
	}
66
	s->q = _vtqalloc();
67
	proccreate(listenproc, s, STACK);
68
	return s;
69
}
70
 
71
static void
72
listenproc(void *v)
73
{
74
	int ctl;
75
	char dir[NETPATHLEN];
76
	VtSrv *srv;
77
	VtSconn *sc;
78
 
79
	srv = v;
80
	for(;;){
81
		ctl = listen(srv->adir, dir);
82
		if(ctl < 0){
83
			srv->dead = 1;
84
			break;
85
		}
86
		sc = vtmallocz(sizeof(VtSconn));
87
		sc->ref = 1;
88
		sc->ctl = ctl;
89
		sc->srv = srv;
90
		strcpy(sc->dir, dir);
91
		proccreate(connproc, sc, STACK);
92
	}
93
 
94
	/* hangup */
95
}
96
 
97
static void
98
connproc(void *v)
99
{
100
	VtSconn *sc;
101
	VtConn *c;
102
	Packet *p;
103
	VtReq *r;
104
	int fd;
105
static int first=1;
106
 
107
if(first && chattyventi){
108
	first=0;
109
	fmtinstall('F', vtfcallfmt);
110
}
111
	r = nil;
112
	sc = v;
113
	sc->c = nil;
114
	if(0) fprint(2, "new call %s on %d\n", sc->dir, sc->ctl);
115
	fd = accept(sc->ctl, sc->dir);
116
	close(sc->ctl);
117
	if(fd < 0){
118
		fprint(2, "accept %s: %r\n", sc->dir);
119
		goto out;
120
	}
121
 
122
	c = vtconn(fd, fd);
123
	sc->c = c;
124
	if(vtversion(c) < 0){
125
		fprint(2, "vtversion %s: %r\n", sc->dir);
126
		goto out;
127
	}
128
	if(vtsrvhello(c) < 0){
129
		fprint(2, "vtsrvhello %s: %r\n", sc->dir);
130
		goto out;
131
	}
132
 
133
	if(0) fprint(2, "new proc %s\n", sc->dir);
134
	proccreate(vtsendproc, c, STACK);
135
	qlock(&c->lk);
136
	while(!c->writeq)
137
		rsleep(&c->rpcfork);
138
	qunlock(&c->lk);
139
 
140
	while((p = vtrecv(c)) != nil){
141
		r = vtmallocz(sizeof(VtReq));
142
		if(vtfcallunpack(&r->tx, p) < 0){
143
			vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv bad packet %p: %r<br>\n", c->addr, p);
144
			fprint(2, "bad packet on %s: %r\n", sc->dir);
145
			packetfree(p);
146
			continue;
147
		}
148
		vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv packet %p (%F)<br>\n", c->addr, p, &r->tx);
149
		if(chattyventi)
150
			fprint(2, "%s <- %F\n", argv0, &r->tx);
151
		packetfree(p);
152
		if(r->tx.msgtype == VtTgoodbye)
153
			break;
154
		r->rx.tag = r->tx.tag;
155
		r->sc = sc;
156
		scincref(sc);
157
		if(_vtqsend(sc->srv->q, r) < 0){
158
			scdecref(sc);
159
			fprint(2, "hungup queue\n");
160
			break;
161
		}
162
		r = nil;
163
	}
164
 
165
	if(0) fprint(2, "eof on %s\n", sc->dir);
166
 
167
out:
168
	if(r){
169
		vtfcallclear(&r->tx);
170
		vtfree(r);
171
	}
172
	if(0) fprint(2, "freed %s\n", sc->dir);
173
	scdecref(sc);
174
	return;
175
}
176
 
177
VtReq*
178
vtgetreq(VtSrv *srv)
179
{
180
	VtReq *r;
181
 
182
	r = _vtqrecv(srv->q);
183
	if (r != nil)
184
		vtlog(VtServerLog, "<font size=-1>%T %s:</font> vtgetreq %F<br>\n",
185
			((VtSconn*)r->sc)->c->addr, &r->tx);
186
	return r;
187
}
188
 
189
void
190
vtrespond(VtReq *r)
191
{
192
	Packet *p;
193
	VtSconn *sc;
194
 
195
	sc = r->sc;
196
	if(r->rx.tag != r->tx.tag)
197
		abort();
198
	if(r->rx.msgtype != r->tx.msgtype+1 && r->rx.msgtype != VtRerror)
199
		abort();
200
	if(chattyventi)
201
		fprint(2, "%s -> %F\n", argv0, &r->rx);
202
	if((p = vtfcallpack(&r->rx)) == nil){
203
		vtlog(VtServerLog, "%s: vtfcallpack %F: %r<br>\n", sc->c->addr, &r->rx);
204
		fprint(2, "fcallpack on %s: %r\n", sc->dir);
205
		packetfree(p);
206
		vtfcallclear(&r->rx);
207
		return;
208
	}
209
	vtlog(VtServerLog, "<font size=-1>%T %s:</font> send packet %p (%F)<br>\n", sc->c->addr, p, &r->rx);
210
	if(vtsend(sc->c, p) < 0)
211
		fprint(2, "vtsend %F: %r\n", &r->rx);
212
	scdecref(sc);
213
	vtfcallclear(&r->tx);
214
	vtfcallclear(&r->rx);
215
	vtfree(r);
216
}
217