6 * Copyright (C) 2002 RealVNC Ltd.
7 * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
8 * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
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.
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.
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,
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);
33 rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type);
34 rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type);
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);
46 char *messageNameServer2Client(uint32_t type, char *buf, int len) {
47 if (buf==NULL) return "error";
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 rfbKeyFrameUpdate: snprintf(buf, len, "KeyFrameUpdate"); break;
55 case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break;
56 case rfbTextChat: snprintf(buf, len, "TextChat"); break;
57 case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break;
59 snprintf(buf, len, "svr2cli-0x%08X", 0xFF);
64 char *messageNameClient2Server(uint32_t type, char *buf, int len) {
65 if (buf==NULL) return "error";
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 rfbKeyFrameRequest: snprintf(buf, len, "KeyFrameRequest"); break;
80 case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break;
82 snprintf(buf, len, "cli2svr-0x%08X", type);
89 /* Encoding name must be <=16 characters to fit nicely on the status output in
90 * an 80 column terminal window
92 char *encodingName(uint32_t type, char *buf, int len) {
93 if (buf==NULL) return "error";
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 rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break;
104 case rfbEncodingUltra: snprintf(buf, len, "ultra"); break;
105 case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break;
106 case rfbEncodingZYWRLE: snprintf(buf, len, "ZYWRLE"); break;
107 case rfbEncodingCache: snprintf(buf, len, "cache"); break;
108 case rfbEncodingCacheEnable: snprintf(buf, len, "cacheEnable"); break;
109 case rfbEncodingXOR_Zlib: snprintf(buf, len, "xorZlib"); break;
110 case rfbEncodingXORMonoColor_Zlib: snprintf(buf, len, "xorMonoZlib"); break;
111 case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break;
112 case rfbEncodingSolidColor: snprintf(buf, len, "solidColor"); break;
113 case rfbEncodingXOREnable: snprintf(buf, len, "xorEnable"); break;
114 case rfbEncodingCacheZip: snprintf(buf, len, "cacheZip"); break;
115 case rfbEncodingSolMonoZip: snprintf(buf, len, "monoZip"); break;
116 case rfbEncodingUltraZip: snprintf(buf, len, "ultraZip"); break;
118 case rfbEncodingXCursor: snprintf(buf, len, "Xcursor"); break;
119 case rfbEncodingRichCursor: snprintf(buf, len, "RichCursor"); break;
120 case rfbEncodingPointerPos: snprintf(buf, len, "PointerPos"); break;
122 case rfbEncodingLastRect: snprintf(buf, len, "LastRect"); break;
123 case rfbEncodingNewFBSize: snprintf(buf, len, "NewFBSize"); break;
124 case rfbEncodingKeyboardLedState: snprintf(buf, len, "LedState"); break;
125 case rfbEncodingSupportedMessages: snprintf(buf, len, "SupportedMessage"); break;
126 case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break;
127 case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentify"); break;
129 /* The following lookups do not report in stats */
130 case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0"); break;
131 case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1"); break;
132 case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2"); break;
133 case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3"); break;
134 case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4"); break;
135 case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5"); break;
136 case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6"); break;
137 case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7"); break;
138 case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8"); break;
139 case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9"); break;
141 case rfbEncodingQualityLevel0: snprintf(buf, len, "QualityLevel0"); break;
142 case rfbEncodingQualityLevel1: snprintf(buf, len, "QualityLevel1"); break;
143 case rfbEncodingQualityLevel2: snprintf(buf, len, "QualityLevel2"); break;
144 case rfbEncodingQualityLevel3: snprintf(buf, len, "QualityLevel3"); break;
145 case rfbEncodingQualityLevel4: snprintf(buf, len, "QualityLevel4"); break;
146 case rfbEncodingQualityLevel5: snprintf(buf, len, "QualityLevel5"); break;
147 case rfbEncodingQualityLevel6: snprintf(buf, len, "QualityLevel6"); break;
148 case rfbEncodingQualityLevel7: snprintf(buf, len, "QualityLevel7"); break;
149 case rfbEncodingQualityLevel8: snprintf(buf, len, "QualityLevel8"); break;
150 case rfbEncodingQualityLevel9: snprintf(buf, len, "QualityLevel9"); break;
154 snprintf(buf, len, "Enc(0x%08X)", type);
164 rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type)
167 if (cl==NULL) return NULL;
168 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
170 if (ptr->type==type) return ptr;
172 /* Well, we are here... need to *CREATE* an entry */
173 ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
176 memset((char *)ptr, 0, sizeof(rfbStatList));
178 /* add to the top of the list */
179 ptr->Next = cl->statEncList;
180 cl->statEncList = ptr;
186 rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type)
189 if (cl==NULL) return NULL;
190 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
192 if (ptr->type==type) return ptr;
194 /* Well, we are here... need to *CREATE* an entry */
195 ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
198 memset((char *)ptr, 0, sizeof(rfbStatList));
200 /* add to the top of the list */
201 ptr->Next = cl->statMsgList;
202 cl->statMsgList = ptr;
207 void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */
211 ptr = rfbStatLookupEncoding(cl, type);
213 ptr->bytesSent += byteCount;
217 void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
221 ptr = rfbStatLookupEncoding(cl, type);
225 ptr->bytesSent += byteCount;
226 ptr->bytesSentIfRaw += byteIfRaw;
230 void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
234 ptr = rfbStatLookupEncoding(cl, type);
238 ptr->bytesRcvd += byteCount;
239 ptr->bytesRcvdIfRaw += byteIfRaw;
243 void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
247 ptr = rfbStatLookupMessage(cl, type);
251 ptr->bytesSent += byteCount;
252 ptr->bytesSentIfRaw += byteIfRaw;
256 void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
260 ptr = rfbStatLookupMessage(cl, type);
264 ptr->bytesRcvd += byteCount;
265 ptr->bytesRcvdIfRaw += byteIfRaw;
270 int rfbStatGetSentBytes(rfbClientPtr cl)
272 rfbStatList *ptr=NULL;
274 if (cl==NULL) return 0;
275 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
276 bytes += ptr->bytesSent;
277 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
278 bytes += ptr->bytesSent;
282 int rfbStatGetSentBytesIfRaw(rfbClientPtr cl)
284 rfbStatList *ptr=NULL;
286 if (cl==NULL) return 0;
287 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
288 bytes += ptr->bytesSentIfRaw;
289 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
290 bytes += ptr->bytesSentIfRaw;
294 int rfbStatGetRcvdBytes(rfbClientPtr cl)
296 rfbStatList *ptr=NULL;
298 if (cl==NULL) return 0;
299 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
300 bytes += ptr->bytesRcvd;
301 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
302 bytes += ptr->bytesRcvd;
306 int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl)
308 rfbStatList *ptr=NULL;
310 if (cl==NULL) return 0;
311 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
312 bytes += ptr->bytesRcvdIfRaw;
313 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
314 bytes += ptr->bytesRcvdIfRaw;
318 int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type)
320 rfbStatList *ptr=NULL;
321 if (cl==NULL) return 0;
322 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
323 if (ptr->type==type) return ptr->sentCount;
326 int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type)
328 rfbStatList *ptr=NULL;
329 if (cl==NULL) return 0;
330 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
331 if (ptr->type==type) return ptr->rcvdCount;
335 int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type)
337 rfbStatList *ptr=NULL;
338 if (cl==NULL) return 0;
339 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
340 if (ptr->type==type) return ptr->sentCount;
343 int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type)
345 rfbStatList *ptr=NULL;
346 if (cl==NULL) return 0;
347 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
348 if (ptr->type==type) return ptr->rcvdCount;
355 void rfbResetStats(rfbClientPtr cl)
358 if (cl==NULL) return;
359 while (cl->statEncList!=NULL)
361 ptr = cl->statEncList;
362 cl->statEncList = ptr->Next;
365 while (cl->statMsgList!=NULL)
367 ptr = cl->statMsgList;
368 cl->statMsgList = ptr->Next;
374 void rfbPrintStats(rfbClientPtr cl)
376 rfbStatList *ptr=NULL;
380 double totalBytes=0.0;
381 double totalBytesIfRaw=0.0;
388 if (cl==NULL) return;
390 rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved");
391 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
393 name = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf));
394 count = ptr->sentCount;
395 bytes = ptr->bytesSent;
396 bytesIfRaw = ptr->bytesSentIfRaw;
400 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
401 if ((bytes>0) || (count>0) || (bytesIfRaw>0))
402 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
403 name, count, bytes, bytesIfRaw, savings);
406 totalBytesIfRaw += bytesIfRaw;
409 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
411 name = encodingName(ptr->type, encBuf, sizeof(encBuf));
412 count = ptr->sentCount;
413 bytes = ptr->bytesSent;
414 bytesIfRaw = ptr->bytesSentIfRaw;
418 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
419 if ((bytes>0) || (count>0) || (bytesIfRaw>0))
420 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
421 name, count, bytes, bytesIfRaw, savings);
424 totalBytesIfRaw += bytesIfRaw;
427 if (totalBytesIfRaw>0.0)
428 savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0);
429 rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n",
430 "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings);
436 rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved");
437 for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
439 name = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf));
440 count = ptr->rcvdCount;
441 bytes = ptr->bytesRcvd;
442 bytesIfRaw = ptr->bytesRcvdIfRaw;
446 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
447 if ((bytes>0) || (count>0) || (bytesIfRaw>0))
448 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
449 name, count, bytes, bytesIfRaw, savings);
452 totalBytesIfRaw += bytesIfRaw;
454 for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
456 name = encodingName(ptr->type, encBuf, sizeof(encBuf));
457 count = ptr->rcvdCount;
458 bytes = ptr->bytesRcvd;
459 bytesIfRaw = ptr->bytesRcvdIfRaw;
463 savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
464 if ((bytes>0) || (count>0) || (bytesIfRaw>0))
465 rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
466 name, count, bytes, bytesIfRaw, savings);
469 totalBytesIfRaw += bytesIfRaw;
472 if (totalBytesIfRaw>0.0)
473 savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0);
474 rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n",
475 "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings);