]> git.sesse.net Git - rdpsrv/blob - rdpsrv.c
Send encodings _correctly_ this time...
[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                         // debug
95                         rdp_send_bitmap_update(param1, param2);
96                         
97                         break;
98                 default:
99                         printf("- Unknown type %x\n", message_type);
100                         break;
101                 }
102                 printf("\n");
103         }
104 }
105
106 struct ServerInitialization {
107         unsigned short width;
108         unsigned short height;
109         unsigned char pixelformat[16]; // FIXME
110         unsigned int name_len;
111 };
112
113 int vnc_init()
114 {
115         char buf[256];
116         int vnc_sock = tcp_connect("127.0.0.1", 5901);
117         struct ServerInitialization si;
118
119         // get handshake
120         if (read(vnc_sock, buf, 12) != 12)
121                 error("short read on handshake\n");
122         write(vnc_sock, "RFB 003.003\n", 12);
123
124         // get auth
125         if (read(vnc_sock, buf, 4) != 4)
126                 error("short read on auth\n");
127
128         if (buf[3] != 1)
129                 error("auth needed or connection failed\n");
130
131         // send shared flag
132         buf[0] = 1;
133         write(vnc_sock, buf, 1);
134
135         // read the server initialization
136         if (read(vnc_sock, &si, sizeof(struct ServerInitialization)) != sizeof(struct ServerInitialization))
137                 error("short read on SI");
138
139         printf("Server is %u x %u\n", ntohs(si.width), ntohs(si.height));
140
141         if (read(vnc_sock, buf, ntohl(si.name_len)) != ntohl(si.name_len))
142                 error("short read on server name\n");
143
144         printf("Server name is '%*s' (%u bytes)\n", ntohl(si.name_len), buf, ntohl(si.name_len));
145
146         // we can only accept raw encoding
147         buf[0] = 2; // message type
148         buf[1] = 0; // padding
149         buf[2] = 0; // number of encodings
150         buf[3] = 1;
151         buf[4] = 0; // raw encoding
152         buf[5] = 0; 
153         buf[6] = 0;
154         buf[7] = 0;
155
156         write(vnc_sock, buf, 8);
157         
158         // request the entire framebuffer
159         buf[0] = 3; // message type
160         buf[1] = 0; // incremental
161         buf[2] = 0; // xpos
162         buf[3] = 0;
163         buf[4] = 0; // ypos
164         buf[5] = 0;
165         buf[6] = 640 >> 8; // width
166         buf[7] = 640 % 0xff;
167         buf[8] = 480 >> 8; // height
168         buf[9] = 480 % 0xff;
169
170         write(vnc_sock, buf, 10);
171         
172         printf("Connected to VNC!\n");
173
174         return vnc_sock;
175 }
176
177 int serve_client()
178 {
179         int vnc_sock = vnc_init();
180         
181         if (!mcs_recv_connect_initial())
182                 error("MCS_CONNECT_INITIAL recv failed");
183         mcs_send_connect_response();
184
185         for ( ;; ) {
186                 uint8 type, data_pdu_type;
187                 STREAM s;
188
189                 fd_set readfs;
190                 FD_ZERO(&readfs);
191                 FD_SET(tcp_get_socket(), &readfs);
192                 FD_SET(vnc_sock, &readfs);
193                 
194                 select(FD_SETSIZE, &readfs, NULL, NULL, NULL);
195
196                 // activity on RDP socket?
197                 if (FD_ISSET(tcp_get_socket(), &readfs)) {
198                         if ((s = rdp_recv(&type)) != NULL) {
199                                 if (type != RDP_PDU_DATA) {
200                                         printf("Unknown RDP packet of type %u\n", type);
201                                         continue;
202                                 }
203
204                                 in_uint8s(s, 8);        /* shareid, pad, streamid, length */
205                                 in_uint8(s, data_pdu_type);
206                                 in_uint8s(s, 3);        /* compress_type, compress_len */
207
208                                 switch (data_pdu_type) {
209                                 case RDP_DATA_PDU_INPUT:
210                                         printf("Input PDU\n");
211                                         handle_input_pdu(s);
212                                         break;
213                                 default:
214                                         printf("Unknown data PDU type %u\n", data_pdu_type);
215                                 };
216                         }
217                 }
218
219                 // activity on VNC socket?
220                 if (FD_ISSET(vnc_sock, &readfs)) {
221                         unsigned char buf[256];
222
223                         printf("Activity on VNC socket!\n");
224                         
225                         read(vnc_sock, buf, 1);
226                         switch (buf[0]) {
227                         case 0:
228                                 // frame buffer update!
229                                 printf("Frame buffer update\n");
230                                 break;
231                         default:
232                                 printf("Unknown server message %x\n", buf[0]);
233                                 exit(1);
234                         }
235                 }
236         }
237 }