1 /*
2 * stats.c
3 */
4
5 /*
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.
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
messageNameServer2Client(uint32_t type,char * buf,int len)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
messageNameClient2Server(uint32_t type,char * buf,int len)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 */
encodingName(uint32_t type,char * buf,int len)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
rfbStatLookupEncoding(rfbClientPtr cl,uint32_t type)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
rfbStatLookupMessage(rfbClientPtr cl,uint32_t type)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
rfbStatRecordEncodingSentAdd(rfbClientPtr cl,uint32_t type,int byteCount)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
rfbStatRecordEncodingSent(rfbClientPtr cl,uint32_t type,int byteCount,int byteIfRaw)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
rfbStatRecordEncodingRcvd(rfbClientPtr cl,uint32_t type,int byteCount,int byteIfRaw)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
rfbStatRecordMessageSent(rfbClientPtr cl,uint32_t type,int byteCount,int byteIfRaw)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
rfbStatRecordMessageRcvd(rfbClientPtr cl,uint32_t type,int byteCount,int byteIfRaw)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
rfbStatGetSentBytes(rfbClientPtr cl)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
rfbStatGetSentBytesIfRaw(rfbClientPtr cl)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
rfbStatGetRcvdBytes(rfbClientPtr cl)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
rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl)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
rfbStatGetMessageCountSent(rfbClientPtr cl,uint32_t type)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 }
rfbStatGetMessageCountRcvd(rfbClientPtr cl,uint32_t type)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
rfbStatGetEncodingCountSent(rfbClientPtr cl,uint32_t type)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 }
rfbStatGetEncodingCountRcvd(rfbClientPtr cl,uint32_t type)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
rfbResetStats(rfbClientPtr cl)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
rfbPrintStats(rfbClientPtr cl)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