add libvncserver
[presencevnc] / libvnc / libvncserver / stats.c
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
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 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;
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 rfbKeyFrameRequest:          snprintf(buf, len, "KeyFrameRequest"); break;
80     case rfbPalmVNCSetScaleFactor:    snprintf(buf, len, "PalmVNCSetScale"); 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 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;
117
118     case rfbEncodingXCursor:            snprintf(buf, len, "Xcursor");     break;
119     case rfbEncodingRichCursor:         snprintf(buf, len, "RichCursor");  break;
120     case rfbEncodingPointerPos:         snprintf(buf, len, "PointerPos");  break;
121
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;
128
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;
140     
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;
151
152
153     default:
154         snprintf(buf, len, "Enc(0x%08X)", type);
155     }
156
157     return buf;
158 }
159
160
161
162
163
164 rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type)
165 {
166     rfbStatList *ptr;
167     if (cl==NULL) return NULL;
168     for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
169     {
170         if (ptr->type==type) return ptr;
171     }
172     /* Well, we are here... need to *CREATE* an entry */
173     ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
174     if (ptr!=NULL)
175     {
176         memset((char *)ptr, 0, sizeof(rfbStatList));
177         ptr->type = type;
178         /* add to the top of the list */
179         ptr->Next = cl->statEncList;
180         cl->statEncList = ptr;
181     }
182     return ptr;
183 }
184
185
186 rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type)
187 {
188     rfbStatList *ptr;
189     if (cl==NULL) return NULL;
190     for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
191     {
192         if (ptr->type==type) return ptr;
193     }
194     /* Well, we are here... need to *CREATE* an entry */
195     ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
196     if (ptr!=NULL)
197     {
198         memset((char *)ptr, 0, sizeof(rfbStatList));
199         ptr->type = type;
200         /* add to the top of the list */
201         ptr->Next = cl->statMsgList;
202         cl->statMsgList = ptr;
203     }
204     return ptr;
205 }
206
207 void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */
208 {
209     rfbStatList *ptr;
210
211     ptr = rfbStatLookupEncoding(cl, type);
212     if (ptr!=NULL)
213         ptr->bytesSent      += byteCount;
214 }
215
216
217 void  rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
218 {
219     rfbStatList *ptr;
220
221     ptr = rfbStatLookupEncoding(cl, type);
222     if (ptr!=NULL)
223     {
224         ptr->sentCount++;
225         ptr->bytesSent      += byteCount;
226         ptr->bytesSentIfRaw += byteIfRaw;
227     }
228 }
229
230 void  rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
231 {
232     rfbStatList *ptr;
233
234     ptr = rfbStatLookupEncoding(cl, type);
235     if (ptr!=NULL)
236     {
237         ptr->rcvdCount++;
238         ptr->bytesRcvd      += byteCount;
239         ptr->bytesRcvdIfRaw += byteIfRaw;
240     }
241 }
242
243 void  rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
244 {
245     rfbStatList *ptr;
246
247     ptr = rfbStatLookupMessage(cl, type);
248     if (ptr!=NULL)
249     {
250         ptr->sentCount++;
251         ptr->bytesSent      += byteCount;
252         ptr->bytesSentIfRaw += byteIfRaw;
253     }
254 }
255
256 void  rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
257 {
258     rfbStatList *ptr;
259
260     ptr = rfbStatLookupMessage(cl, type);
261     if (ptr!=NULL)
262     {
263         ptr->rcvdCount++;
264         ptr->bytesRcvd      += byteCount;
265         ptr->bytesRcvdIfRaw += byteIfRaw;
266     }
267 }
268
269
270 int rfbStatGetSentBytes(rfbClientPtr cl)
271 {
272     rfbStatList *ptr=NULL;
273     int bytes=0;
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;
279     return bytes;
280 }
281
282 int rfbStatGetSentBytesIfRaw(rfbClientPtr cl)
283 {
284     rfbStatList *ptr=NULL;
285     int bytes=0;
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;
291     return bytes;
292 }
293
294 int rfbStatGetRcvdBytes(rfbClientPtr cl)
295 {
296     rfbStatList *ptr=NULL;
297     int bytes=0;
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;
303     return bytes;
304 }
305
306 int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl)
307 {
308     rfbStatList *ptr=NULL;
309     int bytes=0;
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;
315     return bytes;
316 }
317
318 int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type)
319 {
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;
324   return 0;
325 }
326 int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type)
327 {
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;
332   return 0;
333 }
334
335 int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type)
336 {
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;
341   return 0;
342 }
343 int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type)
344 {
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;
349   return 0;
350 }
351
352
353
354
355 void rfbResetStats(rfbClientPtr cl)
356 {
357     rfbStatList *ptr;
358     if (cl==NULL) return;
359     while (cl->statEncList!=NULL)
360     {
361         ptr = cl->statEncList;
362         cl->statEncList = ptr->Next;
363         free(ptr);
364     }
365     while (cl->statMsgList!=NULL)
366     {
367         ptr = cl->statMsgList;
368         cl->statMsgList = ptr->Next;
369         free(ptr);
370     }
371 }
372
373
374 void rfbPrintStats(rfbClientPtr cl)
375 {
376     rfbStatList *ptr=NULL;
377     char encBuf[64];
378     double savings=0.0;
379     int    totalRects=0;
380     double totalBytes=0.0;
381     double totalBytesIfRaw=0.0;
382
383     char *name=NULL;
384     int bytes=0;
385     int bytesIfRaw=0;
386     int count=0;
387
388     if (cl==NULL) return;
389     
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)
392     {
393         name       = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf));
394         count      = ptr->sentCount;
395         bytes      = ptr->bytesSent;
396         bytesIfRaw = ptr->bytesSentIfRaw;
397         
398         savings = 0.0;
399         if (bytesIfRaw>0.0)
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);
404         totalRects += count;
405         totalBytes += bytes;
406         totalBytesIfRaw += bytesIfRaw;
407     }
408
409     for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
410     {
411         name       = encodingName(ptr->type, encBuf, sizeof(encBuf));
412         count      = ptr->sentCount;
413         bytes      = ptr->bytesSent;
414         bytesIfRaw = ptr->bytesSentIfRaw;
415         savings    = 0.0;
416
417         if (bytesIfRaw>0.0)
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);
422         totalRects += count;
423         totalBytes += bytes;
424         totalBytesIfRaw += bytesIfRaw;
425     }
426     savings=0.0;
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);
431
432     totalRects=0.0;
433     totalBytes=0.0;
434     totalBytesIfRaw=0.0;
435
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)
438     {
439         name       = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf));
440         count      = ptr->rcvdCount;
441         bytes      = ptr->bytesRcvd;
442         bytesIfRaw = ptr->bytesRcvdIfRaw;
443         savings    = 0.0;
444
445         if (bytesIfRaw>0.0)
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);
450         totalRects += count;
451         totalBytes += bytes;
452         totalBytesIfRaw += bytesIfRaw;
453     }
454     for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
455     {
456         name       = encodingName(ptr->type, encBuf, sizeof(encBuf));
457         count      = ptr->rcvdCount;
458         bytes      = ptr->bytesRcvd;
459         bytesIfRaw = ptr->bytesRcvdIfRaw;
460         savings    = 0.0;
461
462         if (bytesIfRaw>0.0)
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);
467         totalRects += count;
468         totalBytes += bytes;
469         totalBytesIfRaw += bytesIfRaw;
470     }
471     savings=0.0;
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);
476       
477
478