View | Details | Raw Unified | Return to bug 250795 | Differences between
and this patch

Collapse All | Expand All

(-)rfb.c (-107 / +155 lines)
Lines 105-113 Link Here
105
	int		zbuflen;
105
	int		zbuflen;
106
106
107
	int		conn_wait;
107
	int		conn_wait;
108
	int		sending;
108
	int		pending;
109
	int		update_all;
109
	pthread_mutex_t mtx;
110
	pthread_mutex_t mtx;
110
	pthread_cond_t  cond;
111
	pthread_cond_t  cond;
112
	pthread_cond_t  writer_cond;
111
113
112
	int		hw_crc;
114
	int		hw_crc;
113
	uint32_t	*crc;		/* WxH crc cells */
115
	uint32_t	*crc;		/* WxH crc cells */
Lines 202-208 Link Here
202
	uint32_t	length;
204
	uint32_t	length;
203
};
205
};
204
206
205
206
static void
207
static void
207
rfb_send_server_init_msg(int cfd)
208
rfb_send_server_init_msg(int cfd)
208
{
209
{
Lines 223-228 Link Here
223
	sinfo.pixfmt.red_shift = 16;
224
	sinfo.pixfmt.red_shift = 16;
224
	sinfo.pixfmt.green_shift = 8;
225
	sinfo.pixfmt.green_shift = 8;
225
	sinfo.pixfmt.blue_shift = 0;
226
	sinfo.pixfmt.blue_shift = 0;
227
	sinfo.pixfmt.pad[0] = 0;
228
	sinfo.pixfmt.pad[1] = 0;
229
	sinfo.pixfmt.pad[2] = 0;
226
	sinfo.namelen = htonl(strlen("bhyve"));
230
	sinfo.namelen = htonl(strlen("bhyve"));
227
	(void)stream_write(cfd, &sinfo, sizeof(sinfo));
231
	(void)stream_write(cfd, &sinfo, sizeof(sinfo));
228
	(void)stream_write(cfd, "bhyve", strlen("bhyve"));
232
	(void)stream_write(cfd, "bhyve", strlen("bhyve"));
Lines 265-271 Link Here
265
	int i;
269
	int i;
266
	uint32_t encoding;
270
	uint32_t encoding;
267
271
268
	assert((sizeof(enc_msg) - 1) == 3);
269
	(void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1);
272
	(void)stream_read(cfd, ((void *)&enc_msg)+1, sizeof(enc_msg)-1);
270
273
271
	for (i = 0; i < htons(enc_msg.numencs); i++) {
274
	for (i = 0; i < htons(enc_msg.numencs); i++) {
Lines 308-319 Link Here
308
	return (crcval);
311
	return (crcval);
309
}
312
}
310
313
314
static int
315
rfb_send_update_header(struct rfb_softc *rc, int cfd, int numrects)
316
{
317
	struct rfb_srvr_updt_msg supdt_msg;
311
318
319
	supdt_msg.type = 0;
320
	supdt_msg.pad = 0;
321
	supdt_msg.numrects = htons(numrects);
322
323
	return stream_write(cfd, &supdt_msg,
324
	    sizeof(struct rfb_srvr_updt_msg));
325
}
326
312
static int
327
static int
313
rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc,
328
rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc,
314
              int x, int y, int w, int h)
329
              int x, int y, int w, int h)
315
{
330
{
316
	struct rfb_srvr_updt_msg supdt_msg;
317
	struct rfb_srvr_rect_hdr srect_hdr;
331
	struct rfb_srvr_rect_hdr srect_hdr;
318
	unsigned long zlen;
332
	unsigned long zlen;
319
	ssize_t nwrite, total;
333
	ssize_t nwrite, total;
Lines 325-340 Link Here
325
	 * Send a single rectangle of the given x, y, w h dimensions.
339
	 * Send a single rectangle of the given x, y, w h dimensions.
326
	 */
340
	 */
327
341
328
	/* Number of rectangles: 1 */
329
	supdt_msg.type = 0;
330
	supdt_msg.pad = 0;
331
	supdt_msg.numrects = htons(1);
332
	nwrite = stream_write(cfd, &supdt_msg,
333
	                      sizeof(struct rfb_srvr_updt_msg));
334
	if (nwrite <= 0)
335
		return (nwrite);
336
337
338
	/* Rectangle header */
342
	/* Rectangle header */
339
	srect_hdr.x = htons(x);
343
	srect_hdr.x = htons(x);
340
	srect_hdr.y = htons(y);
344
	srect_hdr.y = htons(y);
Lines 479-485 Link Here
479
#define	PIXCELL_MASK	0x1F
483
#define	PIXCELL_MASK	0x1F
480
484
481
static int
485
static int
482
rfb_send_screen(struct rfb_softc *rc, int cfd, int all)
486
rfb_send_screen(struct rfb_softc *rc, int cfd)
483
{
487
{
484
	struct bhyvegc_image *gc_image;
488
	struct bhyvegc_image *gc_image;
485
	ssize_t nwrite;
489
	ssize_t nwrite;
Lines 493-513 Link Here
493
	uint32_t *crc_p, *orig_crc;
497
	uint32_t *crc_p, *orig_crc;
494
	int changes;
498
	int changes;
495
499
500
	retval = 1;
501
496
	console_refresh();
502
	console_refresh();
497
	gc_image = console_get_image();
503
	gc_image = console_get_image();
498
504
499
	pthread_mutex_lock(&rc->mtx);
505
	/* Clear old CRC values when the size changes */
500
	if (rc->sending) {
506
	if (rc->crc_width != gc_image->width ||
501
		pthread_mutex_unlock(&rc->mtx);
507
	    rc->crc_height != gc_image->height) {
502
		return (1);
508
		memset(rc->crc, 0, sizeof(uint32_t) *
509
		    howmany(RFB_MAX_WIDTH, PIX_PER_CELL) *
510
		    howmany(RFB_MAX_HEIGHT, PIX_PER_CELL));
511
		rc->crc_width = gc_image->width;
512
		rc->crc_height = gc_image->height;
503
	}
513
	}
504
	rc->sending = 1;
505
	pthread_mutex_unlock(&rc->mtx);
506
514
507
	retval = 0;
515
       /* A size update counts as an update in itself */
516
       if (rc->width != gc_image->width ||
517
           rc->height != gc_image->height) {
518
               rc->width = gc_image->width;
519
               rc->height = gc_image->height;
520
               if (rc->enc_resize_ok) {
521
                       rfb_send_resize_update_msg(rc, cfd);
522
                       rc->update_all = 1;
523
                       goto done;
524
               }
525
       }
508
526
509
	if (all) {
527
	if (rc->update_all) {
510
		retval = rfb_send_all(rc, cfd, gc_image);
528
		retval = rfb_send_all(rc, cfd, gc_image);
529
		rc->update_all = 0;
511
		goto done;
530
		goto done;
512
	}
531
	}
513
532
Lines 516-526 Link Here
516
	 * has changed since the last scan.
535
	 * has changed since the last scan.
517
	 */
536
	 */
518
537
519
	/* Resolution changed */
520
521
	rc->crc_width = gc_image->width;
522
	rc->crc_height = gc_image->height;
523
524
	w = rc->crc_width;
538
	w = rc->crc_width;
525
	h = rc->crc_height;
539
	h = rc->crc_height;
526
	xcells = howmany(rc->crc_width, PIX_PER_CELL);
540
	xcells = howmany(rc->crc_width, PIX_PER_CELL);
Lines 580-591 Link Here
580
		}
594
		}
581
	}
595
	}
582
596
597
       /* We only send the update if there are changes */
598
	if (!changes) {
599
		goto done;
600
	}
601
	rc->pending = 0;
602
583
	/* If number of changes is > THRESH percent, send the whole screen */
603
	/* If number of changes is > THRESH percent, send the whole screen */
584
	if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) {
604
	if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) {
585
		retval = rfb_send_all(rc, cfd, gc_image);
605
		retval = rfb_send_all(rc, cfd, gc_image);
586
		goto done;
606
		goto done;
587
	}
607
	}
588
	
608
609
	rfb_send_update_header(rc, cfd, changes);
610
589
	/* Go through all cells, and send only changed ones */
611
	/* Go through all cells, and send only changed ones */
590
	crc_p = rc->crc_tmp;
612
	crc_p = rc->crc_tmp;
591
	for (y = 0; y < h; y += PIX_PER_CELL) {
613
	for (y = 0; y < h; y += PIX_PER_CELL) {
Lines 613-657 Link Here
613
			}
635
			}
614
		}
636
		}
615
	}
637
	}
616
	retval = 1;
617
638
618
done:
639
done:
619
	pthread_mutex_lock(&rc->mtx);
640
620
	rc->sending = 0;
621
	pthread_mutex_unlock(&rc->mtx);
622
	
623
	return (retval);
641
	return (retval);
624
}
642
}
625
643
626
644
627
static void
645
static void
628
rfb_recv_update_msg(struct rfb_softc *rc, int cfd, int discardonly)
646
rfb_recv_update_msg(struct rfb_softc *rc, int cfd)
629
{
647
{
630
	struct rfb_updt_msg updt_msg;
648
	struct rfb_updt_msg updt_msg;
631
	struct bhyvegc_image *gc_image;
632
649
633
	(void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1);
650
	(void)stream_read(cfd, ((void *)&updt_msg) + 1 , sizeof(updt_msg) - 1);
634
651
635
	console_refresh();
652
	rc->pending = 1;
636
	gc_image = console_get_image();
653
	if (!updt_msg.incremental) {
637
654
		rc->update_all = 1;
638
	updt_msg.x = htons(updt_msg.x);
639
	updt_msg.y = htons(updt_msg.y);
640
	updt_msg.width = htons(updt_msg.width);
641
	updt_msg.height = htons(updt_msg.height);
642
643
	if (updt_msg.width != gc_image->width ||
644
	    updt_msg.height != gc_image->height) {
645
		rc->width = gc_image->width;
646
		rc->height = gc_image->height;
647
		if (rc->enc_resize_ok)
648
			rfb_send_resize_update_msg(rc, cfd);
649
	}
655
	}
650
656
651
	if (discardonly)
657
	pthread_mutex_lock(&rc->mtx);
652
		return;
658
	pthread_cond_signal(&rc->writer_cond);
653
659
	pthread_mutex_unlock(&rc->mtx);
654
	rfb_send_screen(rc, cfd, 1);
655
}
660
}
656
661
657
static void
662
static void
Lines 703-742 Link Here
703
rfb_wr_thr(void *arg)
708
rfb_wr_thr(void *arg)
704
{
709
{
705
	struct rfb_softc *rc;
710
	struct rfb_softc *rc;
706
	fd_set rfds;
711
	struct timespec ts;
707
	struct timeval tv;
708
	struct timeval prev_tv;
709
	int64_t tdiff;
710
	int cfd;
712
	int cfd;
711
	int err;
712
713
713
	rc = arg;
714
	rc = arg;
714
	cfd = rc->cfd;
715
	cfd = rc->cfd;
715
716
716
	prev_tv.tv_sec = 0;
717
	prev_tv.tv_usec = 0;
718
	while (rc->cfd >= 0) {
717
	while (rc->cfd >= 0) {
719
		FD_ZERO(&rfds);
718
		clock_gettime(CLOCK_MONOTONIC, &ts);
720
		FD_SET(cfd, &rfds);
719
		ts.tv_nsec += 10000000;
721
		tv.tv_sec = 0;
720
		if (ts.tv_nsec >= 1000000000) {
722
		tv.tv_usec = 10000;
721
			ts.tv_sec++;
722
			ts.tv_nsec -= 1000000000;
723
		}
724
		pthread_mutex_lock(&rc->mtx);
725
		pthread_cond_timedwait(&rc->writer_cond, &rc->mtx, &ts);
726
		pthread_mutex_unlock(&rc->mtx);
723
727
724
		err = select(cfd+1, &rfds, NULL, NULL, &tv);
728
		/* Updates require a preceding update request */
725
		if (err < 0)
729
		if (rc->pending) {
726
			return (NULL);
730
			if (rfb_send_screen(rc, cfd) <= 0) {
727
728
		/* Determine if its time to push screen; ~24hz */
729
		gettimeofday(&tv, NULL);
730
		tdiff = timeval_delta(&prev_tv, &tv);
731
		if (tdiff > 40000) {
732
			prev_tv.tv_sec = tv.tv_sec;
733
			prev_tv.tv_usec = tv.tv_usec;
734
			if (rfb_send_screen(rc, cfd, 0) <= 0) {
735
				return (NULL);
731
				return (NULL);
736
			}
732
			}
737
		} else {
738
			/* sleep */
739
			usleep(40000 - tdiff);
740
		}
733
		}
741
	}
734
	}
742
735
Lines 758-764 Link Here
758
	DES_key_schedule ks;
751
	DES_key_schedule ks;
759
	int i;
752
	int i;
760
#endif
753
#endif
761
754
	uint8_t client_ver;
755
	uint8_t auth_type;
762
	pthread_t tid;
756
	pthread_t tid;
763
	uint32_t sres = 0;
757
	uint32_t sres = 0;
764
	int len;
758
	int len;
Lines 771-797 Link Here
771
765
772
	/* 1b. Read client version */
766
	/* 1b. Read client version */
773
	len = stream_read(cfd, buf, VERSION_LENGTH);
767
	len = stream_read(cfd, buf, VERSION_LENGTH);
768
	if (len == VERSION_LENGTH && !strncmp(vbuf, buf, VERSION_LENGTH - 2)) {
769
		client_ver = buf[VERSION_LENGTH - 2];
770
	}
771
	if (client_ver != '8' && client_ver != '7') {
772
		/* only recognize 3.3, 3.7 & 3.8. Others dflt to 3.3 */
773
		client_ver = '3';
774
	}
774
775
775
	/* 2a. Send security type */
776
	/* 2a. Send security type */
776
	buf[0] = 1;
777
	buf[0] = 1;
778
779
	/* In versions 3.7 & 3.8, it's 2-way handshake */
780
	/* For version 3.3, server says what the authentication type must be */
777
#ifndef NO_OPENSSL
781
#ifndef NO_OPENSSL
778
	if (rc->password) 
782
	if (rc->password) {
779
		buf[1] = SECURITY_TYPE_VNC_AUTH;
783
		auth_type = SECURITY_TYPE_VNC_AUTH;
780
	else
784
	} else {
781
		buf[1] = SECURITY_TYPE_NONE;
785
		auth_type = SECURITY_TYPE_NONE;
786
	}
782
#else
787
#else
783
	buf[1] = SECURITY_TYPE_NONE;
788
	auth_type = SECURITY_TYPE_NONE;
784
#endif
789
#endif
785
790
786
	stream_write(cfd, buf, 2);
791
	switch (client_ver) {
792
	case '7':
793
	case '8':
794
		buf[0] = 1;
795
		buf[1] = auth_type;
796
		stream_write(cfd, buf, 2);
787
797
788
	/* 2b. Read agreed security type */
798
		/* 2b. Read agreed security type */
789
	len = stream_read(cfd, buf, 1);
799
		len = stream_read(cfd, buf, 1);
800
		if (buf[0] != auth_type) {
801
			/* deny */
802
			sres = htonl(1);
803
			message = "Auth failed: authentication type mismatch";
804
			goto report_and_done;
805
		}
806
		break;
807
	case '3':
808
	default:
809
		be32enc(buf, auth_type);
810
		stream_write(cfd, buf, 4);
811
		break;
812
	}
790
813
791
	/* 2c. Do VNC authentication */
814
	/* 2c. Do VNC authentication */
792
	switch (buf[0]) {
815
	switch (auth_type) {
793
	case SECURITY_TYPE_NONE:
816
	case SECURITY_TYPE_NONE:
794
		sres = 0;
795
		break;
817
		break;
796
	case SECURITY_TYPE_VNC_AUTH:
818
	case SECURITY_TYPE_VNC_AUTH:
797
		/*
819
		/*
Lines 839-848 Link Here
839
		if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) {
861
		if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) {
840
			message = "Auth Failed: Invalid Password.";
862
			message = "Auth Failed: Invalid Password.";
841
			sres = htonl(1);
863
			sres = htonl(1);
842
		} else
864
		} else {
843
			sres = 0;
865
			sres = 0;
866
		}
844
#else
867
#else
845
		sres = 0;
868
		sres = htonl(1);
846
		WPRINTF(("Auth not supported, no OpenSSL in your system"));
869
		WPRINTF(("Auth not supported, no OpenSSL in your system"));
847
#endif
870
#endif
848
871
Lines 849-862 Link Here
849
		break;
872
		break;
850
	}
873
	}
851
874
852
	/* 2d. Write back a status */
875
	switch (client_ver) {
853
	stream_write(cfd, &sres, 4);
876
	case '7':
877
	case '8':
878
report_and_done:
879
		/* 2d. Write back a status */
880
		stream_write(cfd, &sres, 4);
854
881
855
	if (sres) {
882
		if (sres) {
856
		be32enc(buf, strlen(message));
883
			/* 3.7 does not want string explaining cause */
857
		stream_write(cfd, buf, 4);
884
			if (client_ver == '8') {
858
		stream_write(cfd, message, strlen(message));
885
				be32enc(buf, strlen(message));
859
		goto done;
886
				stream_write(cfd, buf, 4);
887
				stream_write(cfd, message, strlen(message));
888
			}
889
			goto done;
890
		}
891
		break;
892
	case '3':
893
	default:
894
		/* for VNC auth case send status */
895
		if (auth_type == SECURITY_TYPE_VNC_AUTH) {
896
			/* 2d. Write back a status */
897
			stream_write(cfd, &sres, 4);
898
		}
899
		if (sres) {
900
			goto done;
901
		}
902
		break;
860
	}
903
	}
861
904
862
	/* 3a. Read client shared-flag byte */
905
	/* 3a. Read client shared-flag byte */
Lines 870-877 Link Here
870
		assert(rc->zbuf != NULL);
913
		assert(rc->zbuf != NULL);
871
	}
914
	}
872
915
873
	rfb_send_screen(rc, cfd, 1);
874
875
	perror = pthread_create(&tid, NULL, rfb_wr_thr, rc);
916
	perror = pthread_create(&tid, NULL, rfb_wr_thr, rc);
876
	if (perror == 0)
917
	if (perror == 0)
877
		pthread_set_name_np(tid, "rfbout");
918
		pthread_set_name_np(tid, "rfbout");
Lines 892-898 Link Here
892
			rfb_recv_set_encodings_msg(rc, cfd);
933
			rfb_recv_set_encodings_msg(rc, cfd);
893
			break;
934
			break;
894
		case 3:
935
		case 3:
895
			rfb_recv_update_msg(rc, cfd, 1);
936
			rfb_recv_update_msg(rc, cfd);
896
			break;
937
			break;
897
		case 4:
938
		case 4:
898
			rfb_recv_key_msg(rc, cfd);
939
			rfb_recv_key_msg(rc, cfd);
Lines 974-979 Link Here
974
	struct addrinfo *ai = NULL;
1015
	struct addrinfo *ai = NULL;
975
	struct addrinfo hints;
1016
	struct addrinfo hints;
976
	int on = 1;
1017
	int on = 1;
1018
	int cnt;
1019
	pthread_condattr_t condattr;
977
#ifndef WITHOUT_CAPSICUM
1020
#ifndef WITHOUT_CAPSICUM
978
	cap_rights_t rights;
1021
	cap_rights_t rights;
979
#endif
1022
#endif
Lines 980-989 Link Here
980
1023
981
	rc = calloc(1, sizeof(struct rfb_softc));
1024
	rc = calloc(1, sizeof(struct rfb_softc));
982
1025
983
	rc->crc = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
1026
	cnt = howmany(RFB_MAX_WIDTH, PIX_PER_CELL) *
984
	                 sizeof(uint32_t));
1027
	    howmany(RFB_MAX_HEIGHT, PIX_PER_CELL);
985
	rc->crc_tmp = calloc(howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, 32),
1028
	rc->crc = calloc(cnt, sizeof(uint32_t));
986
	                     sizeof(uint32_t));
1029
	rc->crc_tmp = calloc(cnt, sizeof(uint32_t));
987
	rc->crc_width = RFB_MAX_WIDTH;
1030
	rc->crc_width = RFB_MAX_WIDTH;
988
	rc->crc_height = RFB_MAX_HEIGHT;
1031
	rc->crc_height = RFB_MAX_HEIGHT;
989
	rc->sfd = -1;
1032
	rc->sfd = -1;
Lines 1037-1046 Link Here
1037
1080
1038
	rc->conn_wait = wait;
1081
	rc->conn_wait = wait;
1039
	if (wait) {
1082
	if (wait) {
1040
		pthread_mutex_init(&rc->mtx, NULL);
1041
		pthread_cond_init(&rc->cond, NULL);
1083
		pthread_cond_init(&rc->cond, NULL);
1042
	}
1084
	}
1043
1085
1086
	pthread_mutex_init(&rc->mtx, NULL);
1087
1088
	pthread_condattr_init(&condattr);
1089
	pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
1090
	pthread_cond_init(&rc->writer_cond, &condattr);
1091
1044
	pthread_create(&rc->tid, NULL, rfb_thr, rc);
1092
	pthread_create(&rc->tid, NULL, rfb_thr, rc);
1045
	pthread_set_name_np(rc->tid, "rfb");
1093
	pthread_set_name_np(rc->tid, "rfb");
1046
1094

Return to bug 250795