⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	v->dim = (Point){Dx(gscreen->r), Dy(gscreen->r)};	vncwrpoint(v, v->dim);	if(verbose)		fprint(2, "%V: send screen size %P (rect %R)\n", v, v->dim, gscreen->r);	v->bpp = gscreen->depth;	v->depth = gscreen->depth;	v->truecolor = 1;	v->bigendian = 0;	chan2fmt(v, gscreen->chan);	if(verbose)		fprint(2, "%V: bpp=%d, depth=%d, chan=%s\n", v,			v->bpp, v->depth, chantostr(buf, gscreen->chan));	vncwrpixfmt(v, v);	vncwrlong(v, 14);	vncwrbytes(v, "Plan9 Desktop", 14);	vncflush(v);	if(verbose)		fprint(2, "%V: handshaking done\n", v);	switch(rfork(RFPROC|RFMEM)){	case -1:		fprint(2, "%V: cannot fork: %r; hanging up\n", v);		vnchungup(v);	default:		clientreadproc(v);		exits(nil);	case 0:		*vncpriv = v;		v->nproc++;		if(atexit(exiting) == 0){			exiting();			fprint(2, "%V: could not register atexit handler: %r; hanging up\n", v);			exits(nil);		}		clientwriteproc(v);		exits(nil);	}}static voidvncname(char *fmt, ...){	int fd;	char name[64], buf[32];	va_list arg;	va_start(arg, fmt);	vsnprint(name, sizeof name, fmt, arg);	va_end(arg);	sprint(buf, "/proc/%d/args", getpid());	if((fd = open(buf, OWRITE)) >= 0){		write(fd, name, strlen(name));		close(fd);	}}/* * Set the pixel format being sent.  Can only happen once. * (Maybe a client would send this again if the screen changed * underneath it?  If we want to support this we need a way to * make sure the current image is no longer in use, so we can free it.  */static voidsetpixelfmt(Vncs *v){	ulong chan;	vncgobble(v, 3);	v->Pixfmt = vncrdpixfmt(v);	chan = fmt2chan(v);	if(chan == 0){		fprint(2, "%V: bad pixel format; hanging up\n", v);		vnchungup(v);	}	v->imagechan = chan;}/* * Set the preferred encoding list.  Can only happen once. * If we want to support changing this more than once then * we need to put a lock around the encoding functions * so as not to conflict with updateimage. */static voidsetencoding(Vncs *v){	int n, x;	vncrdchar(v);	n = vncrdshort(v);	while(n-- > 0){		x = vncrdlong(v);		switch(x){		case EncCopyRect:			v->copyrect = 1;			continue;		case EncMouseWarp:			v->canwarp = 1;			continue;		}		if(v->countrect != nil)			continue;		switch(x){		case EncRaw:			v->encname = "raw";			v->countrect = countraw;			v->sendrect = sendraw;			break;		case EncRre:			v->encname = "rre";			v->countrect = countrre;			v->sendrect = sendrre;			break;		case EncCorre:			v->encname = "corre";			v->countrect = countcorre;			v->sendrect = sendcorre;			break;		case EncHextile:			v->encname = "hextile";			v->countrect = counthextile;			v->sendrect = sendhextile;			break;		}	}	if(v->countrect == nil){		v->encname = "raw";		v->countrect = countraw;		v->sendrect = sendraw;	}	if(verbose)		fprint(2, "Encoding with %s%s%s\n", v->encname,			v->copyrect ? ", copyrect" : "",			v->canwarp ? ", canwarp" : "");}/* * Continually read updates from one client. */static voidclientreadproc(Vncs *v){	int incremental, key, keydown, buttons, type, x, y, n;	char *buf;	Rectangle r;	vncname("read %V", v);	for(;;){		type = vncrdchar(v);		switch(type){		default:			fprint(2, "%V: unknown vnc message type %d; hanging up\n", v, type);			vnchungup(v);		/* set pixel format */		case MPixFmt:			setpixelfmt(v);			break;		/* ignore color map changes */		case MFixCmap:			vncgobble(v, 3);			n = vncrdshort(v);			vncgobble(v, n*6);			break;		/* set encoding list */		case MSetEnc:			setencoding(v);			break;		/* request image update in rectangle */		case MFrameReq:			incremental = vncrdchar(v);			r = vncrdrect(v);			if(incremental){				vnclock(v);				v->updaterequest = 1;				vncunlock(v);			}else{				drawlock();	/* protects rlist */				vnclock(v);	/* protects updaterequest */				v->updaterequest = 1;				addtorlist(&v->rlist, r);				vncunlock(v);				drawunlock();			}			break;		/* send keystroke */		case MKey:			keydown = vncrdchar(v);			vncgobble(v, 2);			key = vncrdlong(v);			vncputc(!keydown, key);			break;		/* send mouse event */		case MMouse:			buttons = vncrdchar(v);			x = vncrdshort(v);			y = vncrdshort(v);			mousetrack(x, y, buttons, nsec()/(1000*1000LL));			break;		/* send cut text */		case MCCut:			vncgobble(v, 3);			n = vncrdlong(v);			buf = malloc(n+1);			if(buf){				vncrdbytes(v, buf, n);				buf[n] = 0;				vnclock(v);	/* for snarfvers */				setsnarf(buf, n, &v->snarfvers);				vncunlock(v);			}else				vncgobble(v, n);			break;		}	}}static intnbits(ulong mask){	int n;	n = 0;	for(; mask; mask>>=1)		n += mask&1;	return n;}typedef struct Col Col;struct Col {	int type;	int nbits;	int shift;};static ulongfmt2chan(Pixfmt *fmt){	Col c[4], t;	int i, j, depth, n, nc;	ulong mask, u;	/* unpack the Pixfmt channels */	c[0] = (Col){CRed, nbits(fmt->red.max), fmt->red.shift};	c[1] = (Col){CGreen, nbits(fmt->green.max), fmt->green.shift};	c[2] = (Col){CBlue, nbits(fmt->blue.max), fmt->blue.shift};	nc = 3;	/* add an ignore channel if necessary */	depth = c[0].nbits+c[1].nbits+c[2].nbits;	if(fmt->bpp != depth){		/* BUG: assumes only one run of ignored bits */		if(fmt->bpp == 32)			mask = ~0;		else			mask = (1<<fmt->bpp)-1;		mask ^= fmt->red.max << fmt->red.shift;		mask ^= fmt->green.max << fmt->green.shift;		mask ^= fmt->blue.max << fmt->blue.shift;		if(mask == 0)			abort();		n = 0;		for(; !(mask&1); mask>>=1)			n++;		c[3] = (Col){CIgnore, nbits(mask), n};		nc++;	}	/* sort the channels, largest shift (leftmost bits) first */	for(i=1; i<nc; i++)		for(j=i; j>0; j--)			if(c[j].shift > c[j-1].shift){				t = c[j];				c[j] = c[j-1];				c[j-1] = t;			}	/* build the channel descriptor */	u = 0;	for(i=0; i<nc; i++){		u <<= 8;		u |= CHAN1(c[i].type, c[i].nbits);	}	return u;}static voidchan2fmt(Pixfmt *fmt, ulong chan){	ulong c, rc, shift;	shift = 0;	for(rc = chan; rc; rc >>=8){		c = rc & 0xFF;		switch(TYPE(c)){		case CRed:			fmt->red = (Colorfmt){(1<<NBITS(c))-1, shift};			break;		case CBlue:			fmt->blue = (Colorfmt){(1<<NBITS(c))-1, shift};			break;		case CGreen:			fmt->green = (Colorfmt){(1<<NBITS(c))-1, shift};			break;		}		shift += NBITS(c);	}}/* * Note that r has changed on the screen. * Updating the rlists is okay because they are protected by drawlock. */voidflushmemscreen(Rectangle r){	Vncs *v;	if(!rectclip(&r, gscreen->r))		return;	qlock(&clients);	for(v=clients.head; v; v=v->next)		addtorlist(&v->rlist, r);	qunlock(&clients);}/* * Queue a mouse warp note for the next update to each client. */voidmousewarpnote(Point p){	Vncs *v;	qlock(&clients);	for(v=clients.head; v; v=v->next){		if(v->canwarp){			vnclock(v);			v->needwarp = 1;			v->warppt = p;			vncunlock(v);		}	}	qunlock(&clients);}/* * Send a client his changed screen image. * v is locked on entrance, locked on exit, but released during. */static intupdateimage(Vncs *v){	int i, ncount, nsend, docursor, needwarp;	vlong ooffset;	Point warppt;	Rectangle cr;	Rlist rlist;	vlong t1;	int (*count)(Vncs*, Rectangle);	int (*send)(Vncs*, Rectangle);	if(v->image == nil)		return 0;	/* warping info and unlock v so that updates can proceed */	needwarp = v->canwarp && v->needwarp;	warppt = v->warppt;	v->needwarp = 0;	vncunlock(v);	/* copy the screen bits and then unlock the screen so updates can proceed */	drawlock();	rlist = v->rlist;	memset(&v->rlist, 0, sizeof v->rlist);	/* if the cursor has moved or changed shape, we need to redraw its square */	lock(&cursor);	if(v->cursorver != cursorver || !eqpt(v->cursorpos, cursorpos)){		docursor = 1;		v->cursorver = cursorver;		v->cursorpos = cursorpos;		cr = cursorrect();	}else{		docursor = 0;		cr = v->cursorr;	}	unlock(&cursor);	if(docursor){		addtorlist(&rlist, v->cursorr);		if(!rectclip(&cr, gscreen->r))			cr.max = cr.min;		addtorlist(&rlist, cr);	}	/* copy changed screen parts, also check for parts overlapping cursor location */	for(i=0; i<rlist.nrect; i++){		if(!docursor)			docursor = rectXrect(v->cursorr, rlist.rect[i]);		memimagedraw(v->image, rlist.rect[i], gscreen, rlist.rect[i].min, memopaque, ZP, S);	}	if(docursor){		cursordraw(v->image, cr);		addtorlist(&rlist, v->cursorr);		v->cursorr = cr;	}	drawunlock();	ooffset = Boffset(&v->out);	/* no more locks are held; talk to the client */	if(rlist.nrect == 0 && needwarp == 0){		vnclock(v);		return 0;	}	count = v->countrect;	send = v->sendrect;	if(count == nil || send == nil){		count = countraw;		send = sendraw;	}	ncount = 0;	for(i=0; i<rlist.nrect; i++)		ncount += (*count)(v, rlist.rect[i]);	if(verbose > 1)		fprint(2, "sendupdate: rlist.nrect=%d, ncount=%d", rlist.nrect, ncount);	t1 = nsec();	vncwrchar(v, MFrameUpdate);	vncwrchar(v, 0);	vncwrshort(v, ncount+needwarp);	nsend = 0;	for(i=0; i<rlist.nrect; i++)		nsend += (*send)(v, rlist.rect[i]);	if(ncount != nsend){		fprint(2, "%V: ncount=%d, nsend=%d; hanging up\n", v, ncount, nsend);		vnchungup(v);	}	if(needwarp){		vncwrrect(v, Rect(warppt.x, warppt.y, warppt.x+1, warppt.y+1));		vncwrlong(v, EncMouseWarp);	}	t1 = nsec() - t1;	if(verbose > 1)		fprint(2, " in %lldms, %lld bytes\n", t1/1000000, Boffset(&v->out) - ooffset);	freerlist(&rlist);	vnclock(v);	return 1;}/* * Update the snarf buffer if it has changed. */static voidupdatesnarf(Vncs *v){	char *buf;	int len;	if(v->snarfvers == snarf.vers)		return;	vncunlock(v);	qlock(&snarf);	len = snarf.n;	buf = malloc(len);	if(buf == nil){		qunlock(&snarf);		vnclock(v);		return;	}	memmove(buf, snarf.buf, len);	v->snarfvers = snarf.vers;	qunlock(&snarf);	vncwrchar(v, MSCut);	vncwrbytes(v, "pad", 3);	vncwrlong(v, len);	vncwrbytes(v, buf, len);	free(buf);	vnclock(v);}/* * Continually update one client. */static voidclientwriteproc(Vncs *v){	char buf[32], buf2[32];	int sent;	vncname("write %V", v);	for(;;){		vnclock(v);		if(v->ndead)			break;		if((v->image == nil && v->imagechan!=0)		|| (v->image && v->image->chan != v->imagechan)){			if(v->image)				freememimage(v->image);			v->image = allocmemimage(Rpt(ZP, v->dim), v->imagechan);			if(v->image == nil){				fprint(2, "%V: allocmemimage: %r; hanging up\n", v);				vnchungup(v);			}			if(verbose)				fprint(2, "%V: translating image from chan=%s to chan=%s\n",					v, chantostr(buf, gscreen->chan), chantostr(buf2, v->imagechan));		}		sent = 0;		if(v->updaterequest){			v->updaterequest = 0;			updatesnarf(v);			sent = updateimage(v);			if(!sent)				v->updaterequest = 1;		}		vncunlock(v);		vncflush(v);		if(!sent)			sleep(sleeptime);	}	vncunlock(v);	vnchungup(v);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -