X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=rdpsrv.c;h=cee8d77f17f4b3b5c038468e48e3d11306311578;hp=c838fc7a60c711d7f7ec8434a9b9755ad8040feb;hb=677f1de1497be360b9f70411663d233d6fbe7dab;hpb=dbccf42e4424093cfc0f970d1fcfaad9ae60c954 diff --git a/rdpsrv.c b/rdpsrv.c index c838fc7..cee8d77 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,6 +59,30 @@ 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, int vnc_sock) { @@ -67,6 +92,7 @@ void handle_input_pdu(STREAM s, int vnc_sock) 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 @@ -86,7 +112,24 @@ void handle_input_pdu(STREAM s, int vnc_sock) 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"); @@ -97,6 +140,8 @@ void handle_input_pdu(STREAM s, int vnc_sock) 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 @@ -129,6 +174,45 @@ void handle_input_pdu(STREAM s, int vnc_sock) write(vnc_sock, buf, 10); } +void handle_control_pdu(STREAM s) +{ + uint16 action, userid; + uint32 control_id; + + in_uint16_le(s, action); + in_uint16_le(s, userid); + in_uint32(s, control_id); + + printf("Control PDU: action=%hu userid=%hu control_id=%u\n", action, userid, control_id); + + switch (action) { + case RDP_CTL_COOPERATE: + printf("Cooperate\n"); + rdp_send_control(RDP_CTL_COOPERATE); + break; + case RDP_CTL_REQUEST_CONTROL: + printf("Client requesting control; granting\n"); + rdp_send_control(RDP_CTL_GRANT_CONTROL); + break; + default: + printf("Unhandled\n"); + } +} + +void +handle_font2_pdu(STREAM s) +{ + printf("FONT2 PDU, responding with magic\n"); + + s = rdp_init_data(8); + out_uint16_le(s, 0); + out_uint16_le(s, 0); + out_uint16_le(s, 3); + out_uint16_le(s, 4); + s_mark_end(s); + rdp_send_data(s, 0x28); +} + struct ServerInitialization { unsigned short width; unsigned short height; @@ -205,13 +289,16 @@ struct vnc_rectangle { unsigned int encoding; }; +#define SBX 32 +#define SBY 32 + void handle_vnc_fbupdate(int vnc_sock) { struct vnc_rectangle rect; unsigned char *data, *ptr, *src, *dst; unsigned short num_rect; int ret, data_left, i, xt, yt; - unsigned char smallblock[64 * 64 * 3]; + unsigned char smallblock[SBX * SBY * 3]; if (read(vnc_sock, &num_rect, 2) != 2) error("short read on num_rect\n"); @@ -246,19 +333,19 @@ void handle_vnc_fbupdate(int vnc_sock) // 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) { + for (yt = 0; yt < (height + (SBY-1)) / SBY; ++yt) { + for (xt = 0; xt < (width + (SBX-1)) / SBX; ++xt) { int x, y; - int bw = width - xt * 64; - int bh = height - yt * 64; - if (bw > 64) - bw = 64; - if (bh > 64) - bh = 64; + int bw = width - xt * SBX; + int bh = height - yt * SBY; + if (bw > SBX) + bw = SBX; + if (bh > SBY) + bh = SBY; dst = smallblock; for (y = 0; y < bh; ++y) { - src = data + ((yt * 64 + (bh - 1 - y)) * width + (xt * 64)) * 4; + src = data + ((yt * SBY + (bh - 1 - y)) * width + (xt * SBX)) * 4; for (x = 0; x < bw; ++x) { *dst++ = *src++; *dst++ = *src++; @@ -267,7 +354,7 @@ void handle_vnc_fbupdate(int vnc_sock) } } - rdp_send_bitmap_update(ntohs(rect.x) + xt * 64, ntohs(rect.y) + yt * 64, bw, bh, smallblock); + rdp_send_bitmap_update(ntohs(rect.x) + xt * SBX, ntohs(rect.y) + yt * SBY, bw, bh, smallblock); } } @@ -275,10 +362,11 @@ void handle_vnc_fbupdate(int vnc_sock) } } +int listen_on_vnc = 0; + int serve_client() { int vnc_sock = vnc_init(); - int listen_on_vnc = 0; if (!mcs_recv_connect_initial()) error("MCS_CONNECT_INITIAL recv failed"); @@ -286,6 +374,7 @@ int serve_client() for ( ;; ) { uint8 type, data_pdu_type; + uint16 id; STREAM s; fd_set readfs; @@ -298,23 +387,38 @@ int serve_client() // activity on RDP socket? if (FD_ISSET(tcp_get_socket(), &readfs)) { if ((s = rdp_recv(&type)) != NULL) { - if (type != RDP_PDU_DATA) { - printf("Unknown RDP packet of type %u\n", type); - continue; - } - - in_uint8s(s, 8); /* shareid, pad, streamid, length */ - in_uint8(s, data_pdu_type); - in_uint8s(s, 3); /* compress_type, compress_len */ - - switch (data_pdu_type) { - case RDP_DATA_PDU_INPUT: - handle_input_pdu(s, vnc_sock); - listen_on_vnc = 1; + switch (type) { + case RDP_PDU_DATA: + in_uint8s(s, 8); /* shareid, pad, streamid, length */ + in_uint8(s, data_pdu_type); + in_uint8s(s, 3); /* compress_type, compress_len */ + + switch (data_pdu_type) { + case RDP_DATA_PDU_INPUT: + handle_input_pdu(s, vnc_sock); + listen_on_vnc = 1; + break; + case RDP_DATA_PDU_CONTROL: + handle_control_pdu(s); + break; + case RDP_DATA_PDU_SYNCHRONISE: + in_uint16_le(s, id); + printf("Synchronise, id=%u\n", id); + rdp_send_synchronise(id); + break; + case RDP_DATA_PDU_FONT2: + handle_font2_pdu(s); + break; + default: + printf("Unknown data PDU type %u\n", data_pdu_type); + }; + break; + case RDP_PDU_CONFIRM_ACTIVE: + printf("Client confirms activity\n"); break; default: - printf("Unknown data PDU type %u\n", data_pdu_type); - }; + printf("Unknown RDP PDU type %u\n", type); + } } } @@ -335,9 +439,18 @@ int serve_client() error("short read on vnc_sock\n"); handle_vnc_fbupdate(vnc_sock); break; - case 2: + 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 VNC server message %x\n", buf[0]); exit(1);