xref: /plan9/sys/src/liboventi/server.c (revision 225077b0bf393489f69f6689df234a9b945497b7)
1368c31abSDavid du Colombier #include <u.h>
2368c31abSDavid du Colombier #include <libc.h>
3368c31abSDavid du Colombier #include <oventi.h>
4368c31abSDavid du Colombier #include "session.h"
5368c31abSDavid du Colombier 
6368c31abSDavid du Colombier static char EAuthState[] = "bad authentication state";
7368c31abSDavid du Colombier static char ENotServer[] = "not a server session";
8368c31abSDavid du Colombier static char EVersion[] = "incorrect version number";
9368c31abSDavid du Colombier static char EProtocolBotch[] = "venti protocol botch";
10368c31abSDavid du Colombier 
11368c31abSDavid du Colombier VtSession *
vtServerAlloc(VtServerVtbl * vtbl)12368c31abSDavid du Colombier vtServerAlloc(VtServerVtbl *vtbl)
13368c31abSDavid du Colombier {
14368c31abSDavid du Colombier 	VtSession *z = vtAlloc();
15368c31abSDavid du Colombier 	z->vtbl = vtMemAlloc(sizeof(VtServerVtbl));
16*225077b0SDavid du Colombier 	setmalloctag(z->vtbl, getcallerpc(&vtbl));
17368c31abSDavid du Colombier 	*z->vtbl = *vtbl;
18368c31abSDavid du Colombier 	return z;
19368c31abSDavid du Colombier }
20368c31abSDavid du Colombier 
21368c31abSDavid du Colombier static int
srvHello(VtSession * z,char * version,char * uid,int,uchar *,int,uchar *,int)22368c31abSDavid du Colombier srvHello(VtSession *z, char *version, char *uid, int , uchar *, int , uchar *, int )
23368c31abSDavid du Colombier {
24368c31abSDavid du Colombier 	vtLock(z->lk);
25368c31abSDavid du Colombier 	if(z->auth.state != VtAuthHello) {
26368c31abSDavid du Colombier 		vtSetError(EAuthState);
27368c31abSDavid du Colombier 		goto Err;
28368c31abSDavid du Colombier 	}
29368c31abSDavid du Colombier 	if(strcmp(version, vtGetVersion(z)) != 0) {
30368c31abSDavid du Colombier 		vtSetError(EVersion);
31368c31abSDavid du Colombier 		goto Err;
32368c31abSDavid du Colombier 	}
33368c31abSDavid du Colombier 	vtMemFree(z->uid);
34368c31abSDavid du Colombier 	z->uid = vtStrDup(uid);
35368c31abSDavid du Colombier 	z->auth.state = VtAuthOK;
36368c31abSDavid du Colombier 	vtUnlock(z->lk);
37368c31abSDavid du Colombier 	return 1;
38368c31abSDavid du Colombier Err:
39368c31abSDavid du Colombier 	z->auth.state = VtAuthFailed;
40368c31abSDavid du Colombier 	vtUnlock(z->lk);
41368c31abSDavid du Colombier 	return 0;
42368c31abSDavid du Colombier }
43368c31abSDavid du Colombier 
44368c31abSDavid du Colombier 
45368c31abSDavid du Colombier static int
dispatchHello(VtSession * z,Packet ** pkt)46368c31abSDavid du Colombier dispatchHello(VtSession *z, Packet **pkt)
47368c31abSDavid du Colombier {
48368c31abSDavid du Colombier 	char *version, *uid;
49368c31abSDavid du Colombier 	uchar *crypto, *codec;
50368c31abSDavid du Colombier 	uchar buf[10];
51368c31abSDavid du Colombier 	int ncrypto, ncodec, cryptoStrength;
52368c31abSDavid du Colombier 	int ret;
53368c31abSDavid du Colombier 	Packet *p;
54368c31abSDavid du Colombier 
55368c31abSDavid du Colombier 	p = *pkt;
56368c31abSDavid du Colombier 
57368c31abSDavid du Colombier 	version = nil;
58368c31abSDavid du Colombier 	uid = nil;
59368c31abSDavid du Colombier 	crypto = nil;
60368c31abSDavid du Colombier 	codec = nil;
61368c31abSDavid du Colombier 
62368c31abSDavid du Colombier 	ret = 0;
63368c31abSDavid du Colombier 	if(!vtGetString(p, &version))
64368c31abSDavid du Colombier 		goto Err;
65368c31abSDavid du Colombier 	if(!vtGetString(p, &uid))
66368c31abSDavid du Colombier 		goto Err;
67368c31abSDavid du Colombier 	if(!packetConsume(p, buf, 2))
68368c31abSDavid du Colombier 		goto Err;
69368c31abSDavid du Colombier 	cryptoStrength = buf[0];
70368c31abSDavid du Colombier 	ncrypto = buf[1];
71368c31abSDavid du Colombier 	crypto = vtMemAlloc(ncrypto);
72368c31abSDavid du Colombier 	if(!packetConsume(p, crypto, ncrypto))
73368c31abSDavid du Colombier 		goto Err;
74368c31abSDavid du Colombier 
75368c31abSDavid du Colombier 	if(!packetConsume(p, buf, 1))
76368c31abSDavid du Colombier 		goto Err;
77368c31abSDavid du Colombier 	ncodec = buf[0];
78368c31abSDavid du Colombier 	codec = vtMemAlloc(ncodec);
79368c31abSDavid du Colombier 	if(!packetConsume(p, codec, ncodec))
80368c31abSDavid du Colombier 		goto Err;
81368c31abSDavid du Colombier 
82368c31abSDavid du Colombier 	if(packetSize(p) != 0) {
83368c31abSDavid du Colombier 		vtSetError(EProtocolBotch);
84368c31abSDavid du Colombier 		goto Err;
85368c31abSDavid du Colombier 	}
86368c31abSDavid du Colombier 	if(!srvHello(z, version, uid, cryptoStrength, crypto, ncrypto, codec, ncodec)) {
87368c31abSDavid du Colombier 		packetFree(p);
88368c31abSDavid du Colombier 		*pkt = nil;
89368c31abSDavid du Colombier 	} else {
90368c31abSDavid du Colombier 		if(!vtAddString(p, vtGetSid(z)))
91368c31abSDavid du Colombier 			goto Err;
92368c31abSDavid du Colombier 		buf[0] = vtGetCrypto(z);
93368c31abSDavid du Colombier 		buf[1] = vtGetCodec(z);
94368c31abSDavid du Colombier 		packetAppend(p, buf, 2);
95368c31abSDavid du Colombier 	}
96368c31abSDavid du Colombier 	ret = 1;
97368c31abSDavid du Colombier Err:
98368c31abSDavid du Colombier 	vtMemFree(version);
99368c31abSDavid du Colombier 	vtMemFree(uid);
100368c31abSDavid du Colombier 	vtMemFree(crypto);
101368c31abSDavid du Colombier 	vtMemFree(codec);
102368c31abSDavid du Colombier 	return ret;
103368c31abSDavid du Colombier }
104368c31abSDavid du Colombier 
105368c31abSDavid du Colombier static int
dispatchRead(VtSession * z,Packet ** pkt)106368c31abSDavid du Colombier dispatchRead(VtSession *z, Packet **pkt)
107368c31abSDavid du Colombier {
108368c31abSDavid du Colombier 	Packet *p;
109368c31abSDavid du Colombier 	int type, n;
110368c31abSDavid du Colombier 	uchar score[VtScoreSize], buf[4];
111368c31abSDavid du Colombier 
112368c31abSDavid du Colombier 	p = *pkt;
113368c31abSDavid du Colombier 	if(!packetConsume(p, score, VtScoreSize))
114368c31abSDavid du Colombier 		return 0;
115368c31abSDavid du Colombier 	if(!packetConsume(p, buf, 4))
116368c31abSDavid du Colombier 		return 0;
117368c31abSDavid du Colombier 	type = buf[0];
118368c31abSDavid du Colombier 	n = (buf[2]<<8) | buf[3];
119368c31abSDavid du Colombier 	if(packetSize(p) != 0) {
120368c31abSDavid du Colombier 		vtSetError(EProtocolBotch);
121368c31abSDavid du Colombier 		return 0;
122368c31abSDavid du Colombier 	}
123368c31abSDavid du Colombier 	packetFree(p);
124368c31abSDavid du Colombier 	*pkt = (*z->vtbl->read)(z, score, type, n);
125368c31abSDavid du Colombier 	return 1;
126368c31abSDavid du Colombier }
127368c31abSDavid du Colombier 
128368c31abSDavid du Colombier static int
dispatchWrite(VtSession * z,Packet ** pkt)129368c31abSDavid du Colombier dispatchWrite(VtSession *z, Packet **pkt)
130368c31abSDavid du Colombier {
131368c31abSDavid du Colombier 	Packet *p;
132368c31abSDavid du Colombier 	int type;
133368c31abSDavid du Colombier 	uchar score[VtScoreSize], buf[4];
134368c31abSDavid du Colombier 
135368c31abSDavid du Colombier 	p = *pkt;
136368c31abSDavid du Colombier 	if(!packetConsume(p, buf, 4))
137368c31abSDavid du Colombier 		return 0;
138368c31abSDavid du Colombier 	type = buf[0];
139368c31abSDavid du Colombier 	if(!(z->vtbl->write)(z, score, type, p)) {
140368c31abSDavid du Colombier 		*pkt = 0;
141368c31abSDavid du Colombier 	} else {
142368c31abSDavid du Colombier 		*pkt = packetAlloc();
143368c31abSDavid du Colombier 		packetAppend(*pkt, score, VtScoreSize);
144368c31abSDavid du Colombier 	}
145368c31abSDavid du Colombier 	return 1;
146368c31abSDavid du Colombier }
147368c31abSDavid du Colombier 
148368c31abSDavid du Colombier static int
dispatchSync(VtSession * z,Packet ** pkt)149368c31abSDavid du Colombier dispatchSync(VtSession *z, Packet **pkt)
150368c31abSDavid du Colombier {
151368c31abSDavid du Colombier 	(z->vtbl->sync)(z);
152368c31abSDavid du Colombier 	if(packetSize(*pkt) != 0) {
153368c31abSDavid du Colombier 		vtSetError(EProtocolBotch);
154368c31abSDavid du Colombier 		return 0;
155368c31abSDavid du Colombier 	}
156368c31abSDavid du Colombier 	return 1;
157368c31abSDavid du Colombier }
158368c31abSDavid du Colombier 
159368c31abSDavid du Colombier int
vtExport(VtSession * z)160368c31abSDavid du Colombier vtExport(VtSession *z)
161368c31abSDavid du Colombier {
162368c31abSDavid du Colombier 	Packet *p;
163368c31abSDavid du Colombier 	uchar buf[10], *hdr;
164368c31abSDavid du Colombier 	int op, tid, clean;
165368c31abSDavid du Colombier 
166368c31abSDavid du Colombier 	if(z->vtbl == nil) {
167368c31abSDavid du Colombier 		vtSetError(ENotServer);
168368c31abSDavid du Colombier 		return 0;
169368c31abSDavid du Colombier 	}
170368c31abSDavid du Colombier 
171368c31abSDavid du Colombier 	/* fork off slave */
172368c31abSDavid du Colombier 	switch(rfork(RFNOWAIT|RFMEM|RFPROC)){
173368c31abSDavid du Colombier 	case -1:
174368c31abSDavid du Colombier 		vtOSError();
175368c31abSDavid du Colombier 		return 0;
176368c31abSDavid du Colombier 	case 0:
177368c31abSDavid du Colombier 		break;
178368c31abSDavid du Colombier 	default:
179368c31abSDavid du Colombier 		return 1;
180368c31abSDavid du Colombier 	}
181368c31abSDavid du Colombier 
182368c31abSDavid du Colombier 
183368c31abSDavid du Colombier 	p = nil;
184368c31abSDavid du Colombier 	clean = 0;
185368c31abSDavid du Colombier 	vtAttach();
186368c31abSDavid du Colombier 	if(!vtConnect(z, nil))
187368c31abSDavid du Colombier 		goto Exit;
188368c31abSDavid du Colombier 
189368c31abSDavid du Colombier 	vtDebug(z, "server connected!\n");
190368c31abSDavid du Colombier if(0)	vtSetDebug(z, 1);
191368c31abSDavid du Colombier 
192368c31abSDavid du Colombier 	for(;;) {
193368c31abSDavid du Colombier 		p = vtRecvPacket(z);
194368c31abSDavid du Colombier 		if(p == nil) {
195368c31abSDavid du Colombier 			break;
196368c31abSDavid du Colombier 		}
197368c31abSDavid du Colombier 		vtDebug(z, "server recv: ");
198368c31abSDavid du Colombier 		vtDebugMesg(z, p, "\n");
199368c31abSDavid du Colombier 
200368c31abSDavid du Colombier 		if(!packetConsume(p, buf, 2)) {
201368c31abSDavid du Colombier 			vtSetError(EProtocolBotch);
202368c31abSDavid du Colombier 			break;
203368c31abSDavid du Colombier 		}
204368c31abSDavid du Colombier 		op = buf[0];
205368c31abSDavid du Colombier 		tid = buf[1];
206368c31abSDavid du Colombier 		switch(op) {
207368c31abSDavid du Colombier 		default:
208368c31abSDavid du Colombier 			vtSetError(EProtocolBotch);
209368c31abSDavid du Colombier 			goto Exit;
210368c31abSDavid du Colombier 		case VtQPing:
211368c31abSDavid du Colombier 			break;
212368c31abSDavid du Colombier 		case VtQGoodbye:
213368c31abSDavid du Colombier 			clean = 1;
214368c31abSDavid du Colombier 			goto Exit;
215368c31abSDavid du Colombier 		case VtQHello:
216368c31abSDavid du Colombier 			if(!dispatchHello(z, &p))
217368c31abSDavid du Colombier 				goto Exit;
218368c31abSDavid du Colombier 			break;
219368c31abSDavid du Colombier 		case VtQRead:
220368c31abSDavid du Colombier 			if(!dispatchRead(z, &p))
221368c31abSDavid du Colombier 				goto Exit;
222368c31abSDavid du Colombier 			break;
223368c31abSDavid du Colombier 		case VtQWrite:
224368c31abSDavid du Colombier 			if(!dispatchWrite(z, &p))
225368c31abSDavid du Colombier 				goto Exit;
226368c31abSDavid du Colombier 			break;
227368c31abSDavid du Colombier 		case VtQSync:
228368c31abSDavid du Colombier 			if(!dispatchSync(z, &p))
229368c31abSDavid du Colombier 				goto Exit;
230368c31abSDavid du Colombier 			break;
231368c31abSDavid du Colombier 		}
232368c31abSDavid du Colombier 		if(p != nil) {
233368c31abSDavid du Colombier 			hdr = packetHeader(p, 2);
234368c31abSDavid du Colombier 			hdr[0] = op+1;
235368c31abSDavid du Colombier 			hdr[1] = tid;
236368c31abSDavid du Colombier 		} else {
237368c31abSDavid du Colombier 			p = packetAlloc();
238368c31abSDavid du Colombier 			hdr = packetHeader(p, 2);
239368c31abSDavid du Colombier 			hdr[0] = VtRError;
240368c31abSDavid du Colombier 			hdr[1] = tid;
241368c31abSDavid du Colombier 			if(!vtAddString(p, vtGetError()))
242368c31abSDavid du Colombier 				goto Exit;
243368c31abSDavid du Colombier 		}
244368c31abSDavid du Colombier 
245368c31abSDavid du Colombier 		vtDebug(z, "server send: ");
246368c31abSDavid du Colombier 		vtDebugMesg(z, p, "\n");
247368c31abSDavid du Colombier 
248368c31abSDavid du Colombier 		if(!vtSendPacket(z, p)) {
249368c31abSDavid du Colombier 			p = nil;
250368c31abSDavid du Colombier 			goto Exit;
251368c31abSDavid du Colombier 		}
252368c31abSDavid du Colombier 	}
253368c31abSDavid du Colombier Exit:
254368c31abSDavid du Colombier 	if(p != nil)
255368c31abSDavid du Colombier 		packetFree(p);
256368c31abSDavid du Colombier 	if(z->vtbl->closing)
257368c31abSDavid du Colombier 		z->vtbl->closing(z, clean);
258368c31abSDavid du Colombier 	vtClose(z);
259368c31abSDavid du Colombier 	vtFree(z);
260368c31abSDavid du Colombier 	vtDetach();
261368c31abSDavid du Colombier 
262368c31abSDavid du Colombier 	exits(0);
263368c31abSDavid du Colombier 	return 0;	/* never gets here */
264368c31abSDavid du Colombier }
265368c31abSDavid du Colombier 
266