]> source.dussan.org Git - tigervnc.git/commitdiff
Implemented support for TightVNC protocol extensions in the server code. This version...
authorConstantin Kaplinsky <const@tightvnc.com>
Fri, 8 Sep 2006 12:55:37 +0000 (12:55 +0000)
committerConstantin Kaplinsky <const@tightvnc.com>
Fri, 8 Sep 2006 12:55:37 +0000 (12:55 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@651 3789f03b-4d11-0410-bbf8-ca57d06f2519

common/rfb/CapsContainer.cxx
common/rfb/CapsContainer.h
common/rfb/CapsList.cxx [new file with mode: 0644]
common/rfb/CapsList.h [new file with mode: 0644]
common/rfb/ConnParams.cxx
common/rfb/ConnParams.h
common/rfb/SConnection.cxx
common/rfb/SConnection.h
common/rfb/rfb.dsp

index 2eb91f64c0279684f8e1d1f15ba2406943f05734..cea5f3aaa1a758e16cae02b7777030deb584b114 100644 (file)
  * USA.
  */
 
+//
+// CapsContainer class implementation.
+// FIXME: Extend the comment.
+//
+
 #include <rfb/CapsContainer.h>
 
 using namespace rfb;
index 0abbff0b06d26f0daf9e5258bbe91b7e178b3255..c7c8ab2387fe0cc8ac93245c8f0a232fd518d96b 100644 (file)
@@ -50,7 +50,7 @@ namespace rfb {
   class CapsContainer {
   public:
     CapsContainer(int maxCaps = 64);
-    ~CapsContainer();
+    virtual ~CapsContainer();
 
     void add(const CapabilityInfo *capinfo, const char *desc = 0);
     void add(rdr::U32 code, const char *vendor, const char *name,
diff --git a/common/rfb/CapsList.cxx b/common/rfb/CapsList.cxx
new file mode 100644 (file)
index 0000000..e5f0aff
--- /dev/null
@@ -0,0 +1,81 @@
+/* Copyright (C) 2006 Constantin Kaplinsky. 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.
+ */
+
+//
+// CapsList class implementation.
+// FIXME: Extend the comment.
+//
+
+#include <rfb/CapsList.h>
+#include <rdr/OutStream.h>
+
+using namespace rfb;
+
+const char *const CapsList::VENDOR_STD = "STDV";
+const char *const CapsList::VENDOR_TIGHT = "TGHT";
+
+CapsList::CapsList(int maxCaps)
+  : CapsContainer(maxCaps)
+{
+}
+
+CapsList::~CapsList()
+{
+}
+
+void
+CapsList::addStandard(rdr::U32 code, const char *name)
+{
+  add3rdParty(code, name, VENDOR_STD);
+}
+
+void
+CapsList::addTightExt(rdr::U32 code, const char *name)
+{
+  add3rdParty(code, name, VENDOR_TIGHT);
+}
+
+void
+CapsList::add3rdParty(rdr::U32 code, const char *name, const char *vendor)
+{
+  add(code, vendor, name);
+
+  // NOTE: This code is a bit tricky and not the most efficient. However,
+  //       that's not a problem as we prefer simplicity to performance here.
+  //       Here we need to "enable capability" but that requires comparing
+  //       name and vendor strings. So we just make CapsContainer compare
+  //       the same strings with themselves.
+  CapabilityInfo tmp;
+  if (getInfo(code, &tmp))
+    enable(&tmp);
+}
+
+void
+CapsList::write(rdr::OutStream* os) const
+{
+  int count = getSize();
+  CapabilityInfo cap;
+
+  for (int i = 0; i < count; i++) {
+    getInfo(getByOrder(i), &cap);
+    os->writeU32(cap.code);
+    os->writeBytes(&cap.vendorSignature, 4);
+    os->writeBytes(&cap.nameSignature, 8);
+  }
+}
+
diff --git a/common/rfb/CapsList.h b/common/rfb/CapsList.h
new file mode 100644 (file)
index 0000000..ce17aab
--- /dev/null
@@ -0,0 +1,58 @@
+/* Copyright (C) 2006 Constantin Kaplinsky. 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.
+ */
+
+//
+// CapsList class declaration.
+// FIXME: Extend the comment.
+//
+
+#ifndef __RFB_CAPSLIST_H__
+#define __RFB_CAPSLIST_H__
+
+#include <rfb/CapsContainer.h>
+
+namespace rdr { class OutStream; }
+
+namespace rfb {
+
+  // NOTE: Here we use the CapsContainer class for an off-design purpose.
+  //       However, that class is so good that I believe it's better to
+  //       use its well-tested reliable code instead of writing new class
+  //       from the scratch.
+
+  class CapsList : private CapsContainer {
+  public:
+    CapsList(int maxCaps = 64);
+    virtual ~CapsList();
+
+    int getSize() const { return numEnabled(); }
+
+    void addStandard(rdr::U32 code, const char *name);
+    void addTightExt(rdr::U32 code, const char *name);
+    void add3rdParty(rdr::U32 code, const char *name, const char *vendor);
+
+    void write(rdr::OutStream* os) const;
+
+  protected:
+    static const char *const VENDOR_STD;
+    static const char *const VENDOR_TIGHT;
+  };
+
+}
+
+#endif // __RFB_CAPSLIST_H__
index d4ae58945e47456da1becbd7997f434dbb81087a..42134c3c7ae4d540de534cf37e5b3bb7e935b759 100644 (file)
@@ -26,7 +26,8 @@
 using namespace rfb;
 
 ConnParams::ConnParams()
-  : majorVersion(0), minorVersion(0), width(0), height(0), useCopyRect(false),
+  : majorVersion(0), minorVersion(0), tightExtensionsEnabled(false),
+    width(0), height(0), useCopyRect(false),
     supportsLocalCursor(false), supportsLocalXCursor(false), supportsDesktopResize(true),
     supportsLastRect(false), customCompressLevel(false), compressLevel(6),
     noJpeg(false), qualityLevel(-1), 
index 47e6a5fb7c2e2145211f22d15cd433f8f497f691..e29adf879f978a9000048031540c9b97a7dce4cb 100644 (file)
@@ -39,6 +39,7 @@ namespace rfb {
 
     int majorVersion;
     int minorVersion;
+    bool tightExtensionsEnabled;
 
     void setVersion(int major, int minor) {
       majorVersion = major; minorVersion = minor;
index 3901a81190970eb865df329818c2ce6df35b5f51..d97be6cbd75b034aa593970b7887366084fb57e5 100644 (file)
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <rfb/Exception.h>
 #include <rfb/secTypes.h>
+#include <rfb/CapsList.h>
 #include <rfb/SMsgReaderV3.h>
 #include <rfb/SMsgWriterV3.h>
 #include <rfb/SConnection.h>
@@ -85,6 +86,8 @@ void SConnection::processMsg()
   switch (state_) {
   case RFBSTATE_PROTOCOL_VERSION: processVersionMsg();      break;
   case RFBSTATE_SECURITY_TYPE:    processSecurityTypeMsg(); break;
+  case RFBSTATE_TIGHT_TUNN_TYPE:  processTunnelTypeMsg();   break;
+  case RFBSTATE_TIGHT_AUTH_TYPE:  processAuthTypeMsg();     break;
   case RFBSTATE_SECURITY:         processSecurityMsg();     break;
   case RFBSTATE_INITIALISATION:   processInitMsg();         break;
   case RFBSTATE_NORMAL:           reader_->readMsg();       break;
@@ -161,6 +164,9 @@ void SConnection::processVersionMsg()
     return;
   }
 
+  // Add a special security type to advertise TightVNC protocol extensions.
+  secTypes.push_back(secTypeTight);
+
   // list supported security types for >=3.7 clients
 
   if (secTypes.empty())
@@ -179,9 +185,100 @@ void SConnection::processSecurityTypeMsg()
   vlog.debug("processing security type message");
   int secType = is->readU8();
 
+  if (secType == secTypeTight) {
+    vlog.info("Enabling TightVNC protocol extensions");
+    cp.tightExtensionsEnabled = true;
+    offerTunneling();
+  } else {
+    processSecurityType(secType);
+  }
+}
+
+//
+// TightVNC-specific protocol initialization (tunneling, authentication)
+//
+
+void SConnection::offerTunneling()
+{
+  vlog.debug("offering list of tunneling methods");
+  int nTypes = 0;
+
+  // Advertise our tunneling capabilities (currently, nothing to advertise).
+  os->writeU32(nTypes);
+
+  if (nTypes) {
+    state_ = RFBSTATE_TIGHT_TUNN_TYPE;
+  } else {
+    offerAuthentication();
+  }
+}
+
+// NOTE: This function is never called in current version.
+void SConnection::processTunnelTypeMsg()
+{
+  vlog.debug("processing tunneling type message (TightVNC extension)");
+  int tunnelType = is->readU32();
+  vlog.error("unsupported tunneling type %d requested, ignoring", tunnelType);
+  offerAuthentication();
+}
+
+void SConnection::offerAuthentication()
+{
+  vlog.debug("offering list of authentication methods");
+
+  // FIXME: Security types and TightVNC's auth types should be distinguished
+  //        although we use the same codes for NoAuth and VncAuth.
+
+  // See processVersionMsg(), the code below is very similar.
+  std::list<rdr::U8> secTypes;
+  std::list<rdr::U8>::iterator i;
+  securityFactory->getSecTypes(&secTypes, reverseConnection);
+
+  if (secTypes.empty())
+    throwConnFailedException("No supported security types");
+
+  // FIXME: We should send an empty list for "no authentication".
+
+  CapsList caps;
+  for (i = secTypes.begin(); i != secTypes.end(); i++) {
+    // FIXME: Use mapping instead (authType -> ProtocolCapability).
+    //        Each auth type should provide its capability data.
+    // FIXME: Check that client will send auth type listed in capabilities.
+    //        Currently, capabilities should duplicate secTypes exactly,
+    //        but that may change in the future.
+    switch(*i) {
+    case secTypeNone:
+      caps.addStandard(secTypeNone, "NOAUTH__");
+      break;
+    case secTypeVncAuth:
+      caps.addStandard(secTypeVncAuth, "VNCAUTH_");
+      break;
+    }
+  }
+  os->writeU32(caps.getSize());
+  caps.write(os);
+  os->flush();
+
+  // FIXME: Capability list is never empty here, otherwise
+  //        we would not expect authentication type message.
+  state_ = RFBSTATE_TIGHT_AUTH_TYPE;
+}
+
+void SConnection::processAuthTypeMsg()
+{
+  vlog.debug("processing authentication type message (TightVNC extension)");
+
+  // FIXME: Security types and TightVNC's auth types should be distinguished
+  //        although we use the same codes for NoAuth and VncAuth.
+
+  int secType = is->readU32();
   processSecurityType(secType);
 }
 
+//
+// End of TightVNC-specific code
+//
+
 void SConnection::processSecurityType(int secType)
 {
   // Verify that the requested security type should be offered
@@ -307,9 +404,54 @@ void SConnection::setInitialColourMap()
 void SConnection::clientInit(bool shared)
 {
   writer_->writeServerInit();
+  
+  // FIXME: Is this a right place for this code?
+  if (cp.tightExtensionsEnabled)
+    sendInteractionCaps();
+
   state_ = RFBSTATE_NORMAL;
 }
 
+// FIXME: Is this class a right place for this function?
+void SConnection::sendInteractionCaps()
+{
+  // Advertise support for non-standard server-to-client messages.
+  CapsList scaps;
+  int nServerMsgTypes = scaps.getSize();
+
+  // Advertise support for non-standard client-to-server messages.
+  CapsList ccaps;
+  int nClientMsgTypes = ccaps.getSize();
+
+  // Advertise all supported encoding types (except raw encoding).
+  CapsList ecaps;
+  // FIXME: Add actually registered encodings (and CopyRect which is special).
+  //        Ideally, encoders themselves should provide capability info.
+  ecaps.addStandard(encodingCopyRect,             "COPYRECT");
+  ecaps.addStandard(encodingRRE,                  "RRE_____");
+  ecaps.addStandard(encodingHextile,              "HEXTILE_");
+  ecaps.addStandard(encodingZRLE,                 "ZRLE____");
+  ecaps.addTightExt(encodingTight,                "TIGHT___");
+  ecaps.addTightExt(pseudoEncodingCompressLevel0, "COMPRLVL");
+  ecaps.addTightExt(pseudoEncodingQualityLevel0,  "JPEGQLVL");
+  ecaps.addTightExt(pseudoEncodingXCursor,        "X11CURSR");
+  ecaps.addTightExt(pseudoEncodingCursor,         "RCHCURSR");
+  ecaps.addTightExt(pseudoEncodingLastRect,       "LASTRECT");
+  ecaps.addStandard(pseudoEncodingDesktopSize,    "NEWFBSIZ");
+
+  os->writeU16(scaps.getSize());
+  os->writeU16(ccaps.getSize());
+  os->writeU16(ecaps.getSize());
+  os->writeU16(0);
+  if (scaps.getSize())
+    scaps.write(os);
+  if (ccaps.getSize())
+    ccaps.write(os);
+  if (ecaps.getSize())
+    ecaps.write(os);
+  os->flush();
+}
+
 void SConnection::setPixelFormat(const PixelFormat& pf)
 {
   SMsgHandler::setPixelFormat(pf);
index 4c766315db3532268840f254f260fc188082575a..e41ef5fb1f43d40c04f92dc7b38467caac00271f 100644 (file)
@@ -155,6 +155,8 @@ namespace rfb {
       RFBSTATE_UNINITIALISED,
       RFBSTATE_PROTOCOL_VERSION,
       RFBSTATE_SECURITY_TYPE,
+      RFBSTATE_TIGHT_TUNN_TYPE,
+      RFBSTATE_TIGHT_AUTH_TYPE,
       RFBSTATE_SECURITY,
       RFBSTATE_QUERYING,
       RFBSTATE_INITIALISATION,
@@ -180,6 +182,13 @@ namespace rfb {
     void processSecurityMsg();
     void processInitMsg();
 
+    // These functions add support for TightVNC protocol extensions.
+    void offerTunneling();
+    void processTunnelTypeMsg();
+    void offerAuthentication();
+    void processAuthTypeMsg();
+    void sendInteractionCaps();
+
     int defaultMajorVersion, defaultMinorVersion;
     rdr::InStream* is;
     rdr::OutStream* os;
index a39ef84e19d1bbae7e5bb780c093b0f4292fa486..f24563e067b6c1dc97d30ad02b85c6cb8e713d11 100644 (file)
@@ -118,6 +118,10 @@ SOURCE=.\CapsContainer.cxx
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\CapsList.cxx\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\CConnection.cxx\r
 # End Source File\r
 # Begin Source File\r
@@ -385,6 +389,10 @@ SOURCE=.\CapsContainer.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\CapsList.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\CConnection.h\r
 # End Source File\r
 # Begin Source File\r