blob: 4153c97e82744e30521d8e67707420e141d6a424 [file] [log] [blame]
San Mehata430b2b2014-09-23 08:30:51 -07001/*
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
35static void Dummy(rfbClient* client) {
36}
37static rfbBool DummyPoint(rfbClient* client, int x, int y) {
38 return TRUE;
39}
40static void DummyRect(rfbClient* client, int x, int y, int w, int h) {
41}
42
43#ifdef __MINGW32__
44static 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
55static 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}
84static 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
91static 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
110rfbClient* 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
204static 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
263rfbBool 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
342void 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}