X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=rdpsrv.c;h=91989872cf530955bd5cd274a21f858e9d09818a;hp=edb6299206847ffbefa32a5624b2e239188eb398;hb=132e47e292eea211b9ab0ba2f835cb7f41197ada;hpb=38804e804acfd31c44aae9877dd7fa1183e732d7 diff --git a/rdpsrv.c b/rdpsrv.c index edb6299..9198987 100644 --- a/rdpsrv.c +++ b/rdpsrv.c @@ -8,6 +8,7 @@ #include #include "rdesktop.h" +#include "scancodes.h" const int tcp_port_rdp = 3389; int create_server_socket(); @@ -58,13 +59,40 @@ int create_server_socket() listen(server_sock, 20); return server_sock; } + +int map_scancode_to_vnc_key(int scancode) +{ + switch (scancode) + { + case SCANCODE_CHAR_1 ... SCANCODE_CHAR_9: + return scancode + '1' - SCANCODE_CHAR_1; + case SCANCODE_CHAR_0: + return '0'; + case SCANCODE_CHAR_BACKSPACE: + return 0xff08; + case SCANCODE_CHAR_TAB: + return 0xff09; + case SCANCODE_CHAR_Q ... SCANCODE_CHAR_P: + return "QWERTYUIOP"[scancode - SCANCODE_CHAR_Q]; + case SCANCODE_CHAR_A ... SCANCODE_CHAR_L: + return "ASDFGHJKL"[scancode - SCANCODE_CHAR_A]; + case SCANCODE_CHAR_Z ... SCANCODE_CHAR_M: + return "ZXCVBNM"[scancode - SCANCODE_CHAR_Z]; + default: + printf("Unknown scancode %x, ignoring\n", scancode); + return -1; + } +} -void handle_input_pdu(STREAM s) +void handle_input_pdu(STREAM s, int vnc_sock) { uint32 time; uint16 message_type, device_flags, param1, param2; uint16 num_events; int i; + char buf[256]; + static int mouse1_down = 0, mouse2_down = 0; + int vnc_key; in_uint16_le(s, num_events); // number of events in_uint8s(s, 2); // pad @@ -84,13 +112,45 @@ void handle_input_pdu(STREAM s) printf("- Type: Virtual key (ignored)\n"); break; case RDP_INPUT_SCANCODE: - printf("- Type: Scancode (ignored)\n"); + printf("- Type: Scancode\n"); + printf("- Device flags: %x\n", device_flags); + printf("- Key: %x\n", param1); + + vnc_key = map_scancode_to_vnc_key(param1); + + if (vnc_key != -1) { + buf[0] = 4; // message type + buf[1] = (device_flags & KBD_FLAG_DOWN) ? 1 : 0; // down flag + buf[2] = 0; // padding + buf[3] = 0; + buf[4] = vnc_key >> 24; // keysym + buf[5] = (vnc_key >> 16) & 0xff; + buf[6] = (vnc_key >> 8) & 0xff; + buf[7] = vnc_key & 0xff; + write(vnc_sock, buf, 8); + } + break; case RDP_INPUT_MOUSE: printf("- Type: Mouse\n"); printf("- Device flags: %x\n", device_flags); printf("- Position: (%u,%u)\n", param1, param2); + if (device_flags & MOUSE_FLAG_BUTTON1) + mouse1_down = (device_flags & MOUSE_FLAG_DOWN) ? 0x01 : 0; + if (device_flags & MOUSE_FLAG_BUTTON2) + mouse2_down = (device_flags & MOUSE_FLAG_DOWN) ? 0x02 : 0; + + printf("button mask = %x\n", mouse1_down | mouse2_down); + + buf[0] = 5; // message type + buf[1] = mouse1_down | mouse2_down; // button mask + buf[2] = param1 >> 8; + buf[3] = param1 & 0xff; + buf[4] = param2 >> 8; + buf[5] = param2 & 0xff; + write(vnc_sock, buf, 6); + break; default: printf("- Unknown type %x\n", message_type); @@ -98,6 +158,20 @@ void handle_input_pdu(STREAM s) } printf("\n"); } + + // re-request the entire framebuffer + buf[0] = 3; // message type + buf[1] = 1; // incremental + buf[2] = 0; // xpos + buf[3] = 0; + buf[4] = 0; // ypos + buf[5] = 0; + buf[6] = 640 >> 8; // width + buf[7] = 640 & 0xff; + buf[8] = 480 >> 8; // height + buf[9] = 480 & 0xff; + + write(vnc_sock, buf, 10); } struct ServerInitialization { @@ -138,7 +212,7 @@ int vnc_init() if (read(vnc_sock, buf, ntohl(si.name_len)) != ntohl(si.name_len)) error("short read on server name\n"); - printf("Server name is '%*s' (%u bytes)\n", ntohl(si.name_len), buf, ntohl(si.name_len)); +// printf("Server name is '%*s' (%u bytes)\n", ntohl(si.name_len), buf, ntohl(si.name_len)); // we can only accept raw encoding buf[0] = 2; // message type @@ -160,9 +234,9 @@ int vnc_init() buf[4] = 0; // ypos buf[5] = 0; buf[6] = 640 >> 8; // width - buf[7] = 640 % 0xff; + buf[7] = 640 & 0xff; buf[8] = 480 >> 8; // height - buf[9] = 480 % 0xff; + buf[9] = 480 & 0xff; write(vnc_sock, buf, 10); @@ -179,25 +253,31 @@ struct vnc_rectangle { void handle_vnc_fbupdate(int vnc_sock) { struct vnc_rectangle rect; - unsigned char *data, *ptr; + unsigned char *data, *ptr, *src, *dst; unsigned short num_rect; - int ret, data_left, i; + int ret, data_left, i, xt, yt; + unsigned char smallblock[64 * 64 * 3]; if (read(vnc_sock, &num_rect, 2) != 2) error("short read on num_rect\n"); - for (i = 0; i < ntohs(num_rect); ++i) { + for (i = 0; i < ntohs(num_rect); ++i) { + int width, height; + if (read(vnc_sock, &rect, sizeof(struct vnc_rectangle)) != sizeof(struct vnc_rectangle)) error("short read on vnc_rectangle\n"); - printf("UPDATE: %ux%u at (%u,%u)\n", ntohs(rect.width), ntohs(rect.height), - ntohs(rect.x), ntohs(rect.y)); - if (ntohl(rect.encoding) != 0) error("unsupported encoding\n"); - ptr = data = xmalloc(ntohs(rect.width) * ntohs(rect.height) * 3); - data_left = ntohs(rect.width) * ntohs(rect.height) * 3; + width = ntohs(rect.width); + height = ntohs(rect.height); + + printf("UPDATE: %ux%u at (%u,%u)\n", width, height, + ntohs(rect.x), ntohs(rect.y)); + + ptr = data = xmalloc(width * height * 4); + data_left = width * height * 4; while (data_left > 0) { ret = read(vnc_sock, ptr, data_left); @@ -208,7 +288,34 @@ void handle_vnc_fbupdate(int vnc_sock) data_left -= ret; } - rdp_send_bitmap_update(ntohs(rect.x), ntohs(rect.y), ntohs(rect.width), ntohs(rect.height), data); + // push our 32-bit RGB data into small enough chunks + // (64x64) so we are sure we can send them without + // everything crashing and stuff :-) + for (yt = 0; yt < (height + 63) / 64; ++yt) { + for (xt = 0; xt < (width + 63) / 64; ++xt) { + int x, y; + int bw = width - xt * 64; + int bh = height - yt * 64; + if (bw > 64) + bw = 64; + if (bh > 64) + bh = 64; + + dst = smallblock; + for (y = 0; y < bh; ++y) { + src = data + ((yt * 64 + (bh - 1 - y)) * width + (xt * 64)) * 4; + for (x = 0; x < bw; ++x) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + ++src; + } + } + + rdp_send_bitmap_update(ntohs(rect.x) + xt * 64, ntohs(rect.y) + yt * 64, bw, bh, smallblock); + } + } + xfree(data); } } @@ -216,6 +323,7 @@ void handle_vnc_fbupdate(int vnc_sock) int serve_client() { int vnc_sock = vnc_init(); + int listen_on_vnc = 0; if (!mcs_recv_connect_initial()) error("MCS_CONNECT_INITIAL recv failed"); @@ -246,8 +354,8 @@ int serve_client() switch (data_pdu_type) { case RDP_DATA_PDU_INPUT: - printf("Input PDU\n"); - handle_input_pdu(s); + handle_input_pdu(s, vnc_sock); + listen_on_vnc = 1; break; default: printf("Unknown data PDU type %u\n", data_pdu_type); @@ -256,19 +364,36 @@ int serve_client() } // activity on VNC socket? - if (FD_ISSET(vnc_sock, &readfs)) { + if (FD_ISSET(vnc_sock, &readfs) && listen_on_vnc) { unsigned char buf[256]; printf("Activity on VNC socket!\n"); - read(vnc_sock, buf, 2); + if (read(vnc_sock, buf, 1) != 1) + error("short read on vnc_sock\n"); + switch (buf[0]) { case 0: // frame buffer update! + printf("Framebuffer update\n"); + if (read(vnc_sock, buf, 1) != 1) + error("short read on vnc_sock\n"); handle_vnc_fbupdate(vnc_sock); break; + case 2: // bell + printf("\n"); + break; + case 3: + printf("New text in clipboard, ignoring\n"); + if (read(vnc_sock, buf, 3) != 3) + error("short read on vnc_sock\n"); + if (read(vnc_sock, buf, 4) != 4) + error("short read on vnc_sock\n"); + if (read(vnc_sock, buf, (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) != 4) + error("short read on vnc_sock\n"); + default: - printf("Unknown server message %x\n", buf[0]); + printf("Unknown VNC server message %x\n", buf[0]); exit(1); } }