00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CProtocolUtil.h"
00020 #include "IStream.h"
00021 #include "CLog.h"
00022 #include "stdvector.h"
00023 #include <cctype>
00024 #include <cstring>
00025
00026
00027
00028
00029
00030 void
00031 CProtocolUtil::writef(synergy::IStream* stream, const char* fmt, ...)
00032 {
00033 assert(stream != NULL);
00034 assert(fmt != NULL);
00035 LOG((CLOG_DEBUG2 "writef(%s)", fmt));
00036
00037 va_list args;
00038 va_start(args, fmt);
00039 UInt32 size = getLength(fmt, args);
00040 va_end(args);
00041 va_start(args, fmt);
00042 vwritef(stream, fmt, size, args);
00043 va_end(args);
00044 }
00045
00046 bool
00047 CProtocolUtil::readf(synergy::IStream* stream, const char* fmt, ...)
00048 {
00049 assert(stream != NULL);
00050 assert(fmt != NULL);
00051 LOG((CLOG_DEBUG2 "readf(%s)", fmt));
00052
00053 bool result;
00054 va_list args;
00055 va_start(args, fmt);
00056 try {
00057 vreadf(stream, fmt, args);
00058 result = true;
00059 }
00060 catch (XIO&) {
00061 result = false;
00062 }
00063 va_end(args);
00064 return result;
00065 }
00066
00067 void
00068 CProtocolUtil::vwritef(synergy::IStream* stream,
00069 const char* fmt, UInt32 size, va_list args)
00070 {
00071 assert(stream != NULL);
00072 assert(fmt != NULL);
00073
00074
00075 if (size == 0) {
00076 return;
00077 }
00078
00079
00080 UInt8* buffer = new UInt8[size];
00081 writef(buffer, fmt, args);
00082
00083 try {
00084
00085 stream->write(buffer, size);
00086 LOG((CLOG_DEBUG2 "wrote %d bytes", size));
00087
00088 delete[] buffer;
00089 }
00090 catch (XBase&) {
00091 delete[] buffer;
00092 throw;
00093 }
00094 }
00095
00096 void
00097 CProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args)
00098 {
00099 assert(stream != NULL);
00100 assert(fmt != NULL);
00101
00102
00103 while (*fmt) {
00104 if (*fmt == '%') {
00105
00106 ++fmt;
00107 UInt32 len = eatLength(&fmt);
00108 switch (*fmt) {
00109 case 'i': {
00110
00111 assert(len == 1 || len == 2 || len == 4);
00112
00113
00114 UInt8 buffer[4];
00115 read(stream, buffer, len);
00116
00117
00118 void* v = va_arg(args, void*);
00119 switch (len) {
00120 case 1:
00121
00122 *reinterpret_cast<UInt8*>(v) = buffer[0];
00123 LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt8*>(v), *reinterpret_cast<UInt8*>(v)));
00124 break;
00125
00126 case 2:
00127
00128 *reinterpret_cast<UInt16*>(v) =
00129 static_cast<UInt16>(
00130 (static_cast<UInt16>(buffer[0]) << 8) |
00131 static_cast<UInt16>(buffer[1]));
00132 LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt16*>(v), *reinterpret_cast<UInt16*>(v)));
00133 break;
00134
00135 case 4:
00136
00137 *reinterpret_cast<UInt32*>(v) =
00138 (static_cast<UInt32>(buffer[0]) << 24) |
00139 (static_cast<UInt32>(buffer[1]) << 16) |
00140 (static_cast<UInt32>(buffer[2]) << 8) |
00141 static_cast<UInt32>(buffer[3]);
00142 LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast<UInt32*>(v), *reinterpret_cast<UInt32*>(v)));
00143 break;
00144 }
00145 break;
00146 }
00147
00148 case 'I': {
00149
00150 assert(len == 1 || len == 2 || len == 4);
00151
00152
00153 UInt8 buffer[4];
00154 read(stream, buffer, 4);
00155 UInt32 n = (static_cast<UInt32>(buffer[0]) << 24) |
00156 (static_cast<UInt32>(buffer[1]) << 16) |
00157 (static_cast<UInt32>(buffer[2]) << 8) |
00158 static_cast<UInt32>(buffer[3]);
00159
00160
00161 void* v = va_arg(args, void*);
00162 switch (len) {
00163 case 1:
00164
00165 for (UInt32 i = 0; i < n; ++i) {
00166 read(stream, buffer, 1);
00167 reinterpret_cast<std::vector<UInt8>*>(v)->push_back(
00168 buffer[0]);
00169 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()));
00170 }
00171 break;
00172
00173 case 2:
00174
00175 for (UInt32 i = 0; i < n; ++i) {
00176 read(stream, buffer, 2);
00177 reinterpret_cast<std::vector<UInt16>*>(v)->push_back(
00178 static_cast<UInt16>(
00179 (static_cast<UInt16>(buffer[0]) << 8) |
00180 static_cast<UInt16>(buffer[1])));
00181 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()));
00182 }
00183 break;
00184
00185 case 4:
00186
00187 for (UInt32 i = 0; i < n; ++i) {
00188 read(stream, buffer, 4);
00189 reinterpret_cast<std::vector<UInt32>*>(v)->push_back(
00190 (static_cast<UInt32>(buffer[0]) << 24) |
00191 (static_cast<UInt32>(buffer[1]) << 16) |
00192 (static_cast<UInt32>(buffer[2]) << 8) |
00193 static_cast<UInt32>(buffer[3]));
00194 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()));
00195 }
00196 break;
00197 }
00198 break;
00199 }
00200
00201 case 's': {
00202 assert(len == 0);
00203
00204
00205 UInt8 buffer[128];
00206 read(stream, buffer, 4);
00207 UInt32 len = (static_cast<UInt32>(buffer[0]) << 24) |
00208 (static_cast<UInt32>(buffer[1]) << 16) |
00209 (static_cast<UInt32>(buffer[2]) << 8) |
00210 static_cast<UInt32>(buffer[3]);
00211
00212
00213 const bool useFixed = (len <= sizeof(buffer));
00214
00215
00216 UInt8* sBuffer = buffer;
00217 if (!useFixed) {
00218 sBuffer = new UInt8[len];
00219 }
00220
00221
00222 try {
00223 read(stream, sBuffer, len);
00224 }
00225 catch (...) {
00226 if (!useFixed) {
00227 delete[] sBuffer;
00228 }
00229 throw;
00230 }
00231 LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
00232
00233
00234 CString* dst = va_arg(args, CString*);
00235 dst->assign((const char*)sBuffer, len);
00236
00237
00238 if (!useFixed) {
00239 delete[] sBuffer;
00240 }
00241 break;
00242 }
00243
00244 case '%':
00245 assert(len == 0);
00246 break;
00247
00248 default:
00249 assert(0 && "invalid format specifier");
00250 }
00251
00252
00253 ++fmt;
00254 }
00255 else {
00256
00257 char buffer[1];
00258 read(stream, buffer, 1);
00259
00260
00261 if (buffer[0] != *fmt) {
00262 LOG((CLOG_DEBUG2 "readf: format mismatch: %c vs %c", *fmt, buffer[0]));
00263 throw XIOReadMismatch();
00264 }
00265
00266
00267 ++fmt;
00268 }
00269 }
00270 }
00271
00272 UInt32
00273 CProtocolUtil::getLength(const char* fmt, va_list args)
00274 {
00275 UInt32 n = 0;
00276 while (*fmt) {
00277 if (*fmt == '%') {
00278
00279 ++fmt;
00280 UInt32 len = eatLength(&fmt);
00281 switch (*fmt) {
00282 case 'i':
00283 assert(len == 1 || len == 2 || len == 4);
00284 (void)va_arg(args, UInt32);
00285 break;
00286
00287 case 'I':
00288 assert(len == 1 || len == 2 || len == 4);
00289 switch (len) {
00290 case 1:
00291 len = (UInt32)(va_arg(args, std::vector<UInt8>*))->size() + 4;
00292 break;
00293
00294 case 2:
00295 len = 2 * (UInt32)(va_arg(args, std::vector<UInt16>*))->size() + 4;
00296 break;
00297
00298 case 4:
00299 len = 4 * (UInt32)(va_arg(args, std::vector<UInt32>*))->size() + 4;
00300 break;
00301 }
00302 break;
00303
00304 case 's':
00305 assert(len == 0);
00306 len = (UInt32)(va_arg(args, CString*))->size() + 4;
00307 (void)va_arg(args, UInt8*);
00308 break;
00309
00310 case 'S':
00311 assert(len == 0);
00312 len = va_arg(args, UInt32) + 4;
00313 (void)va_arg(args, UInt8*);
00314 break;
00315
00316 case '%':
00317 assert(len == 0);
00318 len = 1;
00319 break;
00320
00321 default:
00322 assert(0 && "invalid format specifier");
00323 }
00324
00325
00326 n += len;
00327 ++fmt;
00328 }
00329 else {
00330
00331 ++n;
00332 ++fmt;
00333 }
00334 }
00335 return n;
00336 }
00337
00338 void
00339 CProtocolUtil::writef(void* buffer, const char* fmt, va_list args)
00340 {
00341 UInt8* dst = reinterpret_cast<UInt8*>(buffer);
00342
00343 while (*fmt) {
00344 if (*fmt == '%') {
00345
00346 ++fmt;
00347 UInt32 len = eatLength(&fmt);
00348 switch (*fmt) {
00349 case 'i': {
00350 const UInt32 v = va_arg(args, UInt32);
00351 switch (len) {
00352 case 1:
00353
00354 *dst++ = static_cast<UInt8>(v & 0xff);
00355 break;
00356
00357 case 2:
00358
00359 *dst++ = static_cast<UInt8>((v >> 8) & 0xff);
00360 *dst++ = static_cast<UInt8>( v & 0xff);
00361 break;
00362
00363 case 4:
00364
00365 *dst++ = static_cast<UInt8>((v >> 24) & 0xff);
00366 *dst++ = static_cast<UInt8>((v >> 16) & 0xff);
00367 *dst++ = static_cast<UInt8>((v >> 8) & 0xff);
00368 *dst++ = static_cast<UInt8>( v & 0xff);
00369 break;
00370
00371 default:
00372 assert(0 && "invalid integer format length");
00373 return;
00374 }
00375 break;
00376 }
00377
00378 case 'I': {
00379 switch (len) {
00380 case 1: {
00381
00382 const std::vector<UInt8>* list =
00383 va_arg(args, const std::vector<UInt8>*);
00384 const UInt32 n = (UInt32)list->size();
00385 *dst++ = static_cast<UInt8>((n >> 24) & 0xff);
00386 *dst++ = static_cast<UInt8>((n >> 16) & 0xff);
00387 *dst++ = static_cast<UInt8>((n >> 8) & 0xff);
00388 *dst++ = static_cast<UInt8>( n & 0xff);
00389 for (UInt32 i = 0; i < n; ++i) {
00390 *dst++ = (*list)[i];
00391 }
00392 break;
00393 }
00394
00395 case 2: {
00396
00397 const std::vector<UInt16>* list =
00398 va_arg(args, const std::vector<UInt16>*);
00399 const UInt32 n = (UInt32)list->size();
00400 *dst++ = static_cast<UInt8>((n >> 24) & 0xff);
00401 *dst++ = static_cast<UInt8>((n >> 16) & 0xff);
00402 *dst++ = static_cast<UInt8>((n >> 8) & 0xff);
00403 *dst++ = static_cast<UInt8>( n & 0xff);
00404 for (UInt32 i = 0; i < n; ++i) {
00405 const UInt16 v = (*list)[i];
00406 *dst++ = static_cast<UInt8>((v >> 8) & 0xff);
00407 *dst++ = static_cast<UInt8>( v & 0xff);
00408 }
00409 break;
00410 }
00411
00412 case 4: {
00413
00414 const std::vector<UInt32>* list =
00415 va_arg(args, const std::vector<UInt32>*);
00416 const UInt32 n = (UInt32)list->size();
00417 *dst++ = static_cast<UInt8>((n >> 24) & 0xff);
00418 *dst++ = static_cast<UInt8>((n >> 16) & 0xff);
00419 *dst++ = static_cast<UInt8>((n >> 8) & 0xff);
00420 *dst++ = static_cast<UInt8>( n & 0xff);
00421 for (UInt32 i = 0; i < n; ++i) {
00422 const UInt32 v = (*list)[i];
00423 *dst++ = static_cast<UInt8>((v >> 24) & 0xff);
00424 *dst++ = static_cast<UInt8>((v >> 16) & 0xff);
00425 *dst++ = static_cast<UInt8>((v >> 8) & 0xff);
00426 *dst++ = static_cast<UInt8>( v & 0xff);
00427 }
00428 break;
00429 }
00430
00431 default:
00432 assert(0 && "invalid integer vector format length");
00433 return;
00434 }
00435 break;
00436 }
00437
00438 case 's': {
00439 assert(len == 0);
00440 const CString* src = va_arg(args, CString*);
00441 const UInt32 len = (src != NULL) ? (UInt32)src->size() : 0;
00442 *dst++ = static_cast<UInt8>((len >> 24) & 0xff);
00443 *dst++ = static_cast<UInt8>((len >> 16) & 0xff);
00444 *dst++ = static_cast<UInt8>((len >> 8) & 0xff);
00445 *dst++ = static_cast<UInt8>( len & 0xff);
00446 if (len != 0) {
00447 memcpy(dst, src->data(), len);
00448 dst += len;
00449 }
00450 break;
00451 }
00452
00453 case 'S': {
00454 assert(len == 0);
00455 const UInt32 len = va_arg(args, UInt32);
00456 const UInt8* src = va_arg(args, UInt8*);
00457 *dst++ = static_cast<UInt8>((len >> 24) & 0xff);
00458 *dst++ = static_cast<UInt8>((len >> 16) & 0xff);
00459 *dst++ = static_cast<UInt8>((len >> 8) & 0xff);
00460 *dst++ = static_cast<UInt8>( len & 0xff);
00461 memcpy(dst, src, len);
00462 dst += len;
00463 break;
00464 }
00465
00466 case '%':
00467 assert(len == 0);
00468 *dst++ = '%';
00469 break;
00470
00471 default:
00472 assert(0 && "invalid format specifier");
00473 }
00474
00475
00476 ++fmt;
00477 }
00478 else {
00479
00480 *dst++ = *fmt++;
00481 }
00482 }
00483 }
00484
00485 UInt32
00486 CProtocolUtil::eatLength(const char** pfmt)
00487 {
00488 const char* fmt = *pfmt;
00489 UInt32 n = 0;
00490 for (;;) {
00491 UInt32 d;
00492 switch (*fmt) {
00493 case '0': d = 0; break;
00494 case '1': d = 1; break;
00495 case '2': d = 2; break;
00496 case '3': d = 3; break;
00497 case '4': d = 4; break;
00498 case '5': d = 5; break;
00499 case '6': d = 6; break;
00500 case '7': d = 7; break;
00501 case '8': d = 8; break;
00502 case '9': d = 9; break;
00503 default: *pfmt = fmt; return n;
00504 }
00505 n = 10 * n + d;
00506 ++fmt;
00507 }
00508 }
00509
00510 void
00511 CProtocolUtil::read(synergy::IStream* stream, void* vbuffer, UInt32 count)
00512 {
00513 assert(stream != NULL);
00514 assert(vbuffer != NULL);
00515
00516 UInt8* buffer = reinterpret_cast<UInt8*>(vbuffer);
00517 while (count > 0) {
00518
00519 UInt32 n = stream->read(buffer, count);
00520
00521
00522 if (n == 0) {
00523 LOG((CLOG_DEBUG2 "unexpected disconnect in readf(), %d bytes left", count));
00524 throw XIOEndOfStream();
00525 }
00526
00527
00528 buffer += n;
00529 count -= n;
00530 }
00531 }
00532
00533
00534
00535
00536
00537
00538 CString
00539 XIOReadMismatch::getWhat() const throw()
00540 {
00541 return format("XIOReadMismatch", "CProtocolUtil::readf() mismatch");
00542 }