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