~ubuntu-branches/ubuntu/natty/synergy/natty

« back to all changes in this revision

Viewing changes to lib/synergy/CProtocolUtil.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Lutz
  • Date: 2003-10-31 19:36:30 UTC
  • Revision ID: james.westby@ubuntu.com-20031031193630-knbv79x5az7qh49y
Tags: upstream-1.0.14
ImportĀ upstreamĀ versionĀ 1.0.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * synergy -- mouse and keyboard sharing utility
 
3
 * Copyright (C) 2002 Chris Schoeneman
 
4
 * 
 
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.
 
8
 * 
 
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.
 
13
 */
 
14
 
 
15
#include "CProtocolUtil.h"
 
16
#include "IInputStream.h"
 
17
#include "IOutputStream.h"
 
18
#include "CLog.h"
 
19
#include "stdvector.h"
 
20
#include <cctype>
 
21
#include <cstring>
 
22
 
 
23
//
 
24
// CProtocolUtil
 
25
//
 
26
 
 
27
void
 
28
CProtocolUtil::writef(IOutputStream* stream, const char* fmt, ...)
 
29
{
 
30
        assert(stream != NULL);
 
31
        assert(fmt != NULL);
 
32
        LOG((CLOG_DEBUG2 "writef(%s)", fmt));
 
33
 
 
34
        va_list args;
 
35
 
 
36
        // determine total size to write
 
37
        va_start(args, fmt);
 
38
        UInt32 count = getLength(fmt, args);
 
39
        va_end(args);
 
40
 
 
41
        // done if nothing to write
 
42
        if (count == 0) {
 
43
                return;
 
44
        }
 
45
 
 
46
        // fill buffer
 
47
        UInt8* buffer = new UInt8[count];
 
48
        va_start(args, fmt);
 
49
        writef(buffer, fmt, args);
 
50
        va_end(args);
 
51
 
 
52
        // write buffer
 
53
        UInt8* scan = buffer;
 
54
        while (count > 0) {
 
55
                const UInt32 n = stream->write(scan, count);
 
56
                LOG((CLOG_DEBUG2 "wrote %d of %d bytes", n, count));
 
57
                count -= n;
 
58
                scan  += n;
 
59
        }
 
60
 
 
61
        delete[] buffer;
 
62
}
 
63
 
 
64
void
 
65
CProtocolUtil::readf(IInputStream* stream, const char* fmt, ...)
 
66
{
 
67
        assert(stream != NULL);
 
68
        assert(fmt != NULL);
 
69
        LOG((CLOG_DEBUG2 "readf(%s)", fmt));
 
70
 
 
71
        va_list args;
 
72
        va_start(args, fmt);
 
73
 
 
74
        // begin scanning
 
75
        while (*fmt) {
 
76
                if (*fmt == '%') {
 
77
                        // format specifier.  determine argument size.
 
78
                        ++fmt;
 
79
                        UInt32 len = eatLength(&fmt);
 
80
                        switch (*fmt) {
 
81
                        case 'i': {
 
82
                                // check for valid length
 
83
                                assert(len == 1 || len == 2 || len == 4);
 
84
 
 
85
                                // read the data
 
86
                                UInt8 buffer[4];
 
87
                                read(stream, buffer, len);
 
88
 
 
89
                                // convert it
 
90
                                void* v = va_arg(args, void*);
 
91
                                switch (len) {
 
92
                                case 1:
 
93
                                        // 1 byte integer
 
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)));
 
96
                                        break;
 
97
 
 
98
                                case 2:
 
99
                                        // 2 byte integer
 
100
                                        *reinterpret_cast<UInt16*>(v) =
 
101
                                                static_cast<UInt16>(
 
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)));
 
105
                                        break;
 
106
 
 
107
                                case 4:
 
108
                                        // 4 byte integer
 
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)));
 
115
                                        break;
 
116
                                }
 
117
                                break;
 
118
                        }
 
119
 
 
120
                        case 'I': {
 
121
                                // check for valid length
 
122
                                assert(len == 1 || len == 2 || len == 4);
 
123
 
 
124
                                // read the vector length
 
125
                                UInt8 buffer[4];
 
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]);
 
131
 
 
132
                                // convert it
 
133
                                void* v = va_arg(args, void*);
 
134
                                switch (len) {
 
135
                                case 1:
 
136
                                        // 1 byte integer
 
137
                                        for (UInt32 i = 0; i < n; ++i) {
 
138
                                                read(stream, buffer, 1);
 
139
                                                reinterpret_cast<std::vector<UInt8>*>(v)->push_back(
 
140
                                                        buffer[0]);
 
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()));
 
142
                                        }
 
143
                                        break;
 
144
 
 
145
                                case 2:
 
146
                                        // 2 byte integer
 
147
                                        for (UInt32 i = 0; i < n; ++i) {
 
148
                                                read(stream, buffer, 2);
 
149
                                                reinterpret_cast<std::vector<UInt16>*>(v)->push_back(
 
150
                                                        static_cast<UInt16>(
 
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()));
 
154
                                        }
 
155
                                        break;
 
156
 
 
157
                                case 4:
 
158
                                        // 4 byte integer
 
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()));
 
167
                                        }
 
168
                                        break;
 
169
                                }
 
170
                                break;
 
171
                        }
 
172
 
 
173
                        case 's': {
 
174
                                assert(len == 0);
 
175
 
 
176
                                // read the string length
 
177
                                UInt8 buffer[128];
 
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]);
 
183
 
 
184
                                // use a fixed size buffer if its big enough
 
185
                                const bool useFixed = (len <= sizeof(buffer));
 
186
 
 
187
                                // allocate a buffer to read the data
 
188
                                UInt8* sBuffer;
 
189
                                if (useFixed) {
 
190
                                        sBuffer = buffer;
 
191
                                }
 
192
                                else {
 
193
                                        sBuffer = new UInt8[len];
 
194
                                }
 
195
 
 
196
                                // read the data
 
197
                                try {
 
198
                                        read(stream, sBuffer, len);
 
199
                                }
 
200
                                catch (...) {
 
201
                                        if (!useFixed) {
 
202
                                                delete[] sBuffer;
 
203
                                        }
 
204
                                        throw;
 
205
                                }
 
206
                                LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
 
207
 
 
208
                                // save the data
 
209
                                CString* dst = va_arg(args, CString*);
 
210
                                dst->assign((const char*)sBuffer, len);
 
211
 
 
212
                                // release the buffer
 
213
                                if (!useFixed) {
 
214
                                        delete[] sBuffer;
 
215
                                }
 
216
                                break;
 
217
                        }
 
218
 
 
219
                        case '%':
 
220
                                assert(len == 0);
 
221
                                break;
 
222
 
 
223
                        default:
 
224
                                assert(0 && "invalid format specifier");
 
225
                        }
 
226
 
 
227
                        // next format character
 
228
                        ++fmt;
 
229
                }
 
230
                else {
 
231
                        // read next character
 
232
                        char buffer[1];
 
233
                        read(stream, buffer, 1);
 
234
 
 
235
                        // verify match
 
236
                        if (buffer[0] != *fmt) {
 
237
                                LOG((CLOG_DEBUG2 "readf: format mismatch: %c vs %c", *fmt, buffer[0]));
 
238
                                throw XIOReadMismatch();
 
239
                        }
 
240
 
 
241
                        // next format character
 
242
                        ++fmt;
 
243
                }
 
244
        }
 
245
 
 
246
        va_end(args);
 
247
}
 
248
 
 
249
UInt32
 
250
CProtocolUtil::getLength(const char* fmt, va_list args)
 
251
{
 
252
        UInt32 n = 0;
 
253
        while (*fmt) {
 
254
                if (*fmt == '%') {
 
255
                        // format specifier.  determine argument size.
 
256
                        ++fmt;
 
257
                        UInt32 len = eatLength(&fmt);
 
258
                        switch (*fmt) {
 
259
                        case 'i':
 
260
                                assert(len == 1 || len == 2 || len == 4);
 
261
                                (void)va_arg(args, UInt32);
 
262
                                break;
 
263
 
 
264
                        case 'I':
 
265
                                assert(len == 1 || len == 2 || len == 4);
 
266
                                switch (len) {
 
267
                                case 1:
 
268
                                        len = (va_arg(args, std::vector<UInt8>*))->size() + 4;
 
269
                                        break;
 
270
 
 
271
                                case 2:
 
272
                                        len = 2 * (va_arg(args, std::vector<UInt16>*))->size() + 4;
 
273
                                        break;
 
274
 
 
275
                                case 4:
 
276
                                        len = 4 * (va_arg(args, std::vector<UInt32>*))->size() + 4;
 
277
                                        break;
 
278
                                }
 
279
                                break;
 
280
 
 
281
                        case 's':
 
282
                                assert(len == 0);
 
283
                                len = (va_arg(args, CString*))->size() + 4;
 
284
                                (void)va_arg(args, UInt8*);
 
285
                                break;
 
286
 
 
287
                        case 'S':
 
288
                                assert(len == 0);
 
289
                                len = va_arg(args, UInt32) + 4;
 
290
                                (void)va_arg(args, UInt8*);
 
291
                                break;
 
292
 
 
293
                        case '%':
 
294
                                assert(len == 0);
 
295
                                len = 1;
 
296
                                break;
 
297
 
 
298
                        default:
 
299
                                assert(0 && "invalid format specifier");
 
300
                        }
 
301
 
 
302
                        // accumulate size
 
303
                        n += len;
 
304
                        ++fmt;
 
305
                }
 
306
                else {
 
307
                        // regular character
 
308
                        ++n;
 
309
                        ++fmt;
 
310
                }
 
311
        }
 
312
        return n;
 
313
}
 
314
 
 
315
void
 
316
CProtocolUtil::writef(void* buffer, const char* fmt, va_list args)
 
317
{
 
318
        UInt8* dst = reinterpret_cast<UInt8*>(buffer);
 
319
 
 
320
        while (*fmt) {
 
321
                if (*fmt == '%') {
 
322
                        // format specifier.  determine argument size.
 
323
                        ++fmt;
 
324
                        UInt32 len = eatLength(&fmt);
 
325
                        switch (*fmt) {
 
326
                        case 'i': {
 
327
                                const UInt32 v = va_arg(args, UInt32);
 
328
                                switch (len) {
 
329
                                case 1:
 
330
                                        // 1 byte integer
 
331
                                        *dst++ = static_cast<UInt8>(v & 0xff);
 
332
                                        break;
 
333
 
 
334
                                case 2:
 
335
                                        // 2 byte integer
 
336
                                        *dst++ = static_cast<UInt8>((v >> 8) & 0xff);
 
337
                                        *dst++ = static_cast<UInt8>( v       & 0xff);
 
338
                                        break;
 
339
 
 
340
                                case 4:
 
341
                                        // 4 byte integer
 
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);
 
346
                                        break;
 
347
 
 
348
                                default:
 
349
                                        assert(0 && "invalid integer format length");
 
350
                                        return;
 
351
                                }
 
352
                                break;
 
353
                        }
 
354
 
 
355
                        case 'I': {
 
356
                                switch (len) {
 
357
                                case 1: {
 
358
                                        // 1 byte integers
 
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) {
 
367
                                                *dst++ = (*list)[i];
 
368
                                        }
 
369
                                        break;
 
370
                                }
 
371
 
 
372
                                case 2: {
 
373
                                        // 2 byte integers
 
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);
 
385
                                        }
 
386
                                        break;
 
387
                                }
 
388
 
 
389
                                case 4: {
 
390
                                        // 4 byte integers
 
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);
 
404
                                        }
 
405
                                        break;
 
406
                                }
 
407
 
 
408
                                default:
 
409
                                        assert(0 && "invalid integer vector format length");
 
410
                                        return;
 
411
                                }
 
412
                                break;
 
413
                        }
 
414
 
 
415
                        case 's': {
 
416
                                assert(len == 0);
 
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);
 
423
                                if (len != 0) {
 
424
                                        memcpy(dst, src->data(), len);
 
425
                                        dst += len;
 
426
                                }
 
427
                                break;
 
428
                        }
 
429
 
 
430
                        case 'S': {
 
431
                                assert(len == 0);
 
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);
 
439
                                dst += len;
 
440
                                break;
 
441
                        }
 
442
 
 
443
                        case '%':
 
444
                                assert(len == 0);
 
445
                                *dst++ = '%';
 
446
                                break;
 
447
 
 
448
                        default:
 
449
                                assert(0 && "invalid format specifier");
 
450
                        }
 
451
 
 
452
                        // next format character
 
453
                        ++fmt;
 
454
                }
 
455
                else {
 
456
                        // copy regular character
 
457
                        *dst++ = *fmt++;
 
458
                }
 
459
        }
 
460
}
 
461
 
 
462
UInt32
 
463
CProtocolUtil::eatLength(const char** pfmt)
 
464
{
 
465
        const char* fmt = *pfmt;
 
466
        UInt32 n = 0;
 
467
        for (;;) {
 
468
                UInt32 d;
 
469
                switch (*fmt) {
 
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;
 
481
                }
 
482
                n = 10 * n + d;
 
483
                ++fmt;
 
484
        }
 
485
}
 
486
 
 
487
void
 
488
CProtocolUtil::read(IInputStream* stream, void* vbuffer, UInt32 count)
 
489
{
 
490
        assert(stream != NULL);
 
491
        assert(vbuffer != NULL);
 
492
 
 
493
        UInt8* buffer = reinterpret_cast<UInt8*>(vbuffer);
 
494
        while (count > 0) {
 
495
                // read more
 
496
                UInt32 n = stream->read(buffer, count, -1.0);
 
497
 
 
498
                // bail if stream has hungup
 
499
                if (n == 0) {
 
500
                        LOG((CLOG_DEBUG2 "unexpected disconnect in readf(), %d bytes left", count));
 
501
                        throw XIOEndOfStream();
 
502
                }
 
503
 
 
504
                // prepare for next read
 
505
                buffer += n;
 
506
                count  -= n;
 
507
        }
 
508
}
 
509
 
 
510
 
 
511
//
 
512
// XIOReadMismatch
 
513
//
 
514
 
 
515
CString
 
516
XIOReadMismatch::getWhat() const throw()
 
517
{
 
518
        return format("XIOReadMismatch", "CProtocolUtil::readf() mismatch");
 
519
}