2
* synergy -- mouse and keyboard sharing utility
3
* Copyright (C) 2002 Chris Schoeneman
5
* This package is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* found in the file COPYING that should have accompanied this file.
9
* This package 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.
15
#include "CProtocolUtil.h"
16
#include "IInputStream.h"
17
#include "IOutputStream.h"
19
#include "stdvector.h"
28
CProtocolUtil::writef(IOutputStream* stream, const char* fmt, ...)
30
assert(stream != NULL);
32
LOG((CLOG_DEBUG2 "writef(%s)", fmt));
36
// determine total size to write
38
UInt32 count = getLength(fmt, args);
41
// done if nothing to write
47
UInt8* buffer = new UInt8[count];
49
writef(buffer, fmt, args);
55
const UInt32 n = stream->write(scan, count);
56
LOG((CLOG_DEBUG2 "wrote %d of %d bytes", n, count));
65
CProtocolUtil::readf(IInputStream* stream, const char* fmt, ...)
67
assert(stream != NULL);
69
LOG((CLOG_DEBUG2 "readf(%s)", fmt));
77
// format specifier. determine argument size.
79
UInt32 len = eatLength(&fmt);
82
// check for valid length
83
assert(len == 1 || len == 2 || len == 4);
87
read(stream, buffer, len);
90
void* v = va_arg(args, void*);
94
*reinterpret_cast<UInt8*>(v) = buffer[0];
95
LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt8*>(v), *reinterpret_cast<UInt8*>(v)));
100
*reinterpret_cast<UInt16*>(v) =
102
(static_cast<UInt16>(buffer[0]) << 8) |
103
static_cast<UInt16>(buffer[1]));
104
LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt16*>(v), *reinterpret_cast<UInt16*>(v)));
109
*reinterpret_cast<UInt32*>(v) =
110
(static_cast<UInt32>(buffer[0]) << 24) |
111
(static_cast<UInt32>(buffer[1]) << 16) |
112
(static_cast<UInt32>(buffer[2]) << 8) |
113
static_cast<UInt32>(buffer[3]);
114
LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt32*>(v), *reinterpret_cast<UInt32*>(v)));
121
// check for valid length
122
assert(len == 1 || len == 2 || len == 4);
124
// read the vector length
126
read(stream, buffer, 4);
127
UInt32 n = (static_cast<UInt32>(buffer[0]) << 24) |
128
(static_cast<UInt32>(buffer[1]) << 16) |
129
(static_cast<UInt32>(buffer[2]) << 8) |
130
static_cast<UInt32>(buffer[3]);
133
void* v = va_arg(args, void*);
137
for (UInt32 i = 0; i < n; ++i) {
138
read(stream, buffer, 1);
139
reinterpret_cast<std::vector<UInt8>*>(v)->push_back(
141
LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast<std::vector<UInt8>*>(v)->back(), reinterpret_cast<std::vector<UInt8>*>(v)->back()));
147
for (UInt32 i = 0; i < n; ++i) {
148
read(stream, buffer, 2);
149
reinterpret_cast<std::vector<UInt16>*>(v)->push_back(
151
(static_cast<UInt16>(buffer[0]) << 8) |
152
static_cast<UInt16>(buffer[1])));
153
LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast<std::vector<UInt16>*>(v)->back(), reinterpret_cast<std::vector<UInt16>*>(v)->back()));
159
for (UInt32 i = 0; i < n; ++i) {
160
read(stream, buffer, 4);
161
reinterpret_cast<std::vector<UInt32>*>(v)->push_back(
162
(static_cast<UInt32>(buffer[0]) << 24) |
163
(static_cast<UInt32>(buffer[1]) << 16) |
164
(static_cast<UInt32>(buffer[2]) << 8) |
165
static_cast<UInt32>(buffer[3]));
166
LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast<std::vector<UInt32>*>(v)->back(), reinterpret_cast<std::vector<UInt32>*>(v)->back()));
176
// read the string length
178
read(stream, buffer, 4);
179
UInt32 len = (static_cast<UInt32>(buffer[0]) << 24) |
180
(static_cast<UInt32>(buffer[1]) << 16) |
181
(static_cast<UInt32>(buffer[2]) << 8) |
182
static_cast<UInt32>(buffer[3]);
184
// use a fixed size buffer if its big enough
185
const bool useFixed = (len <= sizeof(buffer));
187
// allocate a buffer to read the data
193
sBuffer = new UInt8[len];
198
read(stream, sBuffer, len);
206
LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
209
CString* dst = va_arg(args, CString*);
210
dst->assign((const char*)sBuffer, len);
212
// release the buffer
224
assert(0 && "invalid format specifier");
227
// next format character
231
// read next character
233
read(stream, buffer, 1);
236
if (buffer[0] != *fmt) {
237
LOG((CLOG_DEBUG2 "readf: format mismatch: %c vs %c", *fmt, buffer[0]));
238
throw XIOReadMismatch();
241
// next format character
250
CProtocolUtil::getLength(const char* fmt, va_list args)
255
// format specifier. determine argument size.
257
UInt32 len = eatLength(&fmt);
260
assert(len == 1 || len == 2 || len == 4);
261
(void)va_arg(args, UInt32);
265
assert(len == 1 || len == 2 || len == 4);
268
len = (va_arg(args, std::vector<UInt8>*))->size() + 4;
272
len = 2 * (va_arg(args, std::vector<UInt16>*))->size() + 4;
276
len = 4 * (va_arg(args, std::vector<UInt32>*))->size() + 4;
283
len = (va_arg(args, CString*))->size() + 4;
284
(void)va_arg(args, UInt8*);
289
len = va_arg(args, UInt32) + 4;
290
(void)va_arg(args, UInt8*);
299
assert(0 && "invalid format specifier");
316
CProtocolUtil::writef(void* buffer, const char* fmt, va_list args)
318
UInt8* dst = reinterpret_cast<UInt8*>(buffer);
322
// format specifier. determine argument size.
324
UInt32 len = eatLength(&fmt);
327
const UInt32 v = va_arg(args, UInt32);
331
*dst++ = static_cast<UInt8>(v & 0xff);
336
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
337
*dst++ = static_cast<UInt8>( v & 0xff);
342
*dst++ = static_cast<UInt8>((v >> 24) & 0xff);
343
*dst++ = static_cast<UInt8>((v >> 16) & 0xff);
344
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
345
*dst++ = static_cast<UInt8>( v & 0xff);
349
assert(0 && "invalid integer format length");
359
const std::vector<UInt8>* list =
360
va_arg(args, const std::vector<UInt8>*);
361
const UInt32 n = list->size();
362
*dst++ = static_cast<UInt8>((n >> 24) & 0xff);
363
*dst++ = static_cast<UInt8>((n >> 16) & 0xff);
364
*dst++ = static_cast<UInt8>((n >> 8) & 0xff);
365
*dst++ = static_cast<UInt8>( n & 0xff);
366
for (UInt32 i = 0; i < n; ++i) {
374
const std::vector<UInt16>* list =
375
va_arg(args, const std::vector<UInt16>*);
376
const UInt32 n = list->size();
377
*dst++ = static_cast<UInt8>((n >> 24) & 0xff);
378
*dst++ = static_cast<UInt8>((n >> 16) & 0xff);
379
*dst++ = static_cast<UInt8>((n >> 8) & 0xff);
380
*dst++ = static_cast<UInt8>( n & 0xff);
381
for (UInt32 i = 0; i < n; ++i) {
382
const UInt16 v = (*list)[i];
383
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
384
*dst++ = static_cast<UInt8>( v & 0xff);
391
const std::vector<UInt32>* list =
392
va_arg(args, const std::vector<UInt32>*);
393
const UInt32 n = list->size();
394
*dst++ = static_cast<UInt8>((n >> 24) & 0xff);
395
*dst++ = static_cast<UInt8>((n >> 16) & 0xff);
396
*dst++ = static_cast<UInt8>((n >> 8) & 0xff);
397
*dst++ = static_cast<UInt8>( n & 0xff);
398
for (UInt32 i = 0; i < n; ++i) {
399
const UInt32 v = (*list)[i];
400
*dst++ = static_cast<UInt8>((v >> 24) & 0xff);
401
*dst++ = static_cast<UInt8>((v >> 16) & 0xff);
402
*dst++ = static_cast<UInt8>((v >> 8) & 0xff);
403
*dst++ = static_cast<UInt8>( v & 0xff);
409
assert(0 && "invalid integer vector format length");
417
const CString* src = va_arg(args, CString*);
418
const UInt32 len = (src != NULL) ? src->size() : 0;
419
*dst++ = static_cast<UInt8>((len >> 24) & 0xff);
420
*dst++ = static_cast<UInt8>((len >> 16) & 0xff);
421
*dst++ = static_cast<UInt8>((len >> 8) & 0xff);
422
*dst++ = static_cast<UInt8>( len & 0xff);
424
memcpy(dst, src->data(), len);
432
const UInt32 len = va_arg(args, UInt32);
433
const UInt8* src = va_arg(args, UInt8*);
434
*dst++ = static_cast<UInt8>((len >> 24) & 0xff);
435
*dst++ = static_cast<UInt8>((len >> 16) & 0xff);
436
*dst++ = static_cast<UInt8>((len >> 8) & 0xff);
437
*dst++ = static_cast<UInt8>( len & 0xff);
438
memcpy(dst, src, len);
449
assert(0 && "invalid format specifier");
452
// next format character
456
// copy regular character
463
CProtocolUtil::eatLength(const char** pfmt)
465
const char* fmt = *pfmt;
470
case '0': d = 0; break;
471
case '1': d = 1; break;
472
case '2': d = 2; break;
473
case '3': d = 3; break;
474
case '4': d = 4; break;
475
case '5': d = 5; break;
476
case '6': d = 6; break;
477
case '7': d = 7; break;
478
case '8': d = 8; break;
479
case '9': d = 9; break;
480
default: *pfmt = fmt; return n;
488
CProtocolUtil::read(IInputStream* stream, void* vbuffer, UInt32 count)
490
assert(stream != NULL);
491
assert(vbuffer != NULL);
493
UInt8* buffer = reinterpret_cast<UInt8*>(vbuffer);
496
UInt32 n = stream->read(buffer, count, -1.0);
498
// bail if stream has hungup
500
LOG((CLOG_DEBUG2 "unexpected disconnect in readf(), %d bytes left", count));
501
throw XIOEndOfStream();
504
// prepare for next read
516
XIOReadMismatch::getWhat() const throw()
518
return format("XIOReadMismatch", "CProtocolUtil::readf() mismatch");