5 #include <sys/select.h>
6 #include <sys/socket.h>
11 #include "scancodes.h"
13 const int tcp_port_rdp = 3389;
14 int create_server_socket();
19 int server_sock = create_server_socket();
21 iso_recv_connect(server_sock);
22 printf("Got connection.\n");
24 printf("Client closed.\n");
28 int create_server_socket()
30 int server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
31 const unsigned int one = 1, zero = 0;
32 struct sockaddr_in addr;
35 setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
36 ioctl(server_sock, FIONBIO, &zero);
38 addr.sin_family = AF_INET;
39 addr.sin_addr.s_addr = INADDR_ANY;
40 addr.sin_port = htons(tcp_port_rdp);
43 err = bind(server_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
48 /* try to recover from recoverable errors... */
49 if (errno == ENOMEM || errno == EADDRINUSE) {
50 puts("Waiting 1 sec before trying again...");
59 listen(server_sock, 20);
63 int map_scancode_to_vnc_key(int scancode)
67 case SCANCODE_CHAR_1 ... SCANCODE_CHAR_9:
68 return scancode + '1' - SCANCODE_CHAR_1;
71 case SCANCODE_CHAR_BACKSPACE:
73 case SCANCODE_CHAR_TAB:
75 case SCANCODE_CHAR_Q ... SCANCODE_CHAR_P:
76 return "QWERTYUIOP"[scancode - SCANCODE_CHAR_Q];
77 case SCANCODE_CHAR_A ... SCANCODE_CHAR_L:
78 return "ASDFGHJKL"[scancode - SCANCODE_CHAR_A];
79 case SCANCODE_CHAR_Z ... SCANCODE_CHAR_M:
80 return "ZXCVBNM"[scancode - SCANCODE_CHAR_Z];
82 printf("Unknown scancode %x, ignoring\n", scancode);
87 void handle_input_pdu(STREAM s, int vnc_sock)
90 uint16 message_type, device_flags, param1, param2;
94 static int mouse1_down = 0, mouse2_down = 0;
97 in_uint16_le(s, num_events); // number of events
98 in_uint8s(s, 2); // pad
100 for (i = 0; i < num_events; ++i) {
101 rdp_recv_input(s, &time, &message_type, &device_flags, ¶m1, ¶m2);
102 printf("Input event at time %u\n", time);
104 switch (message_type) {
105 case RDP_INPUT_SYNCHRONIZE:
106 printf("- Type: Synchronize (ignored)\n");
108 case RDP_INPUT_CODEPOINT:
109 printf("- Type: Codepoint (ignored)\n");
111 case RDP_INPUT_VIRTKEY:
112 printf("- Type: Virtual key (ignored)\n");
114 case RDP_INPUT_SCANCODE:
115 printf("- Type: Scancode\n");
116 printf("- Device flags: %x\n", device_flags);
117 printf("- Key: %x\n", param1);
119 vnc_key = map_scancode_to_vnc_key(param1);
122 buf[0] = 4; // message type
123 buf[1] = (device_flags & KBD_FLAG_DOWN) ? 1 : 0; // down flag
124 buf[2] = 0; // padding
126 buf[4] = vnc_key >> 24; // keysym
127 buf[5] = (vnc_key >> 16) & 0xff;
128 buf[6] = (vnc_key >> 8) & 0xff;
129 buf[7] = vnc_key & 0xff;
130 write(vnc_sock, buf, 8);
134 case RDP_INPUT_MOUSE:
135 printf("- Type: Mouse\n");
136 printf("- Device flags: %x\n", device_flags);
137 printf("- Position: (%u,%u)\n", param1, param2);
139 if (device_flags & MOUSE_FLAG_BUTTON1)
140 mouse1_down = (device_flags & MOUSE_FLAG_DOWN) ? 0x01 : 0;
141 if (device_flags & MOUSE_FLAG_BUTTON2)
142 mouse2_down = (device_flags & MOUSE_FLAG_DOWN) ? 0x02 : 0;
144 printf("button mask = %x\n", mouse1_down | mouse2_down);
146 buf[0] = 5; // message type
147 buf[1] = mouse1_down | mouse2_down; // button mask
148 buf[2] = param1 >> 8;
149 buf[3] = param1 & 0xff;
150 buf[4] = param2 >> 8;
151 buf[5] = param2 & 0xff;
152 write(vnc_sock, buf, 6);
156 printf("- Unknown type %x\n", message_type);
162 // re-request the entire framebuffer
163 buf[0] = 3; // message type
164 buf[1] = 1; // incremental
169 buf[6] = 640 >> 8; // width
171 buf[8] = 480 >> 8; // height
174 write(vnc_sock, buf, 10);
177 void handle_control_pdu(STREAM s)
179 uint16 action, userid;
182 in_uint16_le(s, action);
183 in_uint16_le(s, userid);
184 in_uint32(s, control_id);
186 printf("Control PDU: action=%hu userid=%hu control_id=%u\n", action, userid, control_id);
189 case RDP_CTL_COOPERATE:
190 printf("Cooperate\n");
191 rdp_send_control(RDP_CTL_COOPERATE);
193 case RDP_CTL_REQUEST_CONTROL:
194 printf("Client requesting control; granting\n");
195 rdp_send_control(RDP_CTL_GRANT_CONTROL);
198 printf("Unhandled\n");
203 handle_font2_pdu(STREAM s)
205 printf("FONT2 PDU, responding with magic\n");
207 s = rdp_init_data(8);
213 rdp_send_data(s, 0x28);
216 struct ServerInitialization {
217 unsigned short width;
218 unsigned short height;
219 unsigned char pixelformat[16]; // FIXME
220 unsigned int name_len;
226 int vnc_sock = tcp_connect("127.0.0.1", 5901);
227 struct ServerInitialization si;
230 if (read(vnc_sock, buf, 12) != 12)
231 error("short read on handshake\n");
232 write(vnc_sock, "RFB 003.003\n", 12);
235 if (read(vnc_sock, buf, 4) != 4)
236 error("short read on auth\n");
239 error("auth needed or connection failed\n");
243 write(vnc_sock, buf, 1);
245 // read the server initialization
246 if (read(vnc_sock, &si, sizeof(struct ServerInitialization)) != sizeof(struct ServerInitialization))
247 error("short read on SI");
249 printf("Server is %u x %u\n", ntohs(si.width), ntohs(si.height));
251 if (read(vnc_sock, buf, ntohl(si.name_len)) != ntohl(si.name_len))
252 error("short read on server name\n");
254 // printf("Server name is '%*s' (%u bytes)\n", ntohl(si.name_len), buf, ntohl(si.name_len));
256 // we can only accept raw encoding
257 buf[0] = 2; // message type
258 buf[1] = 0; // padding
259 buf[2] = 0; // number of encodings
261 buf[4] = 0; // raw encoding
266 write(vnc_sock, buf, 8);
268 // request the entire framebuffer
269 buf[0] = 3; // message type
270 buf[1] = 0; // incremental
275 buf[6] = 640 >> 8; // width
277 buf[8] = 480 >> 8; // height
280 write(vnc_sock, buf, 10);
282 printf("Connected to VNC!\n");
287 struct vnc_rectangle {
288 unsigned short x, y, width, height;
289 unsigned int encoding;
295 void handle_vnc_fbupdate(int vnc_sock)
297 struct vnc_rectangle rect;
298 unsigned char *data, *ptr, *src, *dst;
299 unsigned short num_rect;
300 int ret, data_left, i, xt, yt;
301 unsigned char smallblock[SBX * SBY * 3];
303 if (read(vnc_sock, &num_rect, 2) != 2)
304 error("short read on num_rect\n");
306 for (i = 0; i < ntohs(num_rect); ++i) {
309 if (read(vnc_sock, &rect, sizeof(struct vnc_rectangle)) != sizeof(struct vnc_rectangle))
310 error("short read on vnc_rectangle\n");
312 if (ntohl(rect.encoding) != 0)
313 error("unsupported encoding\n");
315 width = ntohs(rect.width);
316 height = ntohs(rect.height);
318 printf("UPDATE: %ux%u at (%u,%u)\n", width, height,
319 ntohs(rect.x), ntohs(rect.y));
321 ptr = data = xmalloc(width * height * 4);
322 data_left = width * height * 4;
324 while (data_left > 0) {
325 ret = read(vnc_sock, ptr, data_left);
327 error("error on data read\n");
333 // push our 32-bit RGB data into small enough chunks
334 // (64x64) so we are sure we can send them without
335 // everything crashing and stuff :-)
336 for (yt = 0; yt < (height + (SBY-1)) / SBY; ++yt) {
337 for (xt = 0; xt < (width + (SBX-1)) / SBX; ++xt) {
339 int bw = width - xt * SBX;
340 int bh = height - yt * SBY;
347 for (y = 0; y < bh; ++y) {
348 src = data + ((yt * SBY + (bh - 1 - y)) * width + (xt * SBX)) * 4;
349 for (x = 0; x < bw; ++x) {
357 rdp_send_bitmap_update(ntohs(rect.x) + xt * SBX, ntohs(rect.y) + yt * SBY, bw, bh, smallblock);
365 int listen_on_vnc = 0;
369 int vnc_sock = vnc_init();
371 if (!mcs_recv_connect_initial())
372 error("MCS_CONNECT_INITIAL recv failed");
373 mcs_send_connect_response();
376 uint8 type, data_pdu_type;
382 FD_SET(tcp_get_socket(), &readfs);
383 FD_SET(vnc_sock, &readfs);
385 select(FD_SETSIZE, &readfs, NULL, NULL, NULL);
387 // activity on RDP socket?
388 if (FD_ISSET(tcp_get_socket(), &readfs)) {
389 if ((s = rdp_recv(&type)) != NULL) {
392 in_uint8s(s, 8); /* shareid, pad, streamid, length */
393 in_uint8(s, data_pdu_type);
394 in_uint8s(s, 3); /* compress_type, compress_len */
396 switch (data_pdu_type) {
397 case RDP_DATA_PDU_INPUT:
398 handle_input_pdu(s, vnc_sock);
401 case RDP_DATA_PDU_CONTROL:
402 handle_control_pdu(s);
404 case RDP_DATA_PDU_SYNCHRONISE:
406 printf("Synchronise, id=%u\n", id);
407 rdp_send_synchronise(id);
409 case RDP_DATA_PDU_FONT2:
413 printf("Unknown data PDU type %u\n", data_pdu_type);
416 case RDP_PDU_CONFIRM_ACTIVE:
417 printf("Client confirms activity\n");
420 printf("Unknown RDP PDU type %u\n", type);
425 // activity on VNC socket?
426 if (FD_ISSET(vnc_sock, &readfs) && listen_on_vnc) {
427 unsigned char buf[256];
429 printf("Activity on VNC socket!\n");
431 if (read(vnc_sock, buf, 1) != 1)
432 error("short read on vnc_sock\n");
436 // frame buffer update!
437 printf("Framebuffer update\n");
438 if (read(vnc_sock, buf, 1) != 1)
439 error("short read on vnc_sock\n");
440 handle_vnc_fbupdate(vnc_sock);
446 printf("New text in clipboard, ignoring\n");
447 if (read(vnc_sock, buf, 3) != 3)
448 error("short read on vnc_sock\n");
449 if (read(vnc_sock, buf, 4) != 4)
450 error("short read on vnc_sock\n");
451 if (read(vnc_sock, buf, (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) != 4)
452 error("short read on vnc_sock\n");
455 printf("Unknown VNC server message %x\n", buf[0]);