vncproto: add MOUSESPEED macro
[fbvnc.git] / vncproto.c
blob791f9aa905e4abd7cbe5ef61751e1e7ff0c34615
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 "fbvnc.h"
15 #include "draw.h"
17 #define MAXRESOL (1 << 21)
19 /* vnc part */
20 static CARD16 cols = 0;
21 static CARD16 rows = 0;
23 /* and buffer for screen updates */
24 static CARD8 updates[MAXRESOL];
25 static int redraw;
27 int vncproto_init(char * addr, int port)
29 struct sockaddr_in si;
30 rfbProtocolVersionMsg vmsg;
31 rfbClientInitMsg clientinit;
32 rfbServerInitMsg serverinit;
33 rfbSetPixelFormatMsg pixformmsg;
34 struct hostent * he;
35 int servsock, i;
36 CARD32 i32;
37 CARD8 x;
38 #if 0
39 CARD8 passwd[128];
40 #endif
41 rfbSetEncodingsMsg * encodingsmsgp;
43 encodingsmsgp = (rfbSetEncodingsMsg *)malloc(sizeof(rfbSetEncodingsMsg)+sizeof(CARD32));
44 if (encodingsmsgp == NULL) {
45 perror("malloc: Cannot initiate communication");
46 return -1;
49 si.sin_family = AF_INET;
50 si.sin_port = htons(port);
51 he = gethostbyname(addr);
52 if (he)
53 si.sin_addr.s_addr = *((unsigned long *)(he->h_addr));
54 else if (inet_aton(addr, &(si.sin_addr)) < 0) {
55 fprintf(stderr, "Cannot resolve hostname");
56 return -1;
59 servsock = socket(PF_INET, SOCK_STREAM, 0);
60 if (servsock == -1) {
61 perror("Cannot create socket");
62 return -1;
64 if (connect(servsock, (struct sockaddr *)&si, sizeof(si)) < 0) {
65 perror("Cannot connect");
66 close(servsock);
67 return -1;
69 sprintf(vmsg, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
70 write(servsock, vmsg, sz_rfbProtocolVersionMsg);
71 read(servsock, vmsg, sz_rfbProtocolVersionMsg);
73 i32 = rfbConnFailed;
74 read(servsock, &i32, sizeof(i32));
75 i32 = ntohl(i32);
77 switch(i32) {
78 case rfbConnFailed: /* conn failed */
79 puts("Remote server says: Connection failed");
80 i32 = 0;
81 read(servsock, &i32, sizeof(i32));
82 while (i32-- && (read(servsock, &x, sizeof(x))==sizeof(x)))
83 printf ("%c", x);
84 puts("");
85 close(servsock);
86 return -1;
87 case rfbNoAuth:
88 break;
89 case rfbVncAuth:
90 puts ("We don't support DES yet");
91 close(servsock);
92 return -1;
93 #if 0
94 p = getpass("Enter password: ");
95 if (!p) {
96 close(servsock);
97 return -1;
99 #endif
102 /* ClientInitialisation */
103 clientinit.shared = 1; /* share */
104 write(servsock, &clientinit, sizeof(clientinit));
106 read(servsock, &serverinit, sizeof(serverinit));
108 fb_init();
109 cols = ntohs(serverinit.framebufferWidth);
110 if (cols > fb_cols())
111 cols = fb_cols();
112 rows = ntohs(serverinit.framebufferHeight);
113 if (rows > fb_rows())
114 rows = fb_rows();
116 i32 = ntohl(serverinit.nameLength);
117 for (i=0; i<i32; i++)
118 read(servsock, &x, 1);
120 pixformmsg.type = rfbSetPixelFormat;
121 pixformmsg.format.bitsPerPixel = 8;
122 pixformmsg.format.depth = 8;
123 pixformmsg.format.bigEndian = 0; /* don't care */
124 pixformmsg.format.trueColour = 1;
126 pixformmsg.format.redMax = htons(3);
127 pixformmsg.format.greenMax = htons(7);
128 pixformmsg.format.blueMax = htons(7);
130 pixformmsg.format.redShift = 0;
131 pixformmsg.format.greenShift = 2;
132 pixformmsg.format.blueShift = 5;
134 write(servsock, &pixformmsg, sizeof(pixformmsg));
136 encodingsmsgp->type = rfbSetEncodings;
137 encodingsmsgp->nEncodings = htons(1);
138 *((CARD32 *)((char *) encodingsmsgp +
139 sizeof(rfbSetEncodingsMsg))) = htonl(rfbEncodingRaw);
140 write(servsock, encodingsmsgp, sizeof(*encodingsmsgp)+sizeof(CARD32));
141 return servsock;
144 int vncproto_free(void)
146 fb_free();
147 return 0;
150 int request_vnc_refresh(int fd, int inc)
152 rfbFramebufferUpdateRequestMsg updreq;
153 updreq.type = rfbFramebufferUpdateRequest;
154 updreq.incremental = inc;
155 updreq.x = htons(0);
156 updreq.y = htons(0);
157 updreq.w = htons(cols);
158 updreq.h = htons(rows);
159 write(fd, &updreq, sizeof(updreq));
160 return 0;
163 static void update_fb(CARD8 *buffer, rfbRectangle r)
165 fbval_t slice[1 << 14];
166 int i, j;
167 for (i = 0; i < r.h; i++) {
168 for (j = 0; j < r.w; j++) {
169 unsigned char *p = &buffer[i * r.w + j];
170 slice[j] = fb_color(*p, *p, *p);
172 fb_set(r.y + i, r.x, slice, r.w);
176 int must_redraw(void)
178 int ret = redraw;
179 redraw = 0;
180 return ret;
183 int parse_vnc_in(int fd)
185 rfbFramebufferUpdateRectHeader uprect;
186 rfbServerToClientMsg msg;
187 rfbServerToClientMsg * vomsgp = &msg;
188 int i, j, k;
190 i = read (fd, vomsgp, sizeof(CARD8));
191 if (i != sizeof(CARD8))
192 return -1;
193 switch (vomsgp->type) {
194 case rfbFramebufferUpdate:
195 i = read(fd, (char *) vomsgp + sizeof(CARD8),
196 sizeof(rfbFramebufferUpdateMsg) - sizeof(CARD8));
197 break;
198 case rfbBell:
199 i = read(fd, (char *) vomsgp + sizeof(CARD8),
200 sizeof(rfbBellMsg) - sizeof(CARD8));
201 break;
202 case rfbServerCutText:
203 i = read(fd, (char *) vomsgp + sizeof(CARD8),
204 sizeof(rfbServerCutTextMsg) - sizeof(CARD8));
205 break;
206 default:
207 return -1;
209 switch (vomsgp->type) {
210 case rfbBell:
211 break;
213 case rfbFramebufferUpdate:
214 vomsgp->fu.nRects = ntohs(vomsgp->fu.nRects);
215 for (k=0; k<vomsgp->fu.nRects; k++) {
216 i = read(fd, &uprect, sizeof(uprect));
217 if (i != sizeof(uprect))
218 return -1;
219 uprect.r.x = ntohs(uprect.r.x);
220 uprect.r.y = ntohs(uprect.r.y);
221 uprect.r.w = ntohs(uprect.r.w);
222 uprect.r.h = ntohs(uprect.r.h);
223 if (uprect.r.x >= cols)
224 return -1;
225 if (uprect.r.x + uprect.r.w > cols)
226 return -1;
227 if (uprect.r.y >= rows)
228 return -1;
229 if (uprect.r.y + uprect.r.h > rows)
230 return -1;
231 for (i=0; i < uprect.r.w * uprect.r.h;) {
232 j = read(fd, updates + i,
233 uprect.r.w * uprect.r.h - i);
234 if (j == -1)
235 return 0;
236 i+=j;
238 update_fb(updates, uprect.r);
240 break;
242 return 0;
245 /* escape key */
246 #define ESCKEY '\x1b'
247 /* mouse keys: left, down, up, right, button1, button2, button3 */
248 #define MOUSEKEYS "hjkl\r \t"
249 /* mouse movements in pixels */
250 #define MOUSESPEED 4
252 static int mr, mc; /* mouse position */
253 static int esc; /* escape mode */
254 static char mk[] = MOUSEKEYS;
256 static void handle_mouse(int fd, int c)
258 rfbPointerEventMsg me = {rfbPointerEvent, 0, 0, 0};
259 CARD8 mask = 0;
260 switch (strchr(mk, c) - mk) {
261 case 0:
262 mc -= MOUSESPEED;
263 break;
264 case 1:
265 mr += MOUSESPEED;
266 break;
267 case 2:
268 mr -= MOUSESPEED;
269 break;
270 case 3:
271 mc += MOUSESPEED;
272 break;
273 case 4:
274 mask = rfbButton1Mask;
275 break;
276 case 5:
277 mask = rfbButton2Mask;
278 break;
279 case 6:
280 mask = rfbButton3Mask;
281 break;
283 me.y = htons(MAX(0, MIN(rows - 1, mr)));
284 me.x = htons(MAX(0, MIN(cols - 1, mc)));
285 write(fd, &me, sizeof(me));
286 if (mask) {
287 me.buttonMask = mask;
288 write(fd, &me, sizeof(me));
289 me.buttonMask = 0;
290 write(fd, &me, sizeof(me));
294 int parse_kbd_in(int kbdfd, int fd)
296 static rfbKeyEventMsg ke = {rfbKeyEvent};
297 char buf[1024];
298 int i, j;
300 if ((j = read(kbdfd, buf, sizeof(buf))) <= 0 )
301 return -1;
302 for (i = 0; i < j; i++) {
303 int k = -1;
304 if (!esc) {
305 switch (buf[i]) {
306 case '\x08':
307 k = 0xFF08;
308 break;
309 case '\x09':
310 k = 0xFF09;
311 break;
312 case '\x0d':
313 k = 0xFF0D;
314 break;
315 case ESCKEY:
316 esc = 1;
317 break;
318 default:
319 k = (unsigned char) buf[i];
321 } else {
322 if (strchr(mk, buf[i])) {
323 handle_mouse(fd, buf[i]);
324 continue;
326 switch(buf[i]) {
327 case ESCKEY:
328 k = (unsigned char) buf[i];
329 break;
330 case 'q':
331 case 'i':
332 esc = 0;
333 break;
334 case '\x03': /* esc ^c */
335 return -1;
336 case 'r':
337 case 'L':
338 redraw = 1;
339 break;
342 if (k > 0) {
343 ke.down = 1;
344 ke.key = htonl(k);
345 write(fd, &ke, sizeof(ke));
346 ke.down = 0;
347 write(fd, &ke, sizeof(ke));
350 return 0;