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

📄 vnc.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 3 页
字号:
    }}static void key_event(VncState *vs, int down, uint32_t sym){    if (sym >= 'A' && sym <= 'Z')	sym = sym - 'A' + 'a';    do_key_event(vs, down, sym);}static void framebuffer_update_request(VncState *vs, int incremental,				       int x_position, int y_position,				       int w, int h){    int i;    vs->need_update = 1;    if (!incremental) {	char *old_row = vs->old_data + y_position * vs->ds->linesize;	for (i = 0; i < h; i++) {            vnc_set_bits(vs->dirty_row[y_position + i],                          (vs->ds->width / 16), VNC_DIRTY_WORDS);	    memset(old_row, 42, vs->ds->width * vs->depth);	    old_row += vs->ds->linesize;	}    }}static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings){    int i;    vs->has_hextile = 0;    vs->has_resize = 0;    vs->has_pointer_type_change = 0;    vs->absolute = -1;    vs->ds->dpy_copy = NULL;    for (i = n_encodings - 1; i >= 0; i--) {	switch (encodings[i]) {	case 0: /* Raw */	    vs->has_hextile = 0;	    break;	case 1: /* CopyRect */	    vs->ds->dpy_copy = vnc_copy;	    break;	case 5: /* Hextile */	    vs->has_hextile = 1;	    break;	case -223: /* DesktopResize */	    vs->has_resize = 1;	    break;	case -257:	    vs->has_pointer_type_change = 1;	    break;	default:	    break;	}    }    check_pointer_type_change(vs, kbd_mouse_is_absolute());}static int compute_nbits(unsigned int val){    int n;    n = 0;    while (val != 0) {        n++;        val >>= 1;    }    return n;}static void set_pixel_format(VncState *vs,			     int bits_per_pixel, int depth,			     int big_endian_flag, int true_color_flag,			     int red_max, int green_max, int blue_max,			     int red_shift, int green_shift, int blue_shift){    int host_big_endian_flag;#ifdef WORDS_BIGENDIAN    host_big_endian_flag = 1;#else    host_big_endian_flag = 0;#endif    if (!true_color_flag) {    fail:	vnc_client_error(vs);        return;    }    if (bits_per_pixel == 32 &&         host_big_endian_flag == big_endian_flag &&        red_max == 0xff && green_max == 0xff && blue_max == 0xff &&        red_shift == 16 && green_shift == 8 && blue_shift == 0) {        vs->depth = 4;        vs->write_pixels = vnc_write_pixels_copy;        vs->send_hextile_tile = send_hextile_tile_32;    } else     if (bits_per_pixel == 16 &&         host_big_endian_flag == big_endian_flag &&        red_max == 31 && green_max == 63 && blue_max == 31 &&        red_shift == 11 && green_shift == 5 && blue_shift == 0) {        vs->depth = 2;        vs->write_pixels = vnc_write_pixels_copy;        vs->send_hextile_tile = send_hextile_tile_16;    } else     if (bits_per_pixel == 8 &&         red_max == 7 && green_max == 7 && blue_max == 3 &&        red_shift == 5 && green_shift == 2 && blue_shift == 0) {        vs->depth = 1;        vs->write_pixels = vnc_write_pixels_copy;        vs->send_hextile_tile = send_hextile_tile_8;    } else     {        /* generic and slower case */        if (bits_per_pixel != 8 &&            bits_per_pixel != 16 &&            bits_per_pixel != 32)            goto fail;        vs->depth = 4;        vs->red_shift = red_shift;        vs->red_max = red_max;        vs->red_shift1 = 24 - compute_nbits(red_max);        vs->green_shift = green_shift;        vs->green_max = green_max;        vs->green_shift1 = 16 - compute_nbits(green_max);        vs->blue_shift = blue_shift;        vs->blue_max = blue_max;        vs->blue_shift1 = 8 - compute_nbits(blue_max);        vs->pix_bpp = bits_per_pixel / 8;        vs->pix_big_endian = big_endian_flag;        vs->write_pixels = vnc_write_pixels_generic;        vs->send_hextile_tile = send_hextile_tile_generic;    }    vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));    memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);    vga_hw_invalidate();    vga_hw_update();}static int protocol_client_msg(VncState *vs, char *data, size_t len){    int i;    uint16_t limit;    switch (data[0]) {    case 0:	if (len == 1)	    return 20;	set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),			 read_u8(data, 6), read_u8(data, 7),			 read_u16(data, 8), read_u16(data, 10),			 read_u16(data, 12), read_u8(data, 14),			 read_u8(data, 15), read_u8(data, 16));	break;    case 2:	if (len == 1)	    return 4;	if (len == 4)	    return 4 + (read_u16(data, 2) * 4);	limit = read_u16(data, 2);	for (i = 0; i < limit; i++) {	    int32_t val = read_s32(data, 4 + (i * 4));	    memcpy(data + 4 + (i * 4), &val, sizeof(val));	}	set_encodings(vs, (int32_t *)(data + 4), limit);	break;    case 3:	if (len == 1)	    return 10;	framebuffer_update_request(vs,				   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),				   read_u16(data, 6), read_u16(data, 8));	break;    case 4:	if (len == 1)	    return 8;	key_event(vs, read_u8(data, 1), read_u32(data, 4));	break;    case 5:	if (len == 1)	    return 6;	pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));	break;    case 6:	if (len == 1)	    return 8;	if (len == 8)	    return 8 + read_u32(data, 4);	client_cut_text(vs, read_u32(data, 4), data + 8);	break;    default:	printf("Msg: %d\n", data[0]);	vnc_client_error(vs);	break;    }	    vnc_read_when(vs, protocol_client_msg, 1);    return 0;}static int protocol_client_init(VncState *vs, char *data, size_t len){    char pad[3] = { 0, 0, 0 };    vs->width = vs->ds->width;    vs->height = vs->ds->height;    vnc_write_u16(vs, vs->ds->width);    vnc_write_u16(vs, vs->ds->height);    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */    vnc_write_u8(vs, vs->depth * 8); /* depth */#ifdef WORDS_BIGENDIAN    vnc_write_u8(vs, 1);             /* big-endian-flag */#else    vnc_write_u8(vs, 0);             /* big-endian-flag */#endif    vnc_write_u8(vs, 1);             /* true-color-flag */    if (vs->depth == 4) {	vnc_write_u16(vs, 0xFF);     /* red-max */	vnc_write_u16(vs, 0xFF);     /* green-max */	vnc_write_u16(vs, 0xFF);     /* blue-max */	vnc_write_u8(vs, 16);        /* red-shift */	vnc_write_u8(vs, 8);         /* green-shift */	vnc_write_u8(vs, 0);         /* blue-shift */        vs->send_hextile_tile = send_hextile_tile_32;    } else if (vs->depth == 2) {	vnc_write_u16(vs, 31);       /* red-max */	vnc_write_u16(vs, 63);       /* green-max */	vnc_write_u16(vs, 31);       /* blue-max */	vnc_write_u8(vs, 11);        /* red-shift */	vnc_write_u8(vs, 5);         /* green-shift */	vnc_write_u8(vs, 0);         /* blue-shift */        vs->send_hextile_tile = send_hextile_tile_16;    } else if (vs->depth == 1) {        /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */	vnc_write_u16(vs, 7);        /* red-max */	vnc_write_u16(vs, 7);        /* green-max */	vnc_write_u16(vs, 3);        /* blue-max */	vnc_write_u8(vs, 5);         /* red-shift */	vnc_write_u8(vs, 2);         /* green-shift */	vnc_write_u8(vs, 0);         /* blue-shift */        vs->send_hextile_tile = send_hextile_tile_8;    }    vs->write_pixels = vnc_write_pixels_copy;	    vnc_write(vs, pad, 3);           /* padding */    vnc_write_u32(vs, 4);            vnc_write(vs, "QEMU", 4);    vnc_flush(vs);    vnc_read_when(vs, protocol_client_msg, 1);    return 0;}static int protocol_version(VncState *vs, char *version, size_t len){    char local[13];    int maj, min;    memcpy(local, version, 12);    local[12] = 0;    if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {	vnc_client_error(vs);	return 0;    }    vnc_write_u32(vs, 1); /* None */    vnc_flush(vs);    vnc_read_when(vs, protocol_client_init, 1);    return 0;}static void vnc_listen_read(void *opaque){    VncState *vs = opaque;    struct sockaddr_in addr;    socklen_t addrlen = sizeof(addr);    vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);    if (vs->csock != -1) {        socket_set_nonblock(vs->csock);	qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);	vnc_write(vs, "RFB 003.003\n", 12);	vnc_flush(vs);	vnc_read_when(vs, protocol_version, 12);	memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);	memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));	vs->has_resize = 0;	vs->has_hextile = 0;	vs->ds->dpy_copy = NULL;    }}extern int parse_host_port(struct sockaddr_in *saddr, const char *str);void vnc_display_init(DisplayState *ds, const char *arg){    struct sockaddr *addr;    struct sockaddr_in iaddr;#ifndef _WIN32    struct sockaddr_un uaddr;#endif    int reuse_addr, ret;    socklen_t addrlen;    const char *p;    VncState *vs;    vs = qemu_mallocz(sizeof(VncState));    if (!vs)	exit(1);    ds->opaque = vs;    vnc_state = vs;    vs->display = arg;    vs->lsock = -1;    vs->csock = -1;    vs->depth = 4;    vs->last_x = -1;    vs->last_y = -1;    vs->ds = ds;    if (!keyboard_layout)	keyboard_layout = "en-us";    vs->kbd_layout = init_keyboard_layout(keyboard_layout);    if (!vs->kbd_layout)	exit(1);    vs->ds->data = NULL;    vs->ds->dpy_update = vnc_dpy_update;    vs->ds->dpy_resize = vnc_dpy_resize;    vs->ds->dpy_refresh = vnc_dpy_refresh;    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));    vnc_dpy_resize(vs->ds, 640, 400);#ifndef _WIN32    if (strstart(arg, "unix:", &p)) {	addr = (struct sockaddr *)&uaddr;	addrlen = sizeof(uaddr);	vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);	if (vs->lsock == -1) {	    fprintf(stderr, "Could not create socket\n");	    exit(1);	}	uaddr.sun_family = AF_UNIX;	memset(uaddr.sun_path, 0, 108);	snprintf(uaddr.sun_path, 108, "%s", p);	unlink(uaddr.sun_path);    } else#endif    {	addr = (struct sockaddr *)&iaddr;	addrlen = sizeof(iaddr);	vs->lsock = socket(PF_INET, SOCK_STREAM, 0);	if (vs->lsock == -1) {	    fprintf(stderr, "Could not create socket\n");	    exit(1);	}	if (parse_host_port(&iaddr, arg) < 0) {	    fprintf(stderr, "Could not parse VNC address\n");	    exit(1);	}	    	iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);	reuse_addr = 1;	ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,			 (const char *)&reuse_addr, sizeof(reuse_addr));	if (ret == -1) {	    fprintf(stderr, "setsockopt() failed\n");	    exit(1);	}    }    if (bind(vs->lsock, addr, addrlen) == -1) {	fprintf(stderr, "bind() failed\n");	exit(1);    }    if (listen(vs->lsock, 1) == -1) {	fprintf(stderr, "listen() failed\n");	exit(1);    }    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);    if (ret == -1) {	exit(1);    }}

⌨️ 快捷键说明

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