1 /* 2 * stats.c 3 */ 4 5 /* 6 * Copyright (C) 2002 RealVNC Ltd. 7 * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk (at) incompleteness.net>. 8 * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. 9 * All Rights Reserved. 10 * 11 * This is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This software is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this software; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 24 * USA. 25 */ 26 27 #include <rfb/rfb.h> 28 29 #ifdef _MSC_VER 30 #define snprintf _snprintf /* Missing in MSVC */ 31 #endif 32 33 char *messageNameServer2Client(uint32_t type, char *buf, int len); 34 char *messageNameClient2Server(uint32_t type, char *buf, int len); 35 char *encodingName(uint32_t enc, char *buf, int len); 36 37 rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); 38 rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); 39 40 void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); 41 void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); 42 void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); 43 void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); 44 void rfbResetStats(rfbClientPtr cl); 45 void rfbPrintStats(rfbClientPtr cl); 46 47 48 49 50 char *messageNameServer2Client(uint32_t type, char *buf, int len) { 51 if (buf==NULL) return "error"; 52 switch (type) { 53 case rfbFramebufferUpdate: snprintf(buf, len, "FramebufferUpdate"); break; 54 case rfbSetColourMapEntries: snprintf(buf, len, "SetColourMapEntries"); break; 55 case rfbBell: snprintf(buf, len, "Bell"); break; 56 case rfbServerCutText: snprintf(buf, len, "ServerCutText"); break; 57 case rfbResizeFrameBuffer: snprintf(buf, len, "ResizeFrameBuffer"); break; 58 case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; 59 case rfbTextChat: snprintf(buf, len, "TextChat"); break; 60 case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break; 61 case rfbXvp: snprintf(buf, len, "XvpServerMessage"); break; 62 default: 63 snprintf(buf, len, "svr2cli-0x%08X", 0xFF); 64 } 65 return buf; 66 } 67 68 char *messageNameClient2Server(uint32_t type, char *buf, int len) { 69 if (buf==NULL) return "error"; 70 switch (type) { 71 case rfbSetPixelFormat: snprintf(buf, len, "SetPixelFormat"); break; 72 case rfbFixColourMapEntries: snprintf(buf, len, "FixColourMapEntries"); break; 73 case rfbSetEncodings: snprintf(buf, len, "SetEncodings"); break; 74 case rfbFramebufferUpdateRequest: snprintf(buf, len, "FramebufferUpdate"); break; 75 case rfbKeyEvent: snprintf(buf, len, "KeyEvent"); break; 76 case rfbPointerEvent: snprintf(buf, len, "PointerEvent"); break; 77 case rfbClientCutText: snprintf(buf, len, "ClientCutText"); break; 78 case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; 79 case rfbSetScale: snprintf(buf, len, "SetScale"); break; 80 case rfbSetServerInput: snprintf(buf, len, "SetServerInput"); break; 81 case rfbSetSW: snprintf(buf, len, "SetSingleWindow"); break; 82 case rfbTextChat: snprintf(buf, len, "TextChat"); break; 83 case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break; 84 case rfbXvp: snprintf(buf, len, "XvpClientMessage"); break; 85 default: 86 snprintf(buf, len, "cli2svr-0x%08X", type); 87 88 89 } 90 return buf; 91 } 92 93 /* Encoding name must be <=16 characters to fit nicely on the status output in 94 * an 80 column terminal window 95 */ 96 char *encodingName(uint32_t type, char *buf, int len) { 97 if (buf==NULL) return "error"; 98 99 switch (type) { 100 case rfbEncodingRaw: snprintf(buf, len, "raw"); break; 101 case rfbEncodingCopyRect: snprintf(buf, len, "copyRect"); break; 102 case rfbEncodingRRE: snprintf(buf, len, "RRE"); break; 103 case rfbEncodingCoRRE: snprintf(buf, len, "CoRRE"); break; 104 case rfbEncodingHextile: snprintf(buf, len, "hextile"); break; 105 case rfbEncodingZlib: snprintf(buf, len, "zlib"); break; 106 case rfbEncodingTight: snprintf(buf, len, "tight"); break; 107 case rfbEncodingTightPng: snprintf(buf, len, "tightPng"); break; 108 case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break; 109 case rfbEncodingUltra: snprintf(buf, len, "ultra"); break; 110 case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break; 111 case rfbEncodingZYWRLE: snprintf(buf, len, "ZYWRLE"); break; 112 case rfbEncodingCache: snprintf(buf, len, "cache"); break; 113 case rfbEncodingCacheEnable: snprintf(buf, len, "cacheEnable"); break; 114 case rfbEncodingXOR_Zlib: snprintf(buf, len, "xorZlib"); break; 115 case rfbEncodingXORMonoColor_Zlib: snprintf(buf, len, "xorMonoZlib"); break; 116 case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break; 117 case rfbEncodingSolidColor: snprintf(buf, len, "solidColor"); break; 118 case rfbEncodingXOREnable: snprintf(buf, len, "xorEnable"); break; 119 case rfbEncodingCacheZip: snprintf(buf, len, "cacheZip"); break; 120 case rfbEncodingSolMonoZip: snprintf(buf, len, "monoZip"); break; 121 case rfbEncodingUltraZip: snprintf(buf, len, "ultraZip"); break; 122 123 case rfbEncodingXCursor: snprintf(buf, len, "Xcursor"); break; 124 case rfbEncodingRichCursor: snprintf(buf, len, "RichCursor"); break; 125 case rfbEncodingPointerPos: snprintf(buf, len, "PointerPos"); break; 126 127 case rfbEncodingLastRect: snprintf(buf, len, "LastRect"); break; 128 case rfbEncodingNewFBSize: snprintf(buf, len, "NewFBSize"); break; 129 case rfbEncodingKeyboardLedState: snprintf(buf, len, "LedState"); break; 130 case rfbEncodingSupportedMessages: snprintf(buf, len, "SupportedMessage"); break; 131 case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break; 132 case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentify"); break; 133 134 /* The following lookups do not report in stats */ 135 case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0"); break; 136 case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1"); break; 137 case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2"); break; 138 case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3"); break; 139 case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4"); break; 140 case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5"); break; 141 case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6"); break; 142 case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7"); break; 143 case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8"); break; 144 case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9"); break; 145 146 case rfbEncodingQualityLevel0: snprintf(buf, len, "QualityLevel0"); break; 147 case rfbEncodingQualityLevel1: snprintf(buf, len, "QualityLevel1"); break; 148 case rfbEncodingQualityLevel2: snprintf(buf, len, "QualityLevel2"); break; 149 case rfbEncodingQualityLevel3: snprintf(buf, len, "QualityLevel3"); break; 150 case rfbEncodingQualityLevel4: snprintf(buf, len, "QualityLevel4"); break; 151 case rfbEncodingQualityLevel5: snprintf(buf, len, "QualityLevel5"); break; 152 case rfbEncodingQualityLevel6: snprintf(buf, len, "QualityLevel6"); break; 153 case rfbEncodingQualityLevel7: snprintf(buf, len, "QualityLevel7"); break; 154 case rfbEncodingQualityLevel8: snprintf(buf, len, "QualityLevel8"); break; 155 case rfbEncodingQualityLevel9: snprintf(buf, len, "QualityLevel9"); break; 156 157 158 default: 159 snprintf(buf, len, "Enc(0x%08X)", type); 160 } 161 162 return buf; 163 } 164 165 166 167 168 169 rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type) 170 { 171 rfbStatList *ptr; 172 if (cl==NULL) return NULL; 173 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 174 { 175 if (ptr->type==type) return ptr; 176 } 177 /* Well, we are here... need to *CREATE* an entry */ 178 ptr = (rfbStatList *)malloc(sizeof(rfbStatList)); 179 if (ptr!=NULL) 180 { 181 memset((char *)ptr, 0, sizeof(rfbStatList)); 182 ptr->type = type; 183 /* add to the top of the list */ 184 ptr->Next = cl->statEncList; 185 cl->statEncList = ptr; 186 } 187 return ptr; 188 } 189 190 191 rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type) 192 { 193 rfbStatList *ptr; 194 if (cl==NULL) return NULL; 195 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 196 { 197 if (ptr->type==type) return ptr; 198 } 199 /* Well, we are here... need to *CREATE* an entry */ 200 ptr = (rfbStatList *)malloc(sizeof(rfbStatList)); 201 if (ptr!=NULL) 202 { 203 memset((char *)ptr, 0, sizeof(rfbStatList)); 204 ptr->type = type; 205 /* add to the top of the list */ 206 ptr->Next = cl->statMsgList; 207 cl->statMsgList = ptr; 208 } 209 return ptr; 210 } 211 212 void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */ 213 { 214 rfbStatList *ptr; 215 216 ptr = rfbStatLookupEncoding(cl, type); 217 if (ptr!=NULL) 218 ptr->bytesSent += byteCount; 219 } 220 221 222 void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) 223 { 224 rfbStatList *ptr; 225 226 ptr = rfbStatLookupEncoding(cl, type); 227 if (ptr!=NULL) 228 { 229 ptr->sentCount++; 230 ptr->bytesSent += byteCount; 231 ptr->bytesSentIfRaw += byteIfRaw; 232 } 233 } 234 235 void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) 236 { 237 rfbStatList *ptr; 238 239 ptr = rfbStatLookupEncoding(cl, type); 240 if (ptr!=NULL) 241 { 242 ptr->rcvdCount++; 243 ptr->bytesRcvd += byteCount; 244 ptr->bytesRcvdIfRaw += byteIfRaw; 245 } 246 } 247 248 void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) 249 { 250 rfbStatList *ptr; 251 252 ptr = rfbStatLookupMessage(cl, type); 253 if (ptr!=NULL) 254 { 255 ptr->sentCount++; 256 ptr->bytesSent += byteCount; 257 ptr->bytesSentIfRaw += byteIfRaw; 258 } 259 } 260 261 void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) 262 { 263 rfbStatList *ptr; 264 265 ptr = rfbStatLookupMessage(cl, type); 266 if (ptr!=NULL) 267 { 268 ptr->rcvdCount++; 269 ptr->bytesRcvd += byteCount; 270 ptr->bytesRcvdIfRaw += byteIfRaw; 271 } 272 } 273 274 275 int rfbStatGetSentBytes(rfbClientPtr cl) 276 { 277 rfbStatList *ptr=NULL; 278 int bytes=0; 279 if (cl==NULL) return 0; 280 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 281 bytes += ptr->bytesSent; 282 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 283 bytes += ptr->bytesSent; 284 return bytes; 285 } 286 287 int rfbStatGetSentBytesIfRaw(rfbClientPtr cl) 288 { 289 rfbStatList *ptr=NULL; 290 int bytes=0; 291 if (cl==NULL) return 0; 292 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 293 bytes += ptr->bytesSentIfRaw; 294 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 295 bytes += ptr->bytesSentIfRaw; 296 return bytes; 297 } 298 299 int rfbStatGetRcvdBytes(rfbClientPtr cl) 300 { 301 rfbStatList *ptr=NULL; 302 int bytes=0; 303 if (cl==NULL) return 0; 304 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 305 bytes += ptr->bytesRcvd; 306 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 307 bytes += ptr->bytesRcvd; 308 return bytes; 309 } 310 311 int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl) 312 { 313 rfbStatList *ptr=NULL; 314 int bytes=0; 315 if (cl==NULL) return 0; 316 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 317 bytes += ptr->bytesRcvdIfRaw; 318 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 319 bytes += ptr->bytesRcvdIfRaw; 320 return bytes; 321 } 322 323 int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type) 324 { 325 rfbStatList *ptr=NULL; 326 if (cl==NULL) return 0; 327 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 328 if (ptr->type==type) return ptr->sentCount; 329 return 0; 330 } 331 int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type) 332 { 333 rfbStatList *ptr=NULL; 334 if (cl==NULL) return 0; 335 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 336 if (ptr->type==type) return ptr->rcvdCount; 337 return 0; 338 } 339 340 int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type) 341 { 342 rfbStatList *ptr=NULL; 343 if (cl==NULL) return 0; 344 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 345 if (ptr->type==type) return ptr->sentCount; 346 return 0; 347 } 348 int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type) 349 { 350 rfbStatList *ptr=NULL; 351 if (cl==NULL) return 0; 352 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 353 if (ptr->type==type) return ptr->rcvdCount; 354 return 0; 355 } 356 357 358 359 360 void rfbResetStats(rfbClientPtr cl) 361 { 362 rfbStatList *ptr; 363 if (cl==NULL) return; 364 while (cl->statEncList!=NULL) 365 { 366 ptr = cl->statEncList; 367 cl->statEncList = ptr->Next; 368 free(ptr); 369 } 370 while (cl->statMsgList!=NULL) 371 { 372 ptr = cl->statMsgList; 373 cl->statMsgList = ptr->Next; 374 free(ptr); 375 } 376 } 377 378 379 void rfbPrintStats(rfbClientPtr cl) 380 { 381 rfbStatList *ptr=NULL; 382 char encBuf[64]; 383 double savings=0.0; 384 int totalRects=0; 385 double totalBytes=0.0; 386 double totalBytesIfRaw=0.0; 387 388 char *name=NULL; 389 int bytes=0; 390 int bytesIfRaw=0; 391 int count=0; 392 393 if (cl==NULL) return; 394 395 rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved"); 396 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 397 { 398 name = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf)); 399 count = ptr->sentCount; 400 bytes = ptr->bytesSent; 401 bytesIfRaw = ptr->bytesSentIfRaw; 402 403 savings = 0.0; 404 if (bytesIfRaw>0.0) 405 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); 406 if ((bytes>0) || (count>0) || (bytesIfRaw>0)) 407 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", 408 name, count, bytes, bytesIfRaw, savings); 409 totalRects += count; 410 totalBytes += bytes; 411 totalBytesIfRaw += bytesIfRaw; 412 } 413 414 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 415 { 416 name = encodingName(ptr->type, encBuf, sizeof(encBuf)); 417 count = ptr->sentCount; 418 bytes = ptr->bytesSent; 419 bytesIfRaw = ptr->bytesSentIfRaw; 420 savings = 0.0; 421 422 if (bytesIfRaw>0.0) 423 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); 424 if ((bytes>0) || (count>0) || (bytesIfRaw>0)) 425 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", 426 name, count, bytes, bytesIfRaw, savings); 427 totalRects += count; 428 totalBytes += bytes; 429 totalBytesIfRaw += bytesIfRaw; 430 } 431 savings=0.0; 432 if (totalBytesIfRaw>0.0) 433 savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); 434 rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", 435 "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); 436 437 totalRects=0.0; 438 totalBytes=0.0; 439 totalBytesIfRaw=0.0; 440 441 rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved"); 442 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) 443 { 444 name = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf)); 445 count = ptr->rcvdCount; 446 bytes = ptr->bytesRcvd; 447 bytesIfRaw = ptr->bytesRcvdIfRaw; 448 savings = 0.0; 449 450 if (bytesIfRaw>0.0) 451 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); 452 if ((bytes>0) || (count>0) || (bytesIfRaw>0)) 453 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", 454 name, count, bytes, bytesIfRaw, savings); 455 totalRects += count; 456 totalBytes += bytes; 457 totalBytesIfRaw += bytesIfRaw; 458 } 459 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) 460 { 461 name = encodingName(ptr->type, encBuf, sizeof(encBuf)); 462 count = ptr->rcvdCount; 463 bytes = ptr->bytesRcvd; 464 bytesIfRaw = ptr->bytesRcvdIfRaw; 465 savings = 0.0; 466 467 if (bytesIfRaw>0.0) 468 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); 469 if ((bytes>0) || (count>0) || (bytesIfRaw>0)) 470 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", 471 name, count, bytes, bytesIfRaw, savings); 472 totalRects += count; 473 totalBytes += bytes; 474 totalBytesIfRaw += bytesIfRaw; 475 } 476 savings=0.0; 477 if (totalBytesIfRaw>0.0) 478 savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); 479 rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", 480 "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); 481 482 } 483 484