rename esc to cmd to avoid confusion
[fbvnc.git] / vncproto.c
blobf99926fb732f53e7c1ca5ba252688ba7cdabcc61
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10 #include <netdb.h>
11 #include <pwd.h>
12 #include <string.h>
14 #include "config.h"
15 #include "draw.h"
16 #include "fbvnc.h"
18 #define MAXRESOL (1 << 21)
20 /* vnc part */
21 static CARD16 cols = 0;
22 static CARD16 rows = 0;
24 /* and buffer for screen updates */
25 static CARD8 updates[MAXRESOL];
26 static int redraw;
28 int vncproto_init(char * addr, int port)
30 struct sockaddr_in si;
31 rfbProtocolVersionMsg vmsg;
32 rfbClientInitMsg clientinit;
33 rfbServerInitMsg serverinit;
34 rfbSetPixelFormatMsg pixformmsg;
35 struct hostent * he;
36 int servsock, i;
37 CARD32 i32;
38 CARD8 x;
39 #if 0
40 CARD8 passwd[128];
41 #endif
42 rfbSetEncodingsMsg * encodingsmsgp;
44 encodingsmsgp = (rfbSetEncodingsMsg *)malloc(sizeof(rfbSetEncodingsMsg)+sizeof(CARD32));
45 if (encodingsmsgp == NULL) {
46 perror("malloc: Cannot initiate communication");
47 return -1;
50 si.sin_family = AF_INET;
51 si.sin_port = htons(port);
52 he = gethostbyname(addr);
53 if (he)
54 si.sin_addr.s_addr = *((unsigned long *)(he->h_addr));
55 else if (inet_aton(addr, &(si.sin_addr)) < 0) {
56 fprintf(stderr, "Cannot resolve hostname");
57 return -1;
60 servsock = socket(PF_INET, SOCK_STREAM, 0);
61 if (servsock == -1) {
62 perror("Cannot create socket");
63 return -1;
65 if (connect(servsock, (struct sockaddr *)&si, sizeof(si)) < 0) {
66 perror("Cannot connect");
67 close(servsock);
68 return -1;
70 sprintf(vmsg, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
71 write(servsock, vmsg, sz_rfbProtocolVersionMsg);
72 read(servsock, vmsg, sz_rfbProtocolVersionMsg);
74 i32 = rfbConnFailed;
75 read(servsock, &i32, sizeof(i32));
76 i32 = ntohl(i32);
78 switch(i32) {
79 case rfbConnFailed: /* conn failed */
80 puts("Remote server says: Connection failed");
81 i32 = 0;
82 read(servsock, &i32, sizeof(i32));
83 while (i32-- && (read(servsock, &x, sizeof(x))==sizeof(x)))
84 printf ("%c", x);
85 puts("");
86 close(servsock);
87 return -1;
88 case rfbNoAuth:
89 break;
90 case rfbVncAuth:
91 puts ("We don't support DES yet");
92 close(servsock);
93 return -1;
94 #if 0
95 p = getpass("Enter password: ");
96 if (!p) {
97 close(servsock);
98 return -1;
100 #endif
103 /* ClientInitialisation */
104 clientinit.shared = 1; /* share */
105 write(servsock, &clientinit, sizeof(clientinit));
107 read(servsock, &serverinit, sizeof(serverinit));
109 fb_init();
110 cols = ntohs(serverinit.framebufferWidth);
111 if (cols > fb_cols())
112 cols = fb_cols();
113 rows = ntohs(serverinit.framebufferHeight);
114 if (rows > fb_rows())
115 rows = fb_rows();
117 i32 = ntohl(serverinit.nameLength);
118 for (i=0; i<i32; i++)
119 read(servsock, &x, 1);
121 pixformmsg.type = rfbSetPixelFormat;
122 pixformmsg.format.bitsPerPixel = 8;
123 pixformmsg.format.depth = 8;
124 pixformmsg.format.bigEndian = 0; /* don't care */
125 pixformmsg.format.trueColour = 1;
127 pixformmsg.format.redMax = htons(3);
128 pixformmsg.format.greenMax = htons(7);
129 pixformmsg.format.blueMax = htons(7);
131 pixformmsg.format.redShift = 0;
132 pixformmsg.format.greenShift = 2;
133 pixformmsg.format.blueShift = 5;
135 write(servsock, &pixformmsg, sizeof(pixformmsg));
137 encodingsmsgp->type = rfbSetEncodings;
138 encodingsmsgp->nEncodings = htons(1);
139 *((CARD32 *)((char *) encodingsmsgp +
140 sizeof(rfbSetEncodingsMsg))) = htonl(rfbEncodingRaw);
141 write(servsock, encodingsmsgp, sizeof(*encodingsmsgp)+sizeof(CARD32));
142 return servsock;
145 int vncproto_free(void)
147 fb_free();
148 return 0;
151 int request_vnc_refresh(int fd, int inc)
153 rfbFramebufferUpdateRequestMsg updreq;
154 updreq.type = rfbFramebufferUpdateRequest;
155 updreq.incremental = inc;
156 updreq.x = htons(0);
157 updreq.y = htons(0);
158 updreq.w = htons(cols);
159 updreq.h = htons(rows);
160 write(fd, &updreq, sizeof(updreq));
161 return 0;
164 static void update_fb(CARD8 *buffer, rfbRectangle r)
166 fbval_t slice[1 << 14];
167 int i, j;
168 for (i = 0; i < r.h; i++) {
169 for (j = 0; j < r.w; j++) {
170 unsigned char *p = &buffer[i * r.w + j];
171 slice[j] = fb_color(*p, *p, *p);
173 fb_set(r.y + i, r.x, slice, r.w);
177 int must_redraw(void)
179 int ret = redraw;
180 redraw = 0;
181 return ret;
184 int parse_vnc_in(int fd)
186 rfbFramebufferUpdateRectHeader uprect;
187 rfbServerToClientMsg msg;
188 rfbServerToClientMsg * vomsgp = &msg;
189 int i, j, k;
191 i = read (fd, vomsgp, sizeof(CARD8));
192 if (i != sizeof(CARD8))
193 return -1;
194 switch (vomsgp->type) {
195 case rfbFramebufferUpdate:
196 i = read(fd, (char *) vomsgp + sizeof(CARD8),
197 sizeof(rfbFramebufferUpdateMsg) - sizeof(CARD8));
198 break;
199 case rfbBell:
200 i = read(fd, (char *) vomsgp + sizeof(CARD8),
201 sizeof(rfbBellMsg) - sizeof(CARD8));
202 break;
203 case rfbServerCutText:
204 i = read(fd, (char *) vomsgp + sizeof(CARD8),
205 sizeof(rfbServerCutTextMsg) - sizeof(CARD8));
206 break;
207 default:
208 return -1;
210 switch (vomsgp->type) {
211 case rfbBell:
212 break;
214 case rfbFramebufferUpdate:
215 vomsgp->fu.nRects = ntohs(vomsgp->fu.nRects);
216 for (k=0; k<vomsgp->fu.nRects; k++) {
217 i = read(fd, &uprect, sizeof(uprect));
218 if (i != sizeof(uprect))
219 return -1;
220 uprect.r.x = ntohs(uprect.r.x);
221 uprect.r.y = ntohs(uprect.r.y);
222 uprect.r.w = ntohs(uprect.r.w);
223 uprect.r.h = ntohs(uprect.r.h);
224 if (uprect.r.x >= cols)
225 return -1;
226 if (uprect.r.x + uprect.r.w > cols)
227 return -1;
228 if (uprect.r.y >= rows)
229 return -1;
230 if (uprect.r.y + uprect.r.h > rows)
231 return -1;
232 for (i=0; i < uprect.r.w * uprect.r.h;) {
233 j = read(fd, updates + i,
234 uprect.r.w * uprect.r.h - i);
235 if (j == -1)
236 return 0;
237 i+=j;
239 update_fb(updates, uprect.r);
241 break;
243 return 0;
246 static int mr, mc; /* mouse position */
247 static int cmd; /* command mode */
248 static char mk[] = MOUSEKEYS;
250 static void handle_mouse(int fd, int c)
252 rfbPointerEventMsg me = {rfbPointerEvent, 0, 0, 0};
253 CARD8 mask = 0;
254 switch (strchr(mk, c) - mk) {
255 case 0:
256 mc -= MOUSESPEED;
257 break;
258 case 1:
259 mr += MOUSESPEED;
260 break;
261 case 2:
262 mr -= MOUSESPEED;
263 break;
264 case 3:
265 mc += MOUSESPEED;
266 break;
267 case 4:
268 mask = rfbButton1Mask;
269 break;
270 case 5:
271 mask = rfbButton2Mask;
272 break;
273 case 6:
274 mask = rfbButton3Mask;
275 break;
277 me.y = htons(MAX(0, MIN(rows - 1, mr)));
278 me.x = htons(MAX(0, MIN(cols - 1, mc)));
279 write(fd, &me, sizeof(me));
280 if (mask) {
281 me.buttonMask = mask;
282 write(fd, &me, sizeof(me));
283 me.buttonMask = 0;
284 write(fd, &me, sizeof(me));
288 int parse_kbd_in(int kbdfd, int fd)
290 static rfbKeyEventMsg ke = {rfbKeyEvent};
291 char buf[1024];
292 int i, j;
294 if ((j = read(kbdfd, buf, sizeof(buf))) <= 0 )
295 return -1;
296 for (i = 0; i < j; i++) {
297 int k = -1;
298 if (!cmd) {
299 switch (buf[i]) {
300 case '\x08':
301 k = 0xFF08;
302 break;
303 case '\x09':
304 k = 0xFF09;
305 break;
306 case '\x0d':
307 k = 0xFF0D;
308 break;
309 case CMDKEY:
310 cmd = 1;
311 break;
312 default:
313 k = (unsigned char) buf[i];
315 } else {
316 if (strchr(mk, buf[i])) {
317 handle_mouse(fd, buf[i]);
318 continue;
320 switch(buf[i]) {
321 case CMDKEY:
322 k = (unsigned char) buf[i];
323 break;
324 case 'q':
325 case 'i':
326 cmd = 0;
327 break;
328 case '\x03': /* cmd ^c */
329 return -1;
330 case 'r':
331 case 'L':
332 redraw = 1;
333 break;
336 if (k > 0) {
337 ke.down = 1;
338 ke.key = htonl(k);
339 write(fd, &ke, sizeof(ke));
340 ke.down = 0;
341 write(fd, &ke, sizeof(ke));
344 return 0;