xref: /plan9-contrib/sys/src/libventi/server.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
4 #include "session.h"
5 
6 static char EAuthState[] = "bad authentication state";
7 static char ENotServer[] = "not a server session";
8 static char EVersion[] = "incorrect version number";
9 static char EProtocolBotch[] = "venti protocol botch";
10 
11 VtSession *
12 vtServerAlloc(VtServerVtbl *vtbl)
13 {
14 	VtSession *z = vtAlloc();
15 	z->vtbl = vtMemAlloc(sizeof(VtServerVtbl));
16 	*z->vtbl = *vtbl;
17 	return z;
18 }
19 
20 static int
21 srvHello(VtSession *z, char *version, char *uid, int , uchar *, int , uchar *, int )
22 {
23 	vtLock(z->lk);
24 	if(z->auth.state != VtAuthHello) {
25 		vtSetError(EAuthState);
26 		goto Err;
27 	}
28 	if(strcmp(version, vtGetVersion(z)) != 0) {
29 		vtSetError(EVersion);
30 		goto Err;
31 	}
32 	vtMemFree(z->uid);
33 	z->uid = vtStrDup(uid);
34 	z->auth.state = VtAuthOK;
35 	vtUnlock(z->lk);
36 	return 1;
37 Err:
38 	z->auth.state = VtAuthFailed;
39 	vtUnlock(z->lk);
40 	return 0;
41 }
42 
43 
44 static int
45 dispatchHello(VtSession *z, Packet **pkt)
46 {
47 	char *version, *uid;
48 	uchar *crypto, *codec;
49 	uchar buf[10];
50 	int ncrypto, ncodec, cryptoStrength;
51 	int ret;
52 	Packet *p;
53 
54 	p = *pkt;
55 
56 	version = nil;
57 	uid = nil;
58 	crypto = nil;
59 	codec = nil;
60 
61 	ret = 0;
62 	if(!vtGetString(p, &version))
63 		goto Err;
64 	if(!vtGetString(p, &uid))
65 		goto Err;
66 	if(!packetConsume(p, buf, 2))
67 		goto Err;
68 	cryptoStrength = buf[0];
69 	ncrypto = buf[1];
70 	crypto = vtMemAlloc(ncrypto);
71 	if(!packetConsume(p, crypto, ncrypto))
72 		goto Err;
73 
74 	if(!packetConsume(p, buf, 1))
75 		goto Err;
76 	ncodec = buf[0];
77 	codec = vtMemAlloc(ncodec);
78 	if(!packetConsume(p, codec, ncodec))
79 		goto Err;
80 
81 	if(packetSize(p) != 0) {
82 		vtSetError(EProtocolBotch);
83 		goto Err;
84 	}
85 	if(!srvHello(z, version, uid, cryptoStrength, crypto, ncrypto, codec, ncodec)) {
86 		packetFree(p);
87 		*pkt = nil;
88 	} else {
89 		if(!vtAddString(p, vtGetSid(z)))
90 			goto Err;
91 		buf[0] = vtGetCrypto(z);
92 		buf[1] = vtGetCodec(z);
93 		packetAppend(p, buf, 2);
94 	}
95 	ret = 1;
96 Err:
97 	vtMemFree(version);
98 	vtMemFree(uid);
99 	vtMemFree(crypto);
100 	vtMemFree(codec);
101 	return ret;
102 }
103 
104 static int
105 dispatchRead(VtSession *z, Packet **pkt)
106 {
107 	Packet *p;
108 	int type, n;
109 	uchar score[VtScoreSize], buf[4];
110 
111 	p = *pkt;
112 	if(!packetConsume(p, score, VtScoreSize))
113 		return 0;
114 	if(!packetConsume(p, buf, 4))
115 		return 0;
116 	type = buf[0];
117 	n = (buf[2]<<8) | buf[3];
118 	if(packetSize(p) != 0) {
119 		vtSetError(EProtocolBotch);
120 		return 0;
121 	}
122 	packetFree(p);
123 	*pkt = (*z->vtbl->read)(z, score, type, n);
124 	return 1;
125 }
126 
127 static int
128 dispatchWrite(VtSession *z, Packet **pkt)
129 {
130 	Packet *p;
131 	int type;
132 	uchar score[VtScoreSize], buf[4];
133 
134 	p = *pkt;
135 	if(!packetConsume(p, buf, 4))
136 		return 0;
137 	type = buf[0];
138 	if(!(z->vtbl->write)(z, score, type, p)) {
139 		*pkt = 0;
140 	} else {
141 		*pkt = packetAlloc();
142 		packetAppend(*pkt, score, VtScoreSize);
143 	}
144 	return 1;
145 }
146 
147 static int
148 dispatchSync(VtSession *z, Packet **pkt)
149 {
150 	(z->vtbl->sync)(z);
151 	if(packetSize(*pkt) != 0) {
152 		vtSetError(EProtocolBotch);
153 		return 0;
154 	}
155 	return 1;
156 }
157 
158 int
159 vtExport(VtSession *z)
160 {
161 	Packet *p;
162 	uchar buf[10], *hdr;
163 	int op, tid, clean;
164 
165 	if(z->vtbl == nil) {
166 		vtSetError(ENotServer);
167 		return 0;
168 	}
169 
170 	/* fork off slave */
171 	switch(rfork(RFNOWAIT|RFMEM|RFPROC)){
172 	case -1:
173 		vtOSError();
174 		return 0;
175 	case 0:
176 		break;
177 	default:
178 		return 1;
179 	}
180 
181 
182 	p = nil;
183 	clean = 0;
184 	vtAttach();
185 	if(!vtConnect(z, nil))
186 		goto Exit;
187 
188 	vtDebug(z, "server connected!\n");
189 if(0)	vtSetDebug(z, 1);
190 
191 	for(;;) {
192 		p = vtRecvPacket(z);
193 		if(p == nil) {
194 			break;
195 		}
196 		vtDebug(z, "server recv: ");
197 		vtDebugMesg(z, p, "\n");
198 
199 		if(!packetConsume(p, buf, 2)) {
200 			vtSetError(EProtocolBotch);
201 			break;
202 		}
203 		op = buf[0];
204 		tid = buf[1];
205 		switch(op) {
206 		default:
207 			vtSetError(EProtocolBotch);
208 			goto Exit;
209 		case VtQPing:
210 			break;
211 		case VtQGoodbye:
212 			clean = 1;
213 			goto Exit;
214 		case VtQHello:
215 			if(!dispatchHello(z, &p))
216 				goto Exit;
217 			break;
218 		case VtQRead:
219 			if(!dispatchRead(z, &p))
220 				goto Exit;
221 			break;
222 		case VtQWrite:
223 			if(!dispatchWrite(z, &p))
224 				goto Exit;
225 			break;
226 		case VtQSync:
227 			if(!dispatchSync(z, &p))
228 				goto Exit;
229 			break;
230 		}
231 		if(p != nil) {
232 			hdr = packetHeader(p, 2);
233 			hdr[0] = op+1;
234 			hdr[1] = tid;
235 		} else {
236 			p = packetAlloc();
237 			hdr = packetHeader(p, 2);
238 			hdr[0] = VtRError;
239 			hdr[1] = tid;
240 			if(!vtAddString(p, vtGetError()))
241 				goto Exit;
242 		}
243 
244 		vtDebug(z, "server send: ");
245 		vtDebugMesg(z, p, "\n");
246 
247 		if(!vtSendPacket(z, p)) {
248 			p = nil;
249 			goto Exit;
250 		}
251 	}
252 Exit:
253 	if(p != nil)
254 		packetFree(p);
255 	if(z->vtbl->closing)
256 		z->vtbl->closing(z, clean);
257 	vtClose(z);
258 	vtFree(z);
259 	vtDetach();
260 
261 	exits(0);
262 	return 0;	/* never gets here */
263 }
264 
265