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