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 35 static void Dummy(rfbClient* client) { 36 } 37 static rfbBool DummyPoint(rfbClient* client, int x, int y) { 38 return TRUE; 39 } 40 static void DummyRect(rfbClient* client, int x, int y, int w, int h) { 41 } 42 43 #ifdef __MINGW32__ 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 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 } 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 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 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 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 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 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