189 lines · 3.5 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <venti.h> int ventidoublechecksha1 = 1; static intvtfcallrpc(VtConn *z, VtFcall *ou, VtFcall *in){	Packet *p; 	p = vtfcallpack(ou);	if(p == nil)		return -1;	if((p = _vtrpc(z, p, ou)) == nil)		return -1;	if(vtfcallunpack(in, p) < 0){		packetfree(p);		return -1;	}	if(chattyventi)		fprint(2, "%s <- %F\n", argv0, in);	if(in->msgtype == VtRerror){		werrstr(in->error);		vtfcallclear(in);		packetfree(p);		return -1;	}	if(in->msgtype != ou->msgtype+1){		werrstr("type mismatch: sent %c%d got %c%d",			"TR"[ou->msgtype&1], ou->msgtype>>1,			"TR"[in->msgtype&1], in->msgtype>>1);		vtfcallclear(in);		packetfree(p);		return -1;	}	packetfree(p);	return 0;} intvthello(VtConn *z){	VtFcall tx, rx; 	memset(&tx, 0, sizeof tx);	tx.msgtype = VtThello;	tx.version = z->version;	tx.uid = z->uid;	if(tx.uid == nil)		tx.uid = "anonymous";	if(vtfcallrpc(z, &tx, &rx) < 0)		return -1;	z->sid = rx.sid;	rx.sid = 0;	vtfcallclear(&rx);	return 0;} Packet*vtreadpacket(VtConn *z, uchar score[VtScoreSize], uint type, int n){	VtFcall tx, rx; 	if(memcmp(score, vtzeroscore, VtScoreSize) == 0)		return packetalloc(); 	memset(&tx, 0, sizeof tx);	tx.msgtype = VtTread;	tx.blocktype = type;	tx.count = n;	memmove(tx.score, score, VtScoreSize);	if(vtfcallrpc(z, &tx, &rx) < 0)		return nil;	if(packetsize(rx.data) > n){		werrstr("read returned too much data");		packetfree(rx.data);		return nil;	}	if(ventidoublechecksha1){		packetsha1(rx.data, tx.score);		if(memcmp(score, tx.score, VtScoreSize) != 0){			werrstr("read asked for %V got %V", score, tx.score);			packetfree(rx.data);			return nil;		}	}	return rx.data;} intvtread(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n){	int nn;	Packet *p; 	if((p = vtreadpacket(z, score, type, n)) == nil)		return -1;	nn = packetsize(p);	if(packetconsume(p, buf, nn) < 0)		abort();	packetfree(p);	return nn;} intvtwritepacket(VtConn *z, uchar score[VtScoreSize], uint type, Packet *p){	VtFcall tx, rx; 	if(packetsize(p) == 0){		memmove(score, vtzeroscore, VtScoreSize);		return 0;	}	tx.msgtype = VtTwrite;	tx.blocktype = type;	tx.data = p;	if(ventidoublechecksha1)		packetsha1(p, score);	if(vtfcallrpc(z, &tx, &rx) < 0)		return -1;	if(ventidoublechecksha1){		if(memcmp(score, rx.score, VtScoreSize) != 0){			werrstr("sha1 hash mismatch: want %V got %V", score, rx.score);			return -1;		}	}else		memmove(score, rx.score, VtScoreSize);	return 0;} intvtwrite(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n){	Packet *p;	int nn; 	p = packetforeign(buf, n, 0, nil);	nn = vtwritepacket(z, score, type, p);	packetfree(p);	return nn;} intvtsync(VtConn *z){	VtFcall tx, rx; 	tx.msgtype = VtTsync;	return vtfcallrpc(z, &tx, &rx);} intvtping(VtConn *z){	VtFcall tx, rx; 	tx.msgtype = VtTping;	return vtfcallrpc(z, &tx, &rx);} intvtconnect(VtConn *z){	if(vtversion(z) < 0)		return -1;	if(vthello(z) < 0)		return -1;	return 0;} intvtgoodbye(VtConn *z){	VtFcall tx, rx;		tx.msgtype = VtTgoodbye;	vtfcallrpc(z, &tx, &rx);	/* always fails: no VtRgoodbye */	return 0;}