• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
3  *
4  *  This is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This software is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this software; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
17  *  USA.
18  */
19 
20 /*
21  * vncviewer.c - the Xt-based VNC viewer.
22  */
23 
24 #ifdef __STRICT_ANSI__
25 #define _BSD_SOURCE
26 #define _POSIX_SOURCE
27 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <rfb/rfbclient.h>
33 #include "tls.h"
34 
Dummy(rfbClient * client)35 static void Dummy(rfbClient* client) {
36 }
DummyPoint(rfbClient * client,int x,int y)37 static rfbBool DummyPoint(rfbClient* client, int x, int y) {
38   return TRUE;
39 }
DummyRect(rfbClient * client,int x,int y,int w,int h)40 static void DummyRect(rfbClient* client, int x, int y, int w, int h) {
41 }
42 
43 #ifdef __MINGW32__
NoPassword(rfbClient * client)44 static char* NoPassword(rfbClient* client) {
45   return strdup("");
46 }
47 #undef SOCKET
48 #include <winsock2.h>
49 #define close closesocket
50 #else
51 #include <stdio.h>
52 #include <termios.h>
53 #endif
54 
ReadPassword(rfbClient * client)55 static char* ReadPassword(rfbClient* client) {
56 #ifdef __MINGW32__
57 	/* FIXME */
58 	rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n");
59 	return NoPassword(client);
60 #else
61 	int i;
62 	char* p=malloc(9);
63 	struct termios save,noecho;
64 	p[0]=0;
65 	if(tcgetattr(fileno(stdin),&save)!=0) return p;
66 	noecho=save; noecho.c_lflag &= ~ECHO;
67 	if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p;
68 	fprintf(stderr,"Password: ");
69 	i=0;
70 	while(1) {
71 		int c=fgetc(stdin);
72 		if(c=='\n')
73 			break;
74 		if(i<8) {
75 			p[i]=c;
76 			i++;
77 			p[i]=0;
78 		}
79 	}
80 	tcsetattr(fileno(stdin),TCSAFLUSH,&save);
81 	return p;
82 #endif
83 }
MallocFrameBuffer(rfbClient * client)84 static rfbBool MallocFrameBuffer(rfbClient* client) {
85   if(client->frameBuffer)
86     free(client->frameBuffer);
87   client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8);
88   return client->frameBuffer?TRUE:FALSE;
89 }
90 
initAppData(AppData * data)91 static void initAppData(AppData* data) {
92 	data->shareDesktop=TRUE;
93 	data->viewOnly=FALSE;
94 	data->encodingsString="tight zrle ultra copyrect hextile zlib corre rre raw";
95 	data->useBGR233=FALSE;
96 	data->nColours=0;
97 	data->forceOwnCmap=FALSE;
98 	data->forceTrueColour=FALSE;
99 	data->requestedDepth=0;
100 	data->compressLevel=3;
101 	data->qualityLevel=5;
102 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
103 	data->enableJPEG=TRUE;
104 #else
105 	data->enableJPEG=FALSE;
106 #endif
107 	data->useRemoteCursor=FALSE;
108 }
109 
rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel)110 rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
111 			int bytesPerPixel) {
112   rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1);
113   if(!client) {
114     rfbClientErr("Couldn't allocate client structure!\n");
115     return NULL;
116   }
117   initAppData(&client->appData);
118   client->endianTest = 1;
119   client->programName="";
120   client->serverHost=strdup("");
121   client->serverPort=5900;
122 
123   client->destHost = NULL;
124   client->destPort = 5900;
125 
126   client->CurrentKeyboardLedState = 0;
127   client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
128 
129   /* default: use complete frame buffer */
130   client->updateRect.x = -1;
131 
132   client->format.bitsPerPixel = bytesPerPixel*8;
133   client->format.depth = bitsPerSample*samplesPerPixel;
134   client->appData.requestedDepth=client->format.depth;
135   client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE;
136   client->format.trueColour = TRUE;
137 
138   if (client->format.bitsPerPixel == 8) {
139     client->format.redMax = 7;
140     client->format.greenMax = 7;
141     client->format.blueMax = 3;
142     client->format.redShift = 0;
143     client->format.greenShift = 3;
144     client->format.blueShift = 6;
145   } else {
146     client->format.redMax = (1 << bitsPerSample) - 1;
147     client->format.greenMax = (1 << bitsPerSample) - 1;
148     client->format.blueMax = (1 << bitsPerSample) - 1;
149     if(!client->format.bigEndian) {
150       client->format.redShift = 0;
151       client->format.greenShift = bitsPerSample;
152       client->format.blueShift = bitsPerSample * 2;
153     } else {
154       if(client->format.bitsPerPixel==8*3) {
155 	client->format.redShift = bitsPerSample*2;
156 	client->format.greenShift = bitsPerSample*1;
157 	client->format.blueShift = 0;
158       } else {
159 	client->format.redShift = bitsPerSample*3;
160 	client->format.greenShift = bitsPerSample*2;
161 	client->format.blueShift = bitsPerSample;
162       }
163     }
164   }
165 
166   client->bufoutptr=client->buf;
167   client->buffered=0;
168 
169 #ifdef LIBVNCSERVER_HAVE_LIBZ
170   client->raw_buffer_size = -1;
171   client->decompStreamInited = FALSE;
172 
173 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
174   memset(client->zlibStreamActive,0,sizeof(rfbBool)*4);
175   client->jpegSrcManager = NULL;
176 #endif
177 #endif
178 
179   client->HandleCursorPos = DummyPoint;
180   client->SoftCursorLockArea = DummyRect;
181   client->SoftCursorUnlockScreen = Dummy;
182   client->GotFrameBufferUpdate = DummyRect;
183   client->FinishedFrameBufferUpdate = NULL;
184   client->GetPassword = ReadPassword;
185   client->MallocFrameBuffer = MallocFrameBuffer;
186   client->Bell = Dummy;
187   client->CurrentKeyboardLedState = 0;
188   client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint;
189   client->QoS_DSCP = 0;
190 
191   client->authScheme = 0;
192   client->subAuthScheme = 0;
193   client->GetCredential = NULL;
194   client->tlsSession = NULL;
195   client->sock = -1;
196   client->listenSock = -1;
197   client->listenAddress = NULL;
198   client->listen6Sock = -1;
199   client->listen6Address = NULL;
200   client->clientAuthSchemes = NULL;
201   return client;
202 }
203 
rfbInitConnection(rfbClient * client)204 static rfbBool rfbInitConnection(rfbClient* client)
205 {
206   /* Unless we accepted an incoming connection, make a TCP connection to the
207      given VNC server */
208 
209   if (!client->listenSpecified) {
210     if (!client->serverHost)
211       return FALSE;
212     if (client->destHost) {
213       if (!ConnectToRFBRepeater(client,client->serverHost,client->serverPort,client->destHost,client->destPort))
214         return FALSE;
215     } else {
216       if (!ConnectToRFBServer(client,client->serverHost,client->serverPort))
217         return FALSE;
218     }
219   }
220 
221   /* Initialise the VNC connection, including reading the password */
222 
223   if (!InitialiseRFBConnection(client))
224     return FALSE;
225 
226   client->width=client->si.framebufferWidth;
227   client->height=client->si.framebufferHeight;
228   client->MallocFrameBuffer(client);
229 
230   if (!SetFormatAndEncodings(client))
231     return FALSE;
232 
233   if (client->updateRect.x < 0) {
234     client->updateRect.x = client->updateRect.y = 0;
235     client->updateRect.w = client->width;
236     client->updateRect.h = client->height;
237   }
238 
239   if (client->appData.scaleSetting>1)
240   {
241       if (!SendScaleSetting(client, client->appData.scaleSetting))
242           return FALSE;
243       if (!SendFramebufferUpdateRequest(client,
244 			      client->updateRect.x / client->appData.scaleSetting,
245 			      client->updateRect.y / client->appData.scaleSetting,
246 			      client->updateRect.w / client->appData.scaleSetting,
247 			      client->updateRect.h / client->appData.scaleSetting,
248 			      FALSE))
249 	      return FALSE;
250   }
251   else
252   {
253       if (!SendFramebufferUpdateRequest(client,
254 			      client->updateRect.x, client->updateRect.y,
255 			      client->updateRect.w, client->updateRect.h,
256 			      FALSE))
257       return FALSE;
258   }
259 
260   return TRUE;
261 }
262 
rfbInitClient(rfbClient * client,int * argc,char ** argv)263 rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) {
264   int i,j;
265 
266   if(argv && argc && *argc) {
267     if(client->programName==0)
268       client->programName=argv[0];
269 
270     for (i = 1; i < *argc; i++) {
271       j = i;
272       if (strcmp(argv[i], "-listen") == 0) {
273 	listenForIncomingConnections(client);
274 	break;
275       } else if (strcmp(argv[i], "-listennofork") == 0) {
276 	listenForIncomingConnectionsNoFork(client, -1);
277 	break;
278       } else if (strcmp(argv[i], "-play") == 0) {
279 	client->serverPort = -1;
280 	j++;
281       } else if (i+1<*argc && strcmp(argv[i], "-encodings") == 0) {
282 	client->appData.encodingsString = argv[i+1];
283 	j+=2;
284       } else if (i+1<*argc && strcmp(argv[i], "-compress") == 0) {
285 	client->appData.compressLevel = atoi(argv[i+1]);
286 	j+=2;
287       } else if (i+1<*argc && strcmp(argv[i], "-quality") == 0) {
288 	client->appData.qualityLevel = atoi(argv[i+1]);
289 	j+=2;
290       } else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) {
291         client->appData.scaleSetting = atoi(argv[i+1]);
292         j+=2;
293       } else if (i+1<*argc && strcmp(argv[i], "-qosdscp") == 0) {
294         client->QoS_DSCP = atoi(argv[i+1]);
295         j+=2;
296       } else if (i+1<*argc && strcmp(argv[i], "-repeaterdest") == 0) {
297 	char* colon=strchr(argv[i+1],':');
298 
299 	if(client->destHost)
300 	  free(client->destHost);
301         client->destPort = 5900;
302 
303 	client->destHost = strdup(argv[i+1]);
304 	if(colon) {
305 	  client->destHost[(int)(colon-argv[i+1])] = '\0';
306 	  client->destPort = atoi(colon+1);
307 	}
308         j+=2;
309       } else {
310 	char* colon=strchr(argv[i],':');
311 
312 	if(client->serverHost)
313 	  free(client->serverHost);
314 
315 	if(colon) {
316 	  client->serverHost = strdup(argv[i]);
317 	  client->serverHost[(int)(colon-argv[i])] = '\0';
318 	  client->serverPort = atoi(colon+1);
319 	} else {
320 	  client->serverHost = strdup(argv[i]);
321 	}
322 	if(client->serverPort >= 0 && client->serverPort < 5900)
323 	  client->serverPort += 5900;
324       }
325       /* purge arguments */
326       if (j>i) {
327 	*argc-=j-i;
328 	memmove(argv+i,argv+j,(*argc-i)*sizeof(char*));
329 	i--;
330       }
331     }
332   }
333 
334   if(!rfbInitConnection(client)) {
335     rfbClientCleanup(client);
336     return FALSE;
337   }
338 
339   return TRUE;
340 }
341 
rfbClientCleanup(rfbClient * client)342 void rfbClientCleanup(rfbClient* client) {
343 #ifdef LIBVNCSERVER_HAVE_LIBZ
344 #ifdef LIBVNCSERVER_HAVE_LIBJPEG
345   int i;
346 
347   for ( i = 0; i < 4; i++ ) {
348     if (client->zlibStreamActive[i] == TRUE ) {
349       if (inflateEnd (&client->zlibStream[i]) != Z_OK &&
350 	  client->zlibStream[i].msg != NULL)
351 	rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg);
352     }
353   }
354 
355   if ( client->decompStreamInited == TRUE ) {
356     if (inflateEnd (&client->decompStream) != Z_OK &&
357 	client->decompStream.msg != NULL)
358       rfbClientLog("inflateEnd: %s\n", client->decompStream.msg );
359   }
360 
361   if (client->jpegSrcManager)
362     free(client->jpegSrcManager);
363 #endif
364 #endif
365 
366   FreeTLS(client);
367 
368   if (client->sock >= 0)
369     close(client->sock);
370   if (client->listenSock >= 0)
371     close(client->listenSock);
372   free(client->desktopName);
373   free(client->serverHost);
374   if (client->destHost)
375     free(client->destHost);
376   if (client->clientAuthSchemes)
377     free(client->clientAuthSchemes);
378   free(client);
379 }
380