/* * probe_vnc.c * * Copyright (C) Brian de Alwis 2004 * * This file is part of transcode, a video stream processing tool * * transcode is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * transcode is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "transcode.h" #include "tcinfo.h" #include "ioaux.h" #include "tc.h" #include "libtc/libtc.h" /* Some VNC constants */ #define VNCREC_MAGIC_STRING "vncLog0.0" #define VNCREC_MAGIC_SIZE (9) #define VNC_RFB_PROTOCOL_SCANF_FORMAT "RFB %03d.%03d\n" #define VNC_RFB_PROTO_VERSION_SIZE (12) #define VNC33_CHALLENGESIZE (16) #define VNC33_rfbConnFailed (0) #define VNC33_rfbNoAuth (1) #define VNC33_rfbVncAuth (2) #define VNC33_rfbVncAuthOK (0) #define VNC33_rfbVncAuthFailed (1) #define VNC33_rfbVncAuthTooMany (2) /* RFB 3.X protocol is as follows (from vncrec source code): * server send 12-byte (SIZE_SIZE_RFB_PROTO_VERSION) header encoding the RFB version as an ASCII string * server sends 4-byte number (big-endian) to alert auth requirements * if requiring auth, server then sends 16-byte (VNC33_CHALLENGESIZE) packet, which is to be encrypted and sent back (same size). The server then sends 32-bit word result on pass-fail. Entire thing aborted if not passed. * client sends 1-byte message * server then sends a display-paramters message, containing (in order) the width (2-byte), height (2-byte), preferred pixel format (1-byte), and desktop name (1-byte with length, n bytes). */ void probe_vnc(info_t *ipipe) { unsigned char buf[100]; unsigned char matchingBuffer[100]; int index = 0, major, minor, authReqs; int width, height; if(tc_pread(ipipe->fd_in, buf, sizeof(buf)) != sizeof(buf)) { tc_log_error(__FILE__, "end of stream"); ipipe->error=1; return; } /* Check VNCREC magic */ ac_memcpy(matchingBuffer, &buf[index], VNCREC_MAGIC_SIZE); matchingBuffer[VNCREC_MAGIC_SIZE] = 0; if(strcmp(matchingBuffer, VNCREC_MAGIC_STRING)) { /* NOT EQUAL */ tc_log_error(__FILE__, "unsupported version of vncrec (\"%s\")", matchingBuffer); ipipe->error=1; return; } index += VNCREC_MAGIC_SIZE; /* Ensure RFB protocol is valid */ ac_memcpy(matchingBuffer, &buf[index], VNC_RFB_PROTO_VERSION_SIZE); matchingBuffer[VNC_RFB_PROTO_VERSION_SIZE] = 0; if(sscanf(matchingBuffer, VNC_RFB_PROTOCOL_SCANF_FORMAT, &major, &minor) != 2) { tc_log_error(__FILE__, "unknown RFB protocol (\"%s\")", matchingBuffer); ipipe->error=1; return; } if (ipipe->verbose & TC_DEBUG) { tc_log_msg(__FILE__, "File recorded as RFB Protocol v%d.%d", major, minor); } if(major != 3) { tc_log_error(__FILE__, "unsupported RFB protocol (only support v3)"); ipipe->error=1; return; } index += VNC_RFB_PROTO_VERSION_SIZE; /* Check authentication requirements */ authReqs = (buf[index] << 24) | (buf[index+1] << 16) | (buf[index+2] << 8) | buf[index+3]; index += 4; switch(authReqs) { case VNC33_rfbNoAuth: if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "No authorization required."); break; case VNC33_rfbVncAuth: { int authResp = index += VNC33_CHALLENGESIZE; authResp = (buf[index] << 24) | (buf[index+1] << 16) | (buf[index+2] << 8) | buf[index+3]; /* switch(authResp) { ... } */ index += 4; break; } case VNC33_rfbConnFailed: default: tc_log_error(__FILE__, "apparently connection failed?"); ipipe->error=1; return; } /* Receive display parameters */ width = (buf[index] << 8) | buf[index+1]; height = (buf[index+2] << 8) | buf[index+3]; ipipe->probe_info->width = width; ipipe->probe_info->height = height; ipipe->probe_info->fps = 25.; ipipe->probe_info->frc = 3; ipipe->probe_info->codec = TC_CODEC_RGB; ipipe->probe_info->magic = ipipe->magic; }