Various hacks to try to make stuff work (still failing).
[rdpsrv] / rdpsrv.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <sys/select.h>
6 #include <sys/socket.h>
7 #include <sys/ioctl.h>
8 #include <arpa/inet.h>
9
10 #include "rdesktop.h"
11
12 const int tcp_port_rdp = 3389;
13 int create_server_socket();
14 int serve_client();
15
16 int main()
17 {
18         int server_sock = create_server_socket();
19         for ( ;; ) {
20                 iso_recv_connect(server_sock);
21                 printf("Got connection.\n");
22                 serve_client();
23                 printf("Client closed.\n");
24         }
25 }
26
27 int create_server_socket()
28 {
29         int server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
30         const unsigned int one = 1, zero = 0;
31         struct sockaddr_in addr;
32         int err;
33
34         setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
35         ioctl(server_sock, FIONBIO, &zero);
36
37         addr.sin_family = AF_INET;
38         addr.sin_addr.s_addr = INADDR_ANY;
39         addr.sin_port = htons(tcp_port_rdp);
40
41         do {
42                 err = bind(server_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
43
44                 if (err == -1) {
45                         perror("bind()");
46
47                         /* try to recover from recoverable errors... */
48                         if (errno == ENOMEM || errno == EADDRINUSE) {
49                                 puts("Waiting 1 sec before trying again...");
50                                 sleep(1);
51                         } else {
52                                 puts("Giving up.");
53                                 exit(1);
54                         }
55                 }
56         } while (err == -1);
57
58         listen(server_sock, 20);
59         return server_sock;
60 }
61
62 void handle_input_pdu(STREAM s)
63 {
64         uint32 time;
65         uint16 message_type, device_flags, param1, param2;
66         uint16 num_events;
67         int i;
68
69         in_uint16_le(s, num_events);   // number of events
70         in_uint8s(s, 2);        // pad
71
72         for (i = 0; i < num_events; ++i) {
73                 rdp_recv_input(s, &time, &message_type, &device_flags, &param1, &param2);
74                 printf("Input event at time %u\n", time);
75                 
76                 switch (message_type) {
77                 case RDP_INPUT_SYNCHRONIZE:
78                         printf("- Type: Synchronize (ignored)\n");
79                         break;
80                 case RDP_INPUT_CODEPOINT:
81                         printf("- Type: Codepoint (ignored)\n");
82                         break;
83                 case RDP_INPUT_VIRTKEY:
84                         printf("- Type: Virtual key (ignored)\n");
85                         break;
86                 case RDP_INPUT_SCANCODE:
87                         printf("- Type: Scancode (ignored)\n");
88                         break;
89                 case RDP_INPUT_MOUSE:
90                         printf("- Type: Mouse\n");
91                         printf("- Device flags: %x\n", device_flags);
92                         printf("- Position: (%u,%u)\n", param1, param2);
93
94                         break;
95                 default:
96                         printf("- Unknown type %x\n", message_type);
97                         break;
98                 }
99                 printf("\n");
100         }
101 }
102
103 struct ServerInitialization {
104         unsigned short width;
105         unsigned short height;
106         unsigned char pixelformat[16]; // FIXME
107         unsigned int name_len;
108 };
109
110 int vnc_init()
111 {
112         char buf[256];
113         int vnc_sock = tcp_connect("127.0.0.1", 5901);
114         struct ServerInitialization si;
115
116         // get handshake
117         if (read(vnc_sock, buf, 12) != 12)
118                 error("short read on handshake\n");
119         write(vnc_sock, "RFB 003.003\n", 12);
120
121         // get auth
122         if (read(vnc_sock, buf, 4) != 4)
123                 error("short read on auth\n");
124
125         if (buf[3] != 1)
126                 error("auth needed or connection failed\n");
127
128         // send shared flag
129         buf[0] = 1;
130         write(vnc_sock, buf, 1);
131
132         // read the server initialization
133         if (read(vnc_sock, &si, sizeof(struct ServerInitialization)) != sizeof(struct ServerInitialization))
134                 error("short read on SI");
135
136         printf("Server is %u x %u\n", ntohs(si.width), ntohs(si.height));
137
138         if (read(vnc_sock, buf, ntohl(si.name_len)) != ntohl(si.name_len))
139                 error("short read on server name\n");
140
141         printf("Server name is '%*s' (%u bytes)\n", ntohl(si.name_len), buf, ntohl(si.name_len));
142
143         // we can only accept raw encoding
144         buf[0] = 2; // message type
145         buf[1] = 0; // padding
146         buf[2] = 0; // number of encodings
147         buf[3] = 1;
148         buf[4] = 0; // raw encoding
149         buf[5] = 0; 
150         buf[6] = 0;
151         buf[7] = 0;
152
153         write(vnc_sock, buf, 8);
154         
155         // request the entire framebuffer
156         buf[0] = 3; // message type
157         buf[1] = 0; // incremental
158         buf[2] = 0; // xpos
159         buf[3] = 0;
160         buf[4] = 0; // ypos
161         buf[5] = 0;
162         buf[6] = 0; // width
163         buf[7] = 640 % 0xff;
164         buf[8] = 0; // height
165         buf[9] = 480 % 0xff;
166
167         write(vnc_sock, buf, 10);
168         
169         printf("Connected to VNC!\n");
170
171         return vnc_sock;
172 }
173
174 struct vnc_rectangle {
175         unsigned short x, y, width, height;
176         unsigned int encoding;
177 };
178
179 void handle_vnc_fbupdate(int vnc_sock)
180 {
181         struct vnc_rectangle rect;
182         unsigned char *data, *ptr;
183         unsigned short num_rect;
184         int ret, data_left, i;
185
186         if (read(vnc_sock, &num_rect, 2) != 2)
187                 error("short read on num_rect\n");
188
189         for (i = 0; i < ntohs(num_rect); ++i) { 
190                 if (read(vnc_sock, &rect, sizeof(struct vnc_rectangle)) != sizeof(struct vnc_rectangle))
191                         error("short read on vnc_rectangle\n");
192                 
193                 printf("UPDATE: %ux%u at (%u,%u)\n", ntohs(rect.width), ntohs(rect.height),
194                         ntohs(rect.x), ntohs(rect.y));
195                 
196                 if (ntohl(rect.encoding) != 0)
197                         error("unsupported encoding\n");
198
199                 ptr = data = xmalloc(ntohs(rect.width) * ntohs(rect.height) * 3);
200                 data_left = ntohs(rect.width) * ntohs(rect.height) * 3;
201
202                 while (data_left > 0) {
203                         ret = read(vnc_sock, ptr, data_left);
204                         if (ret <= 0)
205                                 error("error on data read\n");
206
207                         ptr += ret;
208                         data_left -= ret;
209                 }
210
211 //              rdp_send_bitmap_update(ntohs(rect.x), ntohs(rect.y), ntohs(rect.width), ntohs(rect.height), data);
212                 xfree(data);
213         }
214 }
215
216 int serve_client()
217 {
218         int vnc_sock = vnc_init();
219         int listen_on_vnc = 0;
220         
221         if (!mcs_recv_connect_initial())
222                 error("MCS_CONNECT_INITIAL recv failed");
223         mcs_send_connect_response();
224
225         for ( ;; ) {
226                 uint8 type, data_pdu_type;
227                 STREAM s;
228
229                 fd_set readfs;
230                 FD_ZERO(&readfs);
231                 FD_SET(tcp_get_socket(), &readfs);
232                 FD_SET(vnc_sock, &readfs);
233                 
234                 select(FD_SETSIZE, &readfs, NULL, NULL, NULL);
235
236                 // activity on RDP socket?
237                 if (FD_ISSET(tcp_get_socket(), &readfs)) {
238                         if ((s = rdp_recv(&type)) != NULL) {
239                                 if (type != RDP_PDU_DATA) {
240                                         printf("Unknown RDP packet of type %u\n", type);
241                                         continue;
242                                 }
243
244                                 in_uint8s(s, 8);        /* shareid, pad, streamid, length */
245                                 in_uint8(s, data_pdu_type);
246                                 in_uint8s(s, 3);        /* compress_type, compress_len */
247
248                                 switch (data_pdu_type) {
249                                 case RDP_DATA_PDU_INPUT:
250                                         printf("Input PDU\n");
251                                         handle_input_pdu(s);
252                                         listen_on_vnc = 1;
253                                         break;
254                                 default:
255                                         printf("Unknown data PDU type %u\n", data_pdu_type);
256                                 };
257                         }
258                 }
259
260                 // activity on VNC socket?
261                 if (FD_ISSET(vnc_sock, &readfs) && listen_on_vnc) {
262                         unsigned char buf[256];
263
264                         printf("Activity on VNC socket!\n");
265                         
266                         if (read(vnc_sock, buf, 2) != 2)
267                                 error("short read on vnc_sock\n");
268
269                         switch (buf[0]) {
270                         case 0:
271                                 // frame buffer update!
272                                 handle_vnc_fbupdate(vnc_sock);
273                                 break;
274                         default:
275                                 printf("Unknown VNC server message %x\n", buf[0]);
276 //                              exit(1);
277                         }
278                 }
279         }
280 }