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