1 /*
2 * probe_vnc.c
3 *
4 * Copyright (C) Brian de Alwis 2004
5 *
6 * This file is part of transcode, a video stream processing tool
7 *
8 * transcode is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * transcode is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Make; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "transcode.h"
25 #include "tcinfo.h"
26 #include "ioaux.h"
27 #include "tc.h"
28 #include "libtc/libtc.h"
29
30
31 /* Some VNC constants */
32 #define VNCREC_MAGIC_STRING "vncLog0.0"
33 #define VNCREC_MAGIC_SIZE (9)
34 #define VNC_RFB_PROTOCOL_SCANF_FORMAT "RFB %03d.%03d\n"
35 #define VNC_RFB_PROTO_VERSION_SIZE (12)
36
37 #define VNC33_CHALLENGESIZE (16)
38
39 #define VNC33_rfbConnFailed (0)
40 #define VNC33_rfbNoAuth (1)
41 #define VNC33_rfbVncAuth (2)
42
43 #define VNC33_rfbVncAuthOK (0)
44 #define VNC33_rfbVncAuthFailed (1)
45 #define VNC33_rfbVncAuthTooMany (2)
46
47 /*
48 RFB 3.X protocol is as follows (from vncrec source code):
49 * server send 12-byte (SIZE_SIZE_RFB_PROTO_VERSION) header
50 encoding the RFB version as an ASCII string
51 * server sends 4-byte number (big-endian) to alert auth
52 requirements
53 * if requiring auth, server then sends 16-byte (VNC33_CHALLENGESIZE)
54 packet, which is to be encrypted and sent back (same size).
55 The server then sends 32-bit word result on pass-fail. Entire
56 thing aborted if not passed.
57 * client sends 1-byte message
58 * server then sends a display-paramters message, containing
59 (in order) the width (2-byte), height (2-byte), preferred pixel
60 format (1-byte), and desktop name (1-byte with length, n bytes).
61 */
62
probe_vnc(info_t * ipipe)63 void probe_vnc(info_t *ipipe)
64 {
65 unsigned char buf[100];
66 unsigned char matchingBuffer[100];
67 int index = 0, major, minor, authReqs;
68 int width, height;
69
70 if(tc_pread(ipipe->fd_in, buf, sizeof(buf)) != sizeof(buf)) {
71 tc_log_error(__FILE__, "end of stream");
72 ipipe->error=1;
73 return;
74 }
75
76 /* Check VNCREC magic */
77 ac_memcpy(matchingBuffer, &buf[index], VNCREC_MAGIC_SIZE);
78 matchingBuffer[VNCREC_MAGIC_SIZE] = 0;
79 if(strcmp(matchingBuffer, VNCREC_MAGIC_STRING)) { /* NOT EQUAL */
80 tc_log_error(__FILE__, "unsupported version of vncrec (\"%s\")",
81 matchingBuffer);
82 ipipe->error=1;
83 return;
84 }
85 index += VNCREC_MAGIC_SIZE;
86
87
88 /* Ensure RFB protocol is valid */
89 ac_memcpy(matchingBuffer, &buf[index], VNC_RFB_PROTO_VERSION_SIZE);
90 matchingBuffer[VNC_RFB_PROTO_VERSION_SIZE] = 0;
91 if(sscanf(matchingBuffer, VNC_RFB_PROTOCOL_SCANF_FORMAT, &major, &minor) != 2) {
92 tc_log_error(__FILE__, "unknown RFB protocol (\"%s\")",
93 matchingBuffer);
94 ipipe->error=1;
95 return;
96 }
97 if (ipipe->verbose & TC_DEBUG) {
98 tc_log_msg(__FILE__, "File recorded as RFB Protocol v%d.%d",
99 major, minor);
100 }
101 if(major != 3) {
102 tc_log_error(__FILE__, "unsupported RFB protocol (only support v3)");
103 ipipe->error=1;
104 return;
105 }
106 index += VNC_RFB_PROTO_VERSION_SIZE;
107
108 /* Check authentication requirements */
109 authReqs = (buf[index] << 24) | (buf[index+1] << 16)
110 | (buf[index+2] << 8) | buf[index+3];
111 index += 4;
112 switch(authReqs) {
113 case VNC33_rfbNoAuth:
114 if (ipipe->verbose & TC_DEBUG)
115 tc_log_msg(__FILE__, "No authorization required.");
116 break;
117
118 case VNC33_rfbVncAuth: {
119 int authResp =
120 index += VNC33_CHALLENGESIZE;
121 authResp = (buf[index] << 24) | (buf[index+1] << 16)
122 | (buf[index+2] << 8) | buf[index+3];
123 /* switch(authResp) { ... } */
124 index += 4;
125 break;
126 }
127
128 case VNC33_rfbConnFailed:
129 default:
130 tc_log_error(__FILE__, "apparently connection failed?");
131 ipipe->error=1;
132 return;
133 }
134
135 /* Receive display parameters */
136 width = (buf[index] << 8) | buf[index+1];
137 height = (buf[index+2] << 8) | buf[index+3];
138
139 ipipe->probe_info->width = width;
140 ipipe->probe_info->height = height;
141 ipipe->probe_info->fps = 25.;
142 ipipe->probe_info->frc = 3;
143 ipipe->probe_info->codec = TC_CODEC_RGB;
144 ipipe->probe_info->magic = ipipe->magic;
145
146 }
147