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 #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 
     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 
     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  */
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 }
    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 
    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 }
    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 
    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 
    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