X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=rdpsrv.c;h=edb6299206847ffbefa32a5624b2e239188eb398;hb=38804e804acfd31c44aae9877dd7fa1183e732d7;hp=5b1603d12f1919f0575a094b4523ba9dfd07ca67;hpb=46f3372353ccdd654ef45f0b73128c16fb057e58;p=rdpsrv diff --git a/rdpsrv.c b/rdpsrv.c index 5b1603d..edb6299 100644 --- a/rdpsrv.c +++ b/rdpsrv.c @@ -2,30 +2,25 @@ #include #include #include +#include #include #include #include +#include "rdesktop.h" + const int tcp_port_rdp = 3389; int create_server_socket(); -int serve_client(int sock); +int serve_client(); int main() { int server_sock = create_server_socket(); for ( ;; ) { - struct sockaddr_in sin; - socklen_t len; - int sock = accept(server_sock, (struct sockaddr *)&sin, &len); - - if (sock == -1) { - perror("accept()"); - exit(1); - } - - serve_client(sock); - - close(sock); + iso_recv_connect(server_sock); + printf("Got connection.\n"); + serve_client(); + printf("Client closed.\n"); } } @@ -64,13 +59,218 @@ int create_server_socket() return server_sock; } +void handle_input_pdu(STREAM s) +{ + uint32 time; + uint16 message_type, device_flags, param1, param2; + uint16 num_events; + int i; + + in_uint16_le(s, num_events); // number of events + in_uint8s(s, 2); // pad -int serve_client(int sock) + for (i = 0; i < num_events; ++i) { + rdp_recv_input(s, &time, &message_type, &device_flags, ¶m1, ¶m2); + printf("Input event at time %u\n", time); + + switch (message_type) { + case RDP_INPUT_SYNCHRONIZE: + printf("- Type: Synchronize (ignored)\n"); + break; + case RDP_INPUT_CODEPOINT: + printf("- Type: Codepoint (ignored)\n"); + break; + case RDP_INPUT_VIRTKEY: + printf("- Type: Virtual key (ignored)\n"); + break; + case RDP_INPUT_SCANCODE: + printf("- Type: Scancode (ignored)\n"); + break; + case RDP_INPUT_MOUSE: + printf("- Type: Mouse\n"); + printf("- Device flags: %x\n", device_flags); + printf("- Position: (%u,%u)\n", param1, param2); + + break; + default: + printf("- Unknown type %x\n", message_type); + break; + } + printf("\n"); + } +} + +struct ServerInitialization { + unsigned short width; + unsigned short height; + unsigned char pixelformat[16]; // FIXME + unsigned int name_len; +}; + +int vnc_init() { - for ( ;; ) { - unsigned char buf[4096]; + char buf[256]; + int vnc_sock = tcp_connect("127.0.0.1", 5901); + struct ServerInitialization si; + + // get handshake + if (read(vnc_sock, buf, 12) != 12) + error("short read on handshake\n"); + write(vnc_sock, "RFB 003.003\n", 12); + + // get auth + if (read(vnc_sock, buf, 4) != 4) + error("short read on auth\n"); + + if (buf[3] != 1) + error("auth needed or connection failed\n"); + + // send shared flag + buf[0] = 1; + write(vnc_sock, buf, 1); + + // read the server initialization + if (read(vnc_sock, &si, sizeof(struct ServerInitialization)) != sizeof(struct ServerInitialization)) + error("short read on SI"); + + printf("Server is %u x %u\n", ntohs(si.width), ntohs(si.height)); + + 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)); + + // we can only accept raw encoding + buf[0] = 2; // message type + buf[1] = 0; // padding + buf[2] = 0; // number of encodings + buf[3] = 1; + buf[4] = 0; // raw encoding + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + write(vnc_sock, buf, 8); + + // request the entire framebuffer + buf[0] = 3; // message type + buf[1] = 0; // 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); + + printf("Connected to VNC!\n"); + + return vnc_sock; +} + +struct vnc_rectangle { + unsigned short x, y, width, height; + unsigned int encoding; +}; + +void handle_vnc_fbupdate(int vnc_sock) +{ + struct vnc_rectangle rect; + unsigned char *data, *ptr; + unsigned short num_rect; + int ret, data_left, i; + + if (read(vnc_sock, &num_rect, 2) != 2) + error("short read on num_rect\n"); + + for (i = 0; i < ntohs(num_rect); ++i) { + if (read(vnc_sock, &rect, sizeof(struct vnc_rectangle)) != sizeof(struct vnc_rectangle)) + error("short read on vnc_rectangle\n"); - /* receive ISO packets */ + 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; + + while (data_left > 0) { + ret = read(vnc_sock, ptr, data_left); + if (ret <= 0) + error("error on data read\n"); + + ptr += ret; + data_left -= ret; + } + + rdp_send_bitmap_update(ntohs(rect.x), ntohs(rect.y), ntohs(rect.width), ntohs(rect.height), data); + xfree(data); + } +} + +int serve_client() +{ + int vnc_sock = vnc_init(); + + if (!mcs_recv_connect_initial()) + error("MCS_CONNECT_INITIAL recv failed"); + mcs_send_connect_response(); + + for ( ;; ) { + uint8 type, data_pdu_type; + STREAM s; + + fd_set readfs; + FD_ZERO(&readfs); + FD_SET(tcp_get_socket(), &readfs); + FD_SET(vnc_sock, &readfs); + + select(FD_SETSIZE, &readfs, NULL, NULL, NULL); + + // 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: + printf("Input PDU\n"); + handle_input_pdu(s); + break; + default: + printf("Unknown data PDU type %u\n", data_pdu_type); + }; + } + } + + // activity on VNC socket? + if (FD_ISSET(vnc_sock, &readfs)) { + unsigned char buf[256]; + + printf("Activity on VNC socket!\n"); + + read(vnc_sock, buf, 2); + switch (buf[0]) { + case 0: + // frame buffer update! + handle_vnc_fbupdate(vnc_sock); + break; + default: + printf("Unknown server message %x\n", buf[0]); + exit(1); + } + } } }