240 lines · 4.1 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> Packet*vtfcallpack(VtFcall *f){	uchar buf[4];	Packet *p; 	p = packetalloc(); 	buf[0] = f->msgtype;	buf[1] = f->tag;	packetappend(p, buf, 2); 	switch(f->msgtype){	default:		werrstr("vtfcallpack: unknown packet type %d", f->msgtype);		goto Err; 	case VtRerror:		if(vtputstring(p, f->error) < 0)			goto Err;		break; 	case VtTping:		break; 	case VtRping:		break; 	case VtThello:		if(vtputstring(p, f->version) < 0		|| vtputstring(p, f->uid) < 0)			goto Err;		buf[0] = f->strength;		buf[1] = f->ncrypto;		packetappend(p, buf, 2);		packetappend(p, f->crypto, f->ncrypto);		buf[0] = f->ncodec;		packetappend(p, buf, 1);		packetappend(p, f->codec, f->ncodec);		break; 	case VtRhello:		if(vtputstring(p, f->sid) < 0)			goto Err;		buf[0] = f->rcrypto;		buf[1] = f->rcodec;		packetappend(p, buf, 2);		break; 	case VtTgoodbye:		break; 	case VtTread:		packetappend(p, f->score, VtScoreSize);		buf[0] = vttodisktype(f->blocktype);		if(~buf[0] == 0)			goto Err;		buf[1] = 0;		buf[2] = f->count >> 8;		buf[3] = f->count;		packetappend(p, buf, 4);		break; 	case VtRread:		packetconcat(p, f->data);		break; 	case VtTwrite:		buf[0] = vttodisktype(f->blocktype);		if(~buf[0] == 0)			goto Err;		buf[1] = 0;		buf[2] = 0;		buf[3] = 0;		packetappend(p, buf, 4);		packetconcat(p, f->data);		break; 	case VtRwrite:		packetappend(p, f->score, VtScoreSize);		break; 	case VtTsync:		break; 	case VtRsync:		break;	} 	return p; Err:	packetfree(p);	return nil;} intvtfcallunpack(VtFcall *f, Packet *p){	uchar buf[4]; 	memset(f, 0, sizeof *f); 	if(packetconsume(p, buf, 2) < 0)		return -1; 	f->msgtype = buf[0];	f->tag = buf[1]; 	switch(f->msgtype){	default:		werrstr("vtfcallunpack: unknown bad packet type %d", f->msgtype);		vtfcallclear(f);		return -1; 	case VtRerror:		if(vtgetstring(p, &f->error) < 0)			goto Err;		break; 	case VtTping:		break; 	case VtRping:		break; 	case VtThello:		if(vtgetstring(p, &f->version) < 0		|| vtgetstring(p, &f->uid) < 0		|| packetconsume(p, buf, 2) < 0)			goto Err;		f->strength = buf[0];		f->ncrypto = buf[1];		if(f->ncrypto){			f->crypto = vtmalloc(f->ncrypto);			if(packetconsume(p, buf, f->ncrypto) < 0)				goto Err;		}		if(packetconsume(p, buf, 1) < 0)			goto Err;		f->ncodec = buf[0];		if(f->ncodec){			f->codec = vtmalloc(f->ncodec);			if(packetconsume(p, buf, f->ncodec) < 0)				goto Err;		}		break; 	case VtRhello:		if(vtgetstring(p, &f->sid) < 0		|| packetconsume(p, buf, 2) < 0)			goto Err;		f->rcrypto = buf[0];		f->rcodec = buf[1];		break; 	case VtTgoodbye:		break; 	case VtTread:		if(packetconsume(p, f->score, VtScoreSize) < 0		|| packetconsume(p, buf, 4) < 0)			goto Err;		f->blocktype = vtfromdisktype(buf[0]);		if(~f->blocktype == 0)			goto Err;		f->count = (buf[2] << 8) | buf[3];		break; 	case VtRread:		f->data = packetalloc();		packetconcat(f->data, p);		break; 	case VtTwrite:		if(packetconsume(p, buf, 4) < 0)			goto Err;		f->blocktype = vtfromdisktype(buf[0]);		if(~f->blocktype == 0)			goto Err;		f->data = packetalloc();		packetconcat(f->data, p);		break; 	case VtRwrite:		if(packetconsume(p, f->score, VtScoreSize) < 0)			goto Err;		break; 	case VtTsync:		break; 	case VtRsync:		break;	} 	if(packetsize(p) != 0)		goto Err; 	return 0; Err:	werrstr("bad packet");	vtfcallclear(f);	return -1;} voidvtfcallclear(VtFcall *f){	vtfree(f->error);	f->error = nil;	vtfree(f->uid);	f->uid = nil;	vtfree(f->sid);	f->sid = nil;	vtfree(f->version);	f->version = nil;	vtfree(f->crypto);	f->crypto = nil;	vtfree(f->codec);	f->codec = nil;	vtfree(f->auth);	f->auth = nil;	packetfree(f->data);	f->data = nil;}