Basic connection to VNC added (read width and height, mostly).
[rdpsrv] / rdpsrv.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <sys/socket.h>
6 #include <sys/ioctl.h>
7 #include <arpa/inet.h>
8
9 #include "rdesktop.h"
10
11 const int tcp_port_rdp = 3389;
12 int create_server_socket();
13 int serve_client();
14
15 int main()
16 {
17         int server_sock = create_server_socket();
18         for ( ;; ) {
19                 iso_recv_connect(server_sock);
20                 printf("Got connection.\n");
21                 serve_client();
22                 printf("Client closed.\n");
23         }
24 }
25
26 int create_server_socket()
27 {
28         int server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
29         const unsigned int one = 1, zero = 0;
30         struct sockaddr_in addr;
31         int err;
32
33         setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
34         ioctl(server_sock, FIONBIO, &zero);
35
36         addr.sin_family = AF_INET;
37         addr.sin_addr.s_addr = INADDR_ANY;
38         addr.sin_port = htons(tcp_port_rdp);
39
40         do {
41                 err = bind(server_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
42
43                 if (err == -1) {
44                         perror("bind()");
45
46                         /* try to recover from recoverable errors... */
47                         if (errno == ENOMEM || errno == EADDRINUSE) {
48                                 puts("Waiting 1 sec before trying again...");
49                                 sleep(1);
50                         } else {
51                                 puts("Giving up.");
52                                 exit(1);
53                         }
54                 }
55         } while (err == -1);
56
57         listen(server_sock, 20);
58         return server_sock;
59 }
60
61 void handle_input_pdu(STREAM s)
62 {
63         uint32 time;
64         uint16 message_type, device_flags, param1, param2;
65         uint16 num_events;
66         int i;
67
68         in_uint16_le(s, num_events);   // number of events
69         in_uint8s(s, 2);        // pad
70
71         for (i = 0; i < num_events; ++i) {
72                 rdp_recv_input(s, &time, &message_type, &device_flags, &param1, &param2);
73                 printf("Input event at time %u\n", time);
74                 
75                 switch (message_type) {
76                 case RDP_INPUT_SYNCHRONIZE:
77                         printf("- Type: Synchronize (ignored)\n");
78                         break;
79                 case RDP_INPUT_CODEPOINT:
80                         printf("- Type: Codepoint (ignored)\n");
81                         break;
82                 case RDP_INPUT_VIRTKEY:
83                         printf("- Type: Virtual key (ignored)\n");
84                         break;
85                 case RDP_INPUT_SCANCODE:
86                         printf("- Type: Scancode (ignored)\n");
87                         break;
88                 case RDP_INPUT_MOUSE:
89                         printf("- Type: Mouse\n");
90                         printf("- Device flags: %x\n", device_flags);
91                         printf("- Position: (%u,%u)\n", param1, param2);
92
93                         // debug
94                         rdp_send_bitmap_update(param1, param2);
95                         
96                         break;
97                 default:
98                         printf("- Unknown type %x\n", message_type);
99                         break;
100                 }
101                 printf("\n");
102         }
103 }
104
105 struct ServerInitialization {
106         unsigned short width;
107         unsigned short height;
108         unsigned char pixelformat[16]; // FIXME
109         unsigned int name_len;
110 };
111
112 int vnc_init()
113 {
114         char buf[256];
115         int vnc_sock = tcp_connect("127.0.0.1", 5901);
116         struct ServerInitialization si;
117
118         // get handshake
119         if (read(vnc_sock, buf, 12) != 12)
120                 error("short read on handshake\n");
121         write(vnc_sock, "RFB 003.003\n", 12);
122
123         // get auth
124         if (read(vnc_sock, buf, 4) != 4)
125                 error("short read on auth\n");
126
127         if (buf[3] != 1)
128                 error("auth needed or connection failed\n");
129
130         // send shared flag
131         buf[0] = 1;
132         write(vnc_sock, buf, 1);
133
134         // read the server initialization
135         if (read(vnc_sock, &si, sizeof(struct ServerInitialization)) != sizeof(struct ServerInitialization))
136                 error("short read on SI");
137
138         printf("Server is %u x %u\n", ntohs(si.width), ntohs(si.height));
139
140         if (read(vnc_sock, buf, si.name_len) != si.name_len)
141                 error("short read on server name");
142
143         printf("Server name is '%*s'\n", si.name_len, buf);
144         
145         printf("Connected to VNC!\n");
146
147         return vnc_sock;
148 }
149
150 int serve_client()
151 {
152         int vnc_sock = vnc_init();
153         
154         if (!mcs_recv_connect_initial())
155                 error("MCS_CONNECT_INITIAL recv failed");
156         mcs_send_connect_response();
157
158         for ( ;; ) {
159                 uint8 type, data_pdu_type;
160                 STREAM s;
161
162                 while ((s = rdp_recv(&type)) != NULL) {
163                         if (type != RDP_PDU_DATA) {
164                                 printf("Unknown RDP packet of type %u\n", type);
165                                 continue;
166                         }
167
168                         in_uint8s(s, 8);        /* shareid, pad, streamid, length */
169                         in_uint8(s, data_pdu_type);
170                         in_uint8s(s, 3);        /* compress_type, compress_len */
171
172                         switch (data_pdu_type) {
173                         case RDP_DATA_PDU_INPUT:
174                                 printf("Input PDU\n");
175                                 handle_input_pdu(s);
176                                 break;
177                         default:
178                                 printf("Unknown data PDU type %u\n", data_pdu_type);
179                         };
180                 }
181         }
182 }