added libvnc/ with RealVNC compatibility fix
[presencevnc] / libvnc / libvncserver / stats.c
diff --git a/libvnc/libvncserver/stats.c b/libvnc/libvncserver/stats.c
new file mode 100755 (executable)
index 0000000..d5d6925
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * stats.c
+ */
+
+/*
+ *  Copyright (C) 2002 RealVNC Ltd.
+ *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
+ *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.  
+ *  All Rights Reserved.
+ *
+ *  This is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This software is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ *  USA.
+ */
+
+#include <rfb/rfb.h>
+
+char *messageNameServer2Client(uint32_t type, char *buf, int len);
+char *messageNameClient2Server(uint32_t type, char *buf, int len);
+char *encodingName(uint32_t enc, char *buf, int len);
+
+rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type);
+rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type);
+
+void  rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
+void  rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
+void  rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
+void  rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw);
+void rfbResetStats(rfbClientPtr cl);
+void rfbPrintStats(rfbClientPtr cl);
+
+
+
+
+char *messageNameServer2Client(uint32_t type, char *buf, int len) {
+    if (buf==NULL) return "error";
+    switch (type) {
+    case rfbFramebufferUpdate:        snprintf(buf, len, "FramebufferUpdate"); break;
+    case rfbSetColourMapEntries:      snprintf(buf, len, "SetColourMapEntries"); break;
+    case rfbBell:                     snprintf(buf, len, "Bell"); break;
+    case rfbServerCutText:            snprintf(buf, len, "ServerCutText"); break;
+    case rfbResizeFrameBuffer:        snprintf(buf, len, "ResizeFrameBuffer"); break;
+    case rfbKeyFrameUpdate:           snprintf(buf, len, "KeyFrameUpdate"); break;
+    case rfbFileTransfer:             snprintf(buf, len, "FileTransfer"); break;
+    case rfbTextChat:                 snprintf(buf, len, "TextChat"); break;
+    case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break;
+    default:
+        snprintf(buf, len, "svr2cli-0x%08X", 0xFF);
+    }
+    return buf;
+}
+
+char *messageNameClient2Server(uint32_t type, char *buf, int len) {
+    if (buf==NULL) return "error";
+    switch (type) {
+    case rfbSetPixelFormat:           snprintf(buf, len, "SetPixelFormat"); break;
+    case rfbFixColourMapEntries:      snprintf(buf, len, "FixColourMapEntries"); break;
+    case rfbSetEncodings:             snprintf(buf, len, "SetEncodings"); break;
+    case rfbFramebufferUpdateRequest: snprintf(buf, len, "FramebufferUpdate"); break;
+    case rfbKeyEvent:                 snprintf(buf, len, "KeyEvent"); break;
+    case rfbPointerEvent:             snprintf(buf, len, "PointerEvent"); break;
+    case rfbClientCutText:            snprintf(buf, len, "ClientCutText"); break;
+    case rfbFileTransfer:             snprintf(buf, len, "FileTransfer"); break;
+    case rfbSetScale:                 snprintf(buf, len, "SetScale"); break;
+    case rfbSetServerInput:           snprintf(buf, len, "SetServerInput"); break;
+    case rfbSetSW:                    snprintf(buf, len, "SetSingleWindow"); break;
+    case rfbTextChat:                 snprintf(buf, len, "TextChat"); break;
+    case rfbKeyFrameRequest:          snprintf(buf, len, "KeyFrameRequest"); break;
+    case rfbPalmVNCSetScaleFactor:    snprintf(buf, len, "PalmVNCSetScale"); break;
+    default:
+        snprintf(buf, len, "cli2svr-0x%08X", type);
+
+
+    }
+    return buf;
+}
+
+/* Encoding name must be <=16 characters to fit nicely on the status output in
+ * an 80 column terminal window
+ */
+char *encodingName(uint32_t type, char *buf, int len) {
+    if (buf==NULL) return "error";
+    
+    switch (type) {
+    case rfbEncodingRaw:                snprintf(buf, len, "raw");         break;
+    case rfbEncodingCopyRect:           snprintf(buf, len, "copyRect");    break;
+    case rfbEncodingRRE:                snprintf(buf, len, "RRE");         break;
+    case rfbEncodingCoRRE:              snprintf(buf, len, "CoRRE");       break;
+    case rfbEncodingHextile:            snprintf(buf, len, "hextile");     break;
+    case rfbEncodingZlib:               snprintf(buf, len, "zlib");        break;
+    case rfbEncodingTight:              snprintf(buf, len, "tight");       break;
+    case rfbEncodingZlibHex:            snprintf(buf, len, "zlibhex");     break;
+    case rfbEncodingUltra:              snprintf(buf, len, "ultra");       break;
+    case rfbEncodingZRLE:               snprintf(buf, len, "ZRLE");        break;
+    case rfbEncodingZYWRLE:             snprintf(buf, len, "ZYWRLE");      break;
+    case rfbEncodingCache:              snprintf(buf, len, "cache");       break;
+    case rfbEncodingCacheEnable:        snprintf(buf, len, "cacheEnable"); break;
+    case rfbEncodingXOR_Zlib:           snprintf(buf, len, "xorZlib");     break;
+    case rfbEncodingXORMonoColor_Zlib:  snprintf(buf, len, "xorMonoZlib");  break;
+    case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break;
+    case rfbEncodingSolidColor:         snprintf(buf, len, "solidColor");  break;
+    case rfbEncodingXOREnable:          snprintf(buf, len, "xorEnable");   break;
+    case rfbEncodingCacheZip:           snprintf(buf, len, "cacheZip");    break;
+    case rfbEncodingSolMonoZip:         snprintf(buf, len, "monoZip");     break;
+    case rfbEncodingUltraZip:           snprintf(buf, len, "ultraZip");    break;
+
+    case rfbEncodingXCursor:            snprintf(buf, len, "Xcursor");     break;
+    case rfbEncodingRichCursor:         snprintf(buf, len, "RichCursor");  break;
+    case rfbEncodingPointerPos:         snprintf(buf, len, "PointerPos");  break;
+
+    case rfbEncodingLastRect:           snprintf(buf, len, "LastRect");    break;
+    case rfbEncodingNewFBSize:          snprintf(buf, len, "NewFBSize");   break;
+    case rfbEncodingKeyboardLedState:   snprintf(buf, len, "LedState");    break;
+    case rfbEncodingSupportedMessages:  snprintf(buf, len, "SupportedMessage");  break;
+    case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break;
+    case rfbEncodingServerIdentity:     snprintf(buf, len, "ServerIdentify");    break;
+
+    /* The following lookups do not report in stats */
+    case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0");  break;
+    case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1");  break;
+    case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2");  break;
+    case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3");  break;
+    case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4");  break;
+    case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5");  break;
+    case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6");  break;
+    case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7");  break;
+    case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8");  break;
+    case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9");  break;
+    
+    case rfbEncodingQualityLevel0:  snprintf(buf, len, "QualityLevel0");   break;
+    case rfbEncodingQualityLevel1:  snprintf(buf, len, "QualityLevel1");   break;
+    case rfbEncodingQualityLevel2:  snprintf(buf, len, "QualityLevel2");   break;
+    case rfbEncodingQualityLevel3:  snprintf(buf, len, "QualityLevel3");   break;
+    case rfbEncodingQualityLevel4:  snprintf(buf, len, "QualityLevel4");   break;
+    case rfbEncodingQualityLevel5:  snprintf(buf, len, "QualityLevel5");   break;
+    case rfbEncodingQualityLevel6:  snprintf(buf, len, "QualityLevel6");   break;
+    case rfbEncodingQualityLevel7:  snprintf(buf, len, "QualityLevel7");   break;
+    case rfbEncodingQualityLevel8:  snprintf(buf, len, "QualityLevel8");   break;
+    case rfbEncodingQualityLevel9:  snprintf(buf, len, "QualityLevel9");   break;
+
+
+    default:
+        snprintf(buf, len, "Enc(0x%08X)", type);
+    }
+
+    return buf;
+}
+
+
+
+
+
+rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type)
+{
+    rfbStatList *ptr;
+    if (cl==NULL) return NULL;
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+    {
+        if (ptr->type==type) return ptr;
+    }
+    /* Well, we are here... need to *CREATE* an entry */
+    ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
+    if (ptr!=NULL)
+    {
+        memset((char *)ptr, 0, sizeof(rfbStatList));
+        ptr->type = type;
+        /* add to the top of the list */
+        ptr->Next = cl->statEncList;
+        cl->statEncList = ptr;
+    }
+    return ptr;
+}
+
+
+rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type)
+{
+    rfbStatList *ptr;
+    if (cl==NULL) return NULL;
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+    {
+        if (ptr->type==type) return ptr;
+    }
+    /* Well, we are here... need to *CREATE* an entry */
+    ptr = (rfbStatList *)malloc(sizeof(rfbStatList));
+    if (ptr!=NULL)
+    {
+        memset((char *)ptr, 0, sizeof(rfbStatList));
+        ptr->type = type;
+        /* add to the top of the list */
+        ptr->Next = cl->statMsgList;
+        cl->statMsgList = ptr;
+    }
+    return ptr;
+}
+
+void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */
+{
+    rfbStatList *ptr;
+
+    ptr = rfbStatLookupEncoding(cl, type);
+    if (ptr!=NULL)
+        ptr->bytesSent      += byteCount;
+}
+
+
+void  rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
+{
+    rfbStatList *ptr;
+
+    ptr = rfbStatLookupEncoding(cl, type);
+    if (ptr!=NULL)
+    {
+        ptr->sentCount++;
+        ptr->bytesSent      += byteCount;
+        ptr->bytesSentIfRaw += byteIfRaw;
+    }
+}
+
+void  rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
+{
+    rfbStatList *ptr;
+
+    ptr = rfbStatLookupEncoding(cl, type);
+    if (ptr!=NULL)
+    {
+        ptr->rcvdCount++;
+        ptr->bytesRcvd      += byteCount;
+        ptr->bytesRcvdIfRaw += byteIfRaw;
+    }
+}
+
+void  rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
+{
+    rfbStatList *ptr;
+
+    ptr = rfbStatLookupMessage(cl, type);
+    if (ptr!=NULL)
+    {
+        ptr->sentCount++;
+        ptr->bytesSent      += byteCount;
+        ptr->bytesSentIfRaw += byteIfRaw;
+    }
+}
+
+void  rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw)
+{
+    rfbStatList *ptr;
+
+    ptr = rfbStatLookupMessage(cl, type);
+    if (ptr!=NULL)
+    {
+        ptr->rcvdCount++;
+        ptr->bytesRcvd      += byteCount;
+        ptr->bytesRcvdIfRaw += byteIfRaw;
+    }
+}
+
+
+int rfbStatGetSentBytes(rfbClientPtr cl)
+{
+    rfbStatList *ptr=NULL;
+    int bytes=0;
+    if (cl==NULL) return 0;
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesSent;
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesSent;
+    return bytes;
+}
+
+int rfbStatGetSentBytesIfRaw(rfbClientPtr cl)
+{
+    rfbStatList *ptr=NULL;
+    int bytes=0;
+    if (cl==NULL) return 0;
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesSentIfRaw;
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesSentIfRaw;
+    return bytes;
+}
+
+int rfbStatGetRcvdBytes(rfbClientPtr cl)
+{
+    rfbStatList *ptr=NULL;
+    int bytes=0;
+    if (cl==NULL) return 0;
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesRcvd;
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesRcvd;
+    return bytes;
+}
+
+int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl)
+{
+    rfbStatList *ptr=NULL;
+    int bytes=0;
+    if (cl==NULL) return 0;
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesRcvdIfRaw;
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+        bytes += ptr->bytesRcvdIfRaw;
+    return bytes;
+}
+
+int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type)
+{
+  rfbStatList *ptr=NULL;
+    if (cl==NULL) return 0;
+  for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+      if (ptr->type==type) return ptr->sentCount;
+  return 0;
+}
+int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type)
+{
+  rfbStatList *ptr=NULL;
+    if (cl==NULL) return 0;
+  for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+      if (ptr->type==type) return ptr->rcvdCount;
+  return 0;
+}
+
+int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type)
+{
+  rfbStatList *ptr=NULL;
+    if (cl==NULL) return 0;
+  for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+      if (ptr->type==type) return ptr->sentCount;
+  return 0;
+}
+int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type)
+{
+  rfbStatList *ptr=NULL;
+    if (cl==NULL) return 0;
+  for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+      if (ptr->type==type) return ptr->rcvdCount;
+  return 0;
+}
+
+
+
+
+void rfbResetStats(rfbClientPtr cl)
+{
+    rfbStatList *ptr;
+    if (cl==NULL) return;
+    while (cl->statEncList!=NULL)
+    {
+        ptr = cl->statEncList;
+        cl->statEncList = ptr->Next;
+        free(ptr);
+    }
+    while (cl->statMsgList!=NULL)
+    {
+        ptr = cl->statMsgList;
+        cl->statMsgList = ptr->Next;
+        free(ptr);
+    }
+}
+
+
+void rfbPrintStats(rfbClientPtr cl)
+{
+    rfbStatList *ptr=NULL;
+    char encBuf[64];
+    double savings=0.0;
+    int    totalRects=0;
+    double totalBytes=0.0;
+    double totalBytesIfRaw=0.0;
+
+    char *name=NULL;
+    int bytes=0;
+    int bytesIfRaw=0;
+    int count=0;
+
+    if (cl==NULL) return;
+    
+    rfbLog("%-21.21s  %-6.6s   %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved");
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+    {
+        name       = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf));
+        count      = ptr->sentCount;
+        bytes      = ptr->bytesSent;
+        bytesIfRaw = ptr->bytesSentIfRaw;
+        
+        savings = 0.0;
+        if (bytesIfRaw>0.0)
+            savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
+        if ((bytes>0) || (count>0) || (bytesIfRaw>0))
+            rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
+               name, count, bytes, bytesIfRaw, savings);
+        totalRects += count;
+        totalBytes += bytes;
+        totalBytesIfRaw += bytesIfRaw;
+    }
+
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+    {
+        name       = encodingName(ptr->type, encBuf, sizeof(encBuf));
+        count      = ptr->sentCount;
+        bytes      = ptr->bytesSent;
+        bytesIfRaw = ptr->bytesSentIfRaw;
+        savings    = 0.0;
+
+        if (bytesIfRaw>0.0)
+            savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
+        if ((bytes>0) || (count>0) || (bytesIfRaw>0))
+            rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
+               name, count, bytes, bytesIfRaw, savings);
+        totalRects += count;
+        totalBytes += bytes;
+        totalBytesIfRaw += bytesIfRaw;
+    }
+    savings=0.0;
+    if (totalBytesIfRaw>0.0)
+        savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0);
+    rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n",
+            "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings);
+
+    totalRects=0.0;
+    totalBytes=0.0;
+    totalBytesIfRaw=0.0;
+
+    rfbLog("%-21.21s  %-6.6s   %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved");
+    for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next)
+    {
+        name       = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf));
+        count      = ptr->rcvdCount;
+        bytes      = ptr->bytesRcvd;
+        bytesIfRaw = ptr->bytesRcvdIfRaw;
+        savings    = 0.0;
+
+        if (bytesIfRaw>0.0)
+            savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
+        if ((bytes>0) || (count>0) || (bytesIfRaw>0))
+            rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
+               name, count, bytes, bytesIfRaw, savings);
+        totalRects += count;
+        totalBytes += bytes;
+        totalBytesIfRaw += bytesIfRaw;
+    }
+    for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next)
+    {
+        name       = encodingName(ptr->type, encBuf, sizeof(encBuf));
+        count      = ptr->rcvdCount;
+        bytes      = ptr->bytesRcvd;
+        bytesIfRaw = ptr->bytesRcvdIfRaw;
+        savings    = 0.0;
+
+        if (bytesIfRaw>0.0)
+            savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0);
+        if ((bytes>0) || (count>0) || (bytesIfRaw>0))
+            rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n",
+               name, count, bytes, bytesIfRaw, savings);
+        totalRects += count;
+        totalBytes += bytes;
+        totalBytesIfRaw += bytesIfRaw;
+    }
+    savings=0.0;
+    if (totalBytesIfRaw>0.0)
+        savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0);
+    rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n",
+            "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings);
+      
+} 
+