1 #include "vnc.h" 2 3 #define SHORT(p) (((p)[0]<<8)|((p)[1])) 4 #define LONG(p) ((SHORT(p)<<16)|SHORT(p+2)) 5 6 uchar zero[64]; 7 8 Vnc* 9 vncinit(int fd, int cfd, Vnc *v) 10 { 11 if(v == nil) 12 v = mallocz(sizeof(*v), 1); 13 Binit(&v->in, fd, OREAD); 14 Binit(&v->out, fd, OWRITE); 15 v->datafd = fd; 16 v->ctlfd = cfd; 17 return v; 18 } 19 20 void 21 vncterm(Vnc *v) 22 { 23 Bterm(&v->out); 24 Bterm(&v->in); 25 } 26 27 void 28 vncflush(Vnc *v) 29 { 30 if(Bflush(&v->out) < 0){ 31 if(verbose > 1) 32 fprint(2, "hungup while sending flush: %r\n"); 33 vnchungup(v); 34 } 35 } 36 37 uchar 38 vncrdchar(Vnc *v) 39 { 40 uchar buf[1]; 41 42 vncrdbytes(v, buf, 1); 43 return buf[0]; 44 } 45 46 ushort 47 vncrdshort(Vnc *v) 48 { 49 uchar buf[2]; 50 51 vncrdbytes(v, buf, 2); 52 return SHORT(buf); 53 } 54 55 ulong 56 vncrdlong(Vnc *v) 57 { 58 uchar buf[4]; 59 60 vncrdbytes(v, buf, 4); 61 return LONG(buf); 62 } 63 64 Point 65 vncrdpoint(Vnc *v) 66 { 67 Point p; 68 69 p.x = vncrdshort(v); 70 p.y = vncrdshort(v); 71 return p; 72 } 73 74 Rectangle 75 vncrdrect(Vnc *v) 76 { 77 Rectangle r; 78 79 r.min.x = vncrdshort(v); 80 r.min.y = vncrdshort(v); 81 r.max.x = r.min.x + vncrdshort(v); 82 r.max.y = r.min.y + vncrdshort(v); 83 return r; 84 } 85 86 Rectangle 87 vncrdcorect(Vnc *v) 88 { 89 Rectangle r; 90 91 r.min.x = vncrdchar(v); 92 r.min.y = vncrdchar(v); 93 r.max.x = r.min.x + vncrdchar(v); 94 r.max.y = r.min.y + vncrdchar(v); 95 return r; 96 } 97 98 void 99 vncrdbytes(Vnc *v, void *a, int n) 100 { 101 if(Bread(&v->in, a, n) != n){ 102 if(verbose > 1) 103 fprint(2, "hungup while reading\n"); 104 vnchungup(v); 105 } 106 } 107 108 Pixfmt 109 vncrdpixfmt(Vnc *v) 110 { 111 Pixfmt fmt; 112 uchar pad[3]; 113 114 fmt.bpp = vncrdchar(v); 115 fmt.depth = vncrdchar(v); 116 fmt.bigendian = vncrdchar(v); 117 fmt.truecolor = vncrdchar(v); 118 fmt.red.max = vncrdshort(v); 119 fmt.green.max = vncrdshort(v); 120 fmt.blue.max = vncrdshort(v); 121 fmt.red.shift = vncrdchar(v); 122 fmt.green.shift = vncrdchar(v); 123 fmt.blue.shift = vncrdchar(v); 124 vncrdbytes(v, pad, 3); 125 return fmt; 126 } 127 128 char* 129 vncrdstring(Vnc *v) 130 { 131 ulong len; 132 char *s; 133 134 len = vncrdlong(v); 135 s = malloc(len+1); 136 assert(s != nil); 137 138 vncrdbytes(v, s, len); 139 s[len] = '\0'; 140 return s; 141 } 142 143 /* 144 * on the server side of the negotiation protocol, we read 145 * the client response and then run the negotiated function. 146 * in some cases (e.g., TLS) the negotiated function needs to 147 * use v->datafd directly and be sure that no data has been 148 * buffered away in the Bio. since we know the client is waiting 149 * for our response, it won't have sent any until we respond. 150 * thus we read the response with vncrdstringx, which goes 151 * behind bio's back. 152 */ 153 char* 154 vncrdstringx(Vnc *v) 155 { 156 char tmp[4]; 157 char *s; 158 ulong len; 159 160 assert(Bbuffered(&v->in) == 0); 161 if(readn(v->datafd, tmp, 4) != 4){ 162 fprint(2, "cannot rdstringx: %r"); 163 vnchungup(v); 164 } 165 len = LONG(tmp); 166 s = malloc(len+1); 167 assert(s != nil); 168 if(readn(v->datafd, s, len) != len){ 169 fprint(2, "cannot rdstringx len %lud: %r", len); 170 vnchungup(v); 171 } 172 s[len] = '\0'; 173 return s; 174 } 175 176 void 177 vncwrstring(Vnc *v, char *s) 178 { 179 ulong len; 180 181 len = strlen(s); 182 vncwrlong(v, len); 183 vncwrbytes(v, s, len); 184 } 185 186 void 187 vncwrbytes(Vnc *v, void *a, int n) 188 { 189 if(Bwrite(&v->out, a, n) < 0){ 190 if(verbose > 1) 191 fprint(2, "hungup while writing bytes\n"); 192 vnchungup(v); 193 } 194 } 195 196 void 197 vncwrlong(Vnc *v, ulong u) 198 { 199 uchar buf[4]; 200 201 buf[0] = u>>24; 202 buf[1] = u>>16; 203 buf[2] = u>>8; 204 buf[3] = u; 205 vncwrbytes(v, buf, 4); 206 } 207 208 void 209 vncwrshort(Vnc *v, ushort u) 210 { 211 uchar buf[2]; 212 213 buf[0] = u>>8; 214 buf[1] = u; 215 vncwrbytes(v, buf, 2); 216 } 217 218 void 219 vncwrchar(Vnc *v, uchar c) 220 { 221 vncwrbytes(v, &c, 1); 222 } 223 224 void 225 vncwrpixfmt(Vnc *v, Pixfmt *fmt) 226 { 227 vncwrchar(v, fmt->bpp); 228 vncwrchar(v, fmt->depth); 229 vncwrchar(v, fmt->bigendian); 230 vncwrchar(v, fmt->truecolor); 231 vncwrshort(v, fmt->red.max); 232 vncwrshort(v, fmt->green.max); 233 vncwrshort(v, fmt->blue.max); 234 vncwrchar(v, fmt->red.shift); 235 vncwrchar(v, fmt->green.shift); 236 vncwrchar(v, fmt->blue.shift); 237 vncwrbytes(v, zero, 3); 238 } 239 240 void 241 vncwrrect(Vnc *v, Rectangle r) 242 { 243 vncwrshort(v, r.min.x); 244 vncwrshort(v, r.min.y); 245 vncwrshort(v, r.max.x-r.min.x); 246 vncwrshort(v, r.max.y-r.min.y); 247 } 248 249 void 250 vncwrpoint(Vnc *v, Point p) 251 { 252 vncwrshort(v, p.x); 253 vncwrshort(v, p.y); 254 } 255 256 void 257 vnclock(Vnc *v) 258 { 259 qlock(v); 260 } 261 262 void 263 vncunlock(Vnc *v) 264 { 265 qunlock(v); 266 } 267 268 void 269 hexdump(void *a, int n) 270 { 271 uchar *p, *ep; 272 273 p = a; 274 ep = p+n; 275 276 for(; p<ep; p++) 277 print("%.2ux ", *p); 278 print("\n"); 279 } 280 281 void 282 vncgobble(Vnc *v, long n) 283 { 284 uchar buf[8192]; 285 long m; 286 287 while(n > 0){ 288 m = n; 289 if(m > sizeof(buf)) 290 m = sizeof(buf); 291 vncrdbytes(v, buf, m); 292 n -= m; 293 } 294 } 295