1 /*
2 * This file is called main.c, because it contains most of the new functions
3 * for use with LibVNCServer.
4 *
5 * LibVNCServer (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
6 * Original OSXvnc (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
7 * Original Xvnc (C) 1999 AT&T Laboratories Cambridge.
8 * All Rights Reserved.
9 *
10 * see GPL (latest version) for full details
11 */
12
13 #include "rfb/rfb.h"
14 #include "rfb/rfbregion.h"
15
16 #include <stdarg.h>
17 #include <errno.h>
18
19 #ifndef false
20 #define false 0
21 #define true -1
22 #endif
23
24 #ifdef HAVE_SYS_TYPES_H
25 #include <sys/types.h>
26 #endif
27
28 #ifndef WIN32
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <unistd.h>
32 #endif
33
34 #include <signal.h>
35 #include <time.h>
36
37 #include <glib.h>
38
39 int rfbEnableLogging=1;
40
41 #ifdef WORDS_BIGENDIAN
42 char rfbEndianTest = 0;
43 #else
44 char rfbEndianTest = -1;
45 #endif
46
rfbLogEnable(int enabled)47 void rfbLogEnable(int enabled) {
48 rfbEnableLogging=enabled;
49 }
50
51 /*
52 * rfbLog prints a time-stamped message to the log file (stderr).
53 */
54
55 static void rfbDefaultLog(const char *format, ...) G_GNUC_PRINTF (1, 2);
56
57 static void
rfbDefaultLog(const char * format,...)58 rfbDefaultLog(const char *format, ...)
59 {
60 va_list args;
61 char buf[256];
62 time_t log_clock;
63
64 if(!rfbEnableLogging)
65 return;
66
67 LOCK(logMutex);
68 va_start(args, format);
69
70 time(&log_clock);
71 strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
72 fprintf(stderr, "%s", buf);
73
74 vfprintf(stderr, format, args);
75 fflush(stderr);
76
77 va_end(args);
78 UNLOCK(logMutex);
79 }
80
81 rfbLogProc rfbLog=rfbDefaultLog;
82 rfbLogProc rfbErr=rfbDefaultLog;
83
rfbLogPerror(const char * str)84 void rfbLogPerror(const char *str)
85 {
86 rfbErr("%s: %s\n", str, strerror(errno));
87 }
88
rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)89 void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
90 {
91 rfbClientIteratorPtr iterator;
92 rfbClientPtr cl;
93
94 iterator=rfbGetClientIterator(rfbScreen);
95 while((cl=rfbClientIteratorNext(iterator))) {
96 LOCK(cl->updateMutex);
97 if(cl->useCopyRect) {
98 sraRegionPtr modifiedRegionBackup;
99 if(!sraRgnEmpty(cl->copyRegion)) {
100 if(cl->copyDX!=dx || cl->copyDY!=dy) {
101 /* if a copyRegion was not yet executed, treat it as a
102 * modifiedRegion. The idea: in this case it could be
103 * source of the new copyRect or modified anyway. */
104 sraRgnOr(cl->modifiedRegion,cl->copyRegion);
105 sraRgnMakeEmpty(cl->copyRegion);
106 } else {
107 /* we have to set the intersection of the source of the copy
108 * and the old copy to modified. */
109 modifiedRegionBackup=sraRgnCreateRgn(copyRegion);
110 sraRgnOffset(modifiedRegionBackup,-dx,-dy);
111 sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
112 sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
113 sraRgnDestroy(modifiedRegionBackup);
114 }
115 }
116
117 sraRgnOr(cl->copyRegion,copyRegion);
118 cl->copyDX = dx;
119 cl->copyDY = dy;
120
121 /* if there were modified regions, which are now copied,
122 * mark them as modified, because the source of these can be overlapped
123 * either by new modified or now copied regions. */
124 modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion);
125 sraRgnOffset(modifiedRegionBackup,dx,dy);
126 sraRgnAnd(modifiedRegionBackup,cl->copyRegion);
127 sraRgnOr(cl->modifiedRegion,modifiedRegionBackup);
128 sraRgnDestroy(modifiedRegionBackup);
129
130 #if 0
131 /* TODO: is this needed? Or does it mess up deferring? */
132 /* while(!sraRgnEmpty(cl->copyRegion)) */ {
133 {
134 sraRegionPtr updateRegion = sraRgnCreateRgn(cl->modifiedRegion);
135 sraRgnOr(updateRegion,cl->copyRegion);
136 UNLOCK(cl->updateMutex);
137 rfbSendFramebufferUpdate(cl,updateRegion);
138 sraRgnDestroy(updateRegion);
139 continue;
140 }
141 }
142 #endif
143 } else {
144 sraRgnOr(cl->modifiedRegion,copyRegion);
145 }
146 UNLOCK(cl->updateMutex);
147 }
148
149 rfbReleaseClientIterator(iterator);
150 }
151
rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)152 void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy)
153 {
154 sraRectangleIterator* i;
155 sraRect rect;
156 int j,widthInBytes,bpp=rfbScreen->rfbServerFormat.bitsPerPixel/8,
157 rowstride=rfbScreen->paddedWidthInBytes;
158 char *in,*out;
159
160 /* copy it, really */
161 i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0);
162 while(sraRgnIteratorNext(i,&rect)) {
163 widthInBytes = (rect.x2-rect.x1)*bpp;
164 out = rfbScreen->frameBuffer+rect.x1*bpp+rect.y1*rowstride;
165 in = rfbScreen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride;
166 if(dy<0)
167 for(j=rect.y1;j<rect.y2;j++,out+=rowstride,in+=rowstride)
168 memmove(out,in,widthInBytes);
169 else {
170 out += rowstride*(rect.y2-rect.y1-1);
171 in += rowstride*(rect.y2-rect.y1-1);
172 for(j=rect.y2-1;j>=rect.y1;j--,out-=rowstride,in-=rowstride)
173 memmove(out,in,widthInBytes);
174 }
175 }
176
177 rfbScheduleCopyRegion(rfbScreen,copyRegion,dx,dy);
178 }
179
rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)180 void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)
181 {
182 sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
183 rfbDoCopyRegion(rfbScreen,region,dx,dy);
184 }
185
rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)186 void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy)
187 {
188 sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2);
189 rfbScheduleCopyRegion(rfbScreen,region,dx,dy);
190 }
191
rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)192 void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion)
193 {
194 rfbClientIteratorPtr iterator;
195 rfbClientPtr cl;
196
197 iterator=rfbGetClientIterator(rfbScreen);
198 while((cl=rfbClientIteratorNext(iterator))) {
199 LOCK(cl->updateMutex);
200 sraRgnOr(cl->modifiedRegion,modRegion);
201 UNLOCK(cl->updateMutex);
202 }
203
204 rfbReleaseClientIterator(iterator);
205 }
206
rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2)207 void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2)
208 {
209 sraRegionPtr region;
210 int i;
211
212 if(x1>x2) { i=x1; x1=x2; x2=i; }
213 if(x1<0) x1=0;
214 if(x2>=rfbScreen->width) x2=rfbScreen->width-1;
215 if(x1==x2) return;
216
217 if(y1>y2) { i=y1; y1=y2; y2=i; }
218 if(y1<0) y1=0;
219 if(y2>=rfbScreen->height) y2=rfbScreen->height-1;
220 if(y1==y2) return;
221
222 region = sraRgnCreateRect(x1,y1,x2,y2);
223 rfbMarkRegionAsModified(rfbScreen,region);
224 sraRgnDestroy(region);
225 }
226
227 void
defaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl)228 defaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
229 {
230 rfbSetCursorPosition(cl->screen, cl, x, y);
231 }
232
233 /* TODO: add a nice VNC or RFB cursor */
234
235 #if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI)
236 static rfbCursor myCursor =
237 {
238 FALSE, FALSE, FALSE, FALSE,
239 (unsigned char*)"\000\102\044\030\044\102\000",
240 (unsigned char*)"\347\347\176\074\176\347\347",
241 8, 7, 3, 3,
242 0, 0, 0,
243 0xffff, 0xffff, 0xffff,
244 0
245 };
246 #else
247 static rfbCursor myCursor =
248 {
249 cleanup: FALSE,
250 cleanupSource: FALSE,
251 cleanupMask: FALSE,
252 cleanupRichSource: FALSE,
253 source: "\000\102\044\030\044\102\000",
254 mask: "\347\347\176\074\176\347\347",
255 width: 8, height: 7, xhot: 3, yhot: 3,
256 foreRed: 0, foreGreen: 0, foreBlue: 0,
257 backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
258 richSource: 0
259 };
260 #endif
261
262 /*
263 * Update server's pixel format in rfbScreenInfo structure. This
264 * function is called from rfbGetScreen() and rfbNewFramebuffer().
265 */
266
rfbInitServerFormat(rfbScreenInfoPtr rfbScreen,int bitsPerSample)267 static void rfbInitServerFormat(rfbScreenInfoPtr rfbScreen, int bitsPerSample)
268 {
269 rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
270
271 format->bitsPerPixel = rfbScreen->bitsPerPixel;
272 format->depth = rfbScreen->depth;
273 format->bigEndian = rfbEndianTest?FALSE:TRUE;
274 format->trueColour = TRUE;
275 rfbScreen->colourMap.count = 0;
276 rfbScreen->colourMap.is16 = 0;
277 rfbScreen->colourMap.data.bytes = NULL;
278
279 if (format->bitsPerPixel == 8) {
280 format->redMax = 7;
281 format->greenMax = 7;
282 format->blueMax = 3;
283 format->redShift = 0;
284 format->greenShift = 3;
285 format->blueShift = 6;
286 } else {
287 format->redMax = (1 << bitsPerSample) - 1;
288 format->greenMax = (1 << bitsPerSample) - 1;
289 format->blueMax = (1 << bitsPerSample) - 1;
290 if(rfbEndianTest) {
291 format->redShift = 0;
292 format->greenShift = bitsPerSample;
293 format->blueShift = bitsPerSample * 2;
294 } else {
295 if(format->bitsPerPixel==8*3) {
296 format->redShift = bitsPerSample*2;
297 format->greenShift = bitsPerSample*1;
298 format->blueShift = 0;
299 } else {
300 format->redShift = bitsPerSample*3;
301 format->greenShift = bitsPerSample*2;
302 format->blueShift = bitsPerSample;
303 }
304 }
305 }
306 }
307
rfbGetScreen(int * argc,char ** argv,int width,int height,int bitsPerSample,int samplesPerPixel,int bytesPerPixel)308 rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
309 int width,int height,int bitsPerSample,int samplesPerPixel,
310 int bytesPerPixel)
311 {
312 rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo));
313
314 if(width&3)
315 rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
316
317 rfbScreen->autoPort=FALSE;
318 rfbScreen->localOnly=FALSE;
319 rfbScreen->rfbClientHead=0;
320 rfbScreen->rfbPort=5900;
321 rfbScreen->socketInitDone=FALSE;
322
323 rfbScreen->inetdInitDone = FALSE;
324 rfbScreen->inetdSock=-1;
325
326 rfbScreen->maxFd=0;
327
328 rfbScreen->rfbListenSock[0] = -1;
329 rfbScreen->rfbListenSockTotal = 0;
330 rfbScreen->netIface = NULL;
331
332 rfbScreen->desktopName = strdup("LibVNCServer");
333 rfbScreen->rfbAlwaysShared = FALSE;
334 rfbScreen->rfbNeverShared = FALSE;
335 rfbScreen->rfbDontDisconnect = FALSE;
336
337 rfbScreen->width = width;
338 rfbScreen->height = height;
339 rfbScreen->bitsPerPixel = rfbScreen->depth = 8*bytesPerPixel;
340
341 rfbScreen->securityTypes[0] = rfbNoAuth;
342 rfbScreen->nSecurityTypes = 0;
343 rfbScreen->authTypes[0] = rfbNoAuth;
344 rfbScreen->nAuthTypes = 0;
345 rfbScreen->passwordCheck = NULL;
346
347 #ifdef WIN32
348 {
349 DWORD dummy=255;
350 GetComputerName(rfbScreen->rfbThisHost,&dummy);
351 }
352 #else
353 gethostname(rfbScreen->rfbThisHost, 255);
354 #endif
355
356 rfbScreen->paddedWidthInBytes = width*bytesPerPixel;
357
358 /* format */
359
360 rfbInitServerFormat(rfbScreen, bitsPerSample);
361
362 /* cursor */
363
364 rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0;
365 rfbScreen->underCursorBuffer=NULL;
366 rfbScreen->cursor = &myCursor;
367
368 rfbScreen->rfbDeferUpdateTime=5;
369 rfbScreen->maxRectsPerUpdate=50;
370
371 /* proc's and hook's */
372
373 rfbScreen->kbdAddEvent = NULL;
374 rfbScreen->ptrAddEvent = defaultPtrAddEvent;
375 rfbScreen->setXCutText = NULL;
376 rfbScreen->newClientHook = NULL;
377 rfbScreen->authenticatedClientHook = NULL;
378
379 /* initialize client list and iterator mutex */
380 rfbClientListInit(rfbScreen);
381
382 rfbAuthInitScreen(rfbScreen);
383
384 return(rfbScreen);
385 }
386
387 /*
388 * Switch to another sized framebuffer. Clients supporting NewFBSize
389 * pseudo-encoding will change their local framebuffer dimensions
390 * if necessary.
391 * NOTE: Rich cursor data should be converted to new pixel format by
392 * the caller.
393 */
394
rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char * framebuffer,int width,int height)395 void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen, char *framebuffer,
396 int width, int height)
397 {
398 rfbClientIteratorPtr iterator;
399 rfbClientPtr cl;
400
401 if (width & 3)
402 rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width);
403
404 /* Update information in the rfbScreenInfo structure */
405
406 rfbScreen->width = width;
407 rfbScreen->height = height;
408 rfbScreen->frameBuffer = framebuffer;
409
410 /* Adjust pointer position if necessary */
411
412 if (rfbScreen->cursorX >= width)
413 rfbScreen->cursorX = width - 1;
414 if (rfbScreen->cursorY >= height)
415 rfbScreen->cursorY = height - 1;
416
417 /* For each client: */
418 iterator = rfbGetClientIterator(rfbScreen);
419 while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
420
421 /* Mark the screen contents as changed, and schedule sending
422 NewFBSize message if supported by this client. */
423
424 LOCK(cl->updateMutex);
425 sraRgnDestroy(cl->modifiedRegion);
426 cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
427 sraRgnMakeEmpty(cl->copyRegion);
428 cl->copyDX = 0;
429 cl->copyDY = 0;
430
431 if (cl->useNewFBSize)
432 cl->newFBSizePending = TRUE;
433
434 UNLOCK(cl->updateMutex);
435 }
436 rfbReleaseClientIterator(iterator);
437 }
438
rfbSetDesktopName(rfbScreenInfoPtr rfbScreen,const char * name)439 void rfbSetDesktopName(rfbScreenInfoPtr rfbScreen, const char *name)
440 {
441 if (rfbScreen->desktopName)
442 free(rfbScreen->desktopName);
443 rfbScreen->desktopName = strdup(name);
444 }
445
rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)446 void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)
447 {
448 rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen);
449 rfbClientPtr cl,cl1=rfbClientIteratorNext(i);
450 while(cl1) {
451 cl=rfbClientIteratorNext(i);
452 rfbClientConnectionGone(cl1);
453 cl1=cl;
454 }
455 rfbReleaseClientIterator(i);
456
457 rfbAuthCleanupScreen(rfbScreen);
458
459 /* TODO: hang up on all clients and free all reserved memory */
460 #define FREE_IF(x) if(rfbScreen->x) free(rfbScreen->x)
461 FREE_IF(colourMap.data.bytes);
462 FREE_IF(underCursorBuffer);
463 if(rfbScreen->cursor)
464 rfbFreeCursor(rfbScreen->cursor);
465 if(rfbScreen->desktopName)
466 free(rfbScreen->desktopName);
467 free(rfbScreen);
468 #ifdef VINO_HAVE_JPEG
469 rfbTightCleanup();
470 #endif
471 }
472
rfbInitServer(rfbScreenInfoPtr rfbScreen)473 void rfbInitServer(rfbScreenInfoPtr rfbScreen)
474 {
475 #ifdef WIN32
476 WSADATA trash;
477 int i=WSAStartup(MAKEWORD(2,2),&trash);
478 #endif
479 rfbInitSockets(rfbScreen);
480 }
481
482 #ifndef HAVE_GETTIMEOFDAY
483 #include <fcntl.h>
484 #include <conio.h>
485 #include <sys/timeb.h>
486
gettimeofday(struct timeval * tv,char * dummy)487 void gettimeofday(struct timeval* tv,char* dummy)
488 {
489 SYSTEMTIME t;
490 GetSystemTime(&t);
491 tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond;
492 tv->tv_usec=t.wMilliseconds*1000;
493 }
494 #endif
495
496 void
rfbUpdateClient(rfbClientPtr cl)497 rfbUpdateClient(rfbClientPtr cl)
498 {
499 struct timeval tv;
500
501 if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) &&
502 !sraRgnEmpty(cl->requestedRegion)) {
503 if(cl->screen->rfbDeferUpdateTime == 0) {
504 rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
505 } else if(cl->startDeferring.tv_usec == 0) {
506 gettimeofday(&cl->startDeferring,NULL);
507 if(cl->startDeferring.tv_usec == 0)
508 cl->startDeferring.tv_usec++;
509 } else {
510 gettimeofday(&tv,NULL);
511 if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */
512 || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000
513 +(tv.tv_usec-cl->startDeferring.tv_usec)/1000)
514 > cl->screen->rfbDeferUpdateTime) {
515 cl->startDeferring.tv_usec = 0;
516 rfbSendFramebufferUpdate(cl,cl->modifiedRegion);
517 }
518 }
519 }
520 }
521
522 void
rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)523 rfbProcessEvents(rfbScreenInfoPtr rfbScreen,long usec)
524 {
525 rfbClientIteratorPtr i;
526 rfbClientPtr cl,clPrev;
527
528 if(usec<0)
529 usec=rfbScreen->rfbDeferUpdateTime*1000;
530
531 rfbCheckFds(rfbScreen,usec);
532
533 i = rfbGetClientIterator(rfbScreen);
534 cl=rfbClientIteratorHead(i);
535 while(cl) {
536 rfbUpdateClient(cl);
537 clPrev=cl;
538 cl=rfbClientIteratorNext(i);
539 if(clPrev->sock==-1)
540 rfbClientConnectionGone(clPrev);
541 }
542 rfbReleaseClientIterator(i);
543 }
544
rfbRunEventLoop(rfbScreenInfoPtr rfbScreen,long usec,rfbBool runInBackground)545 void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, rfbBool runInBackground)
546 {
547 if(runInBackground) {
548 rfbErr("Can't run in background, because I don't have PThreads!\n");
549 return;
550 }
551
552 if(usec<0)
553 usec=rfbScreen->rfbDeferUpdateTime*1000;
554
555 while(1)
556 rfbProcessEvents(rfbScreen,usec);
557 }
558
559 static char *
securityTypeToName(int securityType)560 securityTypeToName(int securityType)
561 {
562 switch (securityType) {
563 case rfbNoAuth:
564 return "No Authentication";
565 case rfbVncAuth:
566 return "VNC Authentication";
567 #ifdef VINO_HAVE_GNUTLS
568 case rfbTLS:
569 return "TLS";
570 #endif
571 default:
572 return "unknown";
573 }
574 }
575
rfbAddSecurityType(rfbScreenInfoPtr rfbScreen,int securityType)576 void rfbAddSecurityType(rfbScreenInfoPtr rfbScreen, int securityType)
577 {
578 if (rfbScreen->nSecurityTypes >= RFB_MAX_N_SECURITY_TYPES)
579 return;
580
581 rfbLog("Advertising security type: '%s' (%d)\n",
582 securityTypeToName(securityType), securityType);
583
584 switch (securityType) {
585 case rfbNoAuth:
586 case rfbVncAuth:
587 #ifdef VINO_HAVE_GNUTLS
588 case rfbTLS:
589 #endif
590 rfbScreen->securityTypes[rfbScreen->nSecurityTypes] = securityType;
591 rfbScreen->nSecurityTypes++;
592 break;
593 default:
594 break;
595 }
596 }
597
rfbClearSecurityTypes(rfbScreenInfoPtr rfbScreen)598 void rfbClearSecurityTypes(rfbScreenInfoPtr rfbScreen)
599 {
600 if (rfbScreen->nSecurityTypes > 0) {
601 rfbLog("Clearing securityTypes\n");
602
603 memset (&rfbScreen->securityTypes, 0, sizeof (rfbScreen->securityTypes));
604 rfbScreen->securityTypes [0] = rfbNoAuth;
605 rfbScreen->nSecurityTypes = 0;
606 }
607 }
608
609 static char *
authTypeToName(int authType)610 authTypeToName(int authType)
611 {
612 switch (authType) {
613 case rfbNoAuth:
614 return "No Authentication";
615 case rfbVncAuth:
616 return "VNC Authentication";
617 default:
618 return "unknown";
619 }
620 }
621
rfbAddAuthType(rfbScreenInfoPtr rfbScreen,int authType)622 void rfbAddAuthType(rfbScreenInfoPtr rfbScreen, int authType)
623 {
624 if (rfbScreen->nAuthTypes >= RFB_MAX_N_AUTH_TYPES)
625 return;
626
627 rfbLog("Advertising authentication type: '%s' (%d)\n",
628 authTypeToName(authType), authType);
629
630 switch (authType) {
631 case rfbNoAuth:
632 case rfbVncAuth:
633 rfbScreen->authTypes[rfbScreen->nAuthTypes] = authType;
634 rfbScreen->nAuthTypes++;
635 break;
636 default:
637 break;
638 }
639 }
640
rfbClearAuthTypes(rfbScreenInfoPtr rfbScreen)641 void rfbClearAuthTypes(rfbScreenInfoPtr rfbScreen)
642 {
643 if (rfbScreen->nAuthTypes > 0) {
644 rfbLog("Clearing authTypes\n");
645
646 memset (&rfbScreen->authTypes, 0, sizeof (rfbScreen->authTypes));
647 rfbScreen->authTypes [0] = rfbNoAuth;
648 rfbScreen->nAuthTypes = 0;
649 }
650 }
651