Home | History | Annotate | Download | only in libvncserver
      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