Migrating to new directory structure adopted from the RealVNC's source tree. More changes will follow.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@589 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx
new file mode 100644
index 0000000..1422b54
--- /dev/null
+++ b/common/rfb/SConnection.cxx
@@ -0,0 +1,322 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  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 <stdio.h>
+#include <string.h>
+#include <rfb/Exception.h>
+#include <rfb/secTypes.h>
+#include <rfb/SMsgReaderV3.h>
+#include <rfb/SMsgWriterV3.h>
+#include <rfb/SConnection.h>
+#include <rfb/ServerCore.h>
+
+#include <rfb/LogWriter.h>
+
+using namespace rfb;
+
+static LogWriter vlog("SConnection");
+
+// AccessRights values
+const SConnection::AccessRights SConnection::AccessView       = 0x0001;
+const SConnection::AccessRights SConnection::AccessKeyEvents  = 0x0002;
+const SConnection::AccessRights SConnection::AccessPtrEvents  = 0x0004;
+const SConnection::AccessRights SConnection::AccessCutText    = 0x0008;
+const SConnection::AccessRights SConnection::AccessDefault    = 0x03ff;
+const SConnection::AccessRights SConnection::AccessNoQuery    = 0x0400;
+const SConnection::AccessRights SConnection::AccessFull       = 0xffff;
+
+
+SConnection::SConnection(SSecurityFactory* secFact, bool reverseConnection_)
+  : readyForSetColourMapEntries(false),
+    is(0), os(0), reader_(0), writer_(0),
+    security(0), securityFactory(secFact), state_(RFBSTATE_UNINITIALISED),
+    reverseConnection(reverseConnection_)
+{
+  defaultMajorVersion = 3;
+  defaultMinorVersion = 8;
+  if (rfb::Server::protocol3_3)
+    defaultMinorVersion = 3;
+
+  cp.setVersion(defaultMajorVersion, defaultMinorVersion);
+}
+
+SConnection::~SConnection()
+{
+  if (security) security->destroy();
+  deleteReaderAndWriter();
+}
+
+void SConnection::deleteReaderAndWriter()
+{
+  delete reader_;
+  reader_ = 0;
+  delete writer_;
+  writer_ = 0;
+}
+
+void SConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
+{
+  is = is_;
+  os = os_;
+}
+
+void SConnection::initialiseProtocol()
+{
+  cp.writeVersion(os);
+  state_ = RFBSTATE_PROTOCOL_VERSION;
+}
+
+void SConnection::processMsg()
+{
+  switch (state_) {
+  case RFBSTATE_PROTOCOL_VERSION: processVersionMsg();      break;
+  case RFBSTATE_SECURITY_TYPE:    processSecurityTypeMsg(); break;
+  case RFBSTATE_SECURITY:         processSecurityMsg();     break;
+  case RFBSTATE_INITIALISATION:   processInitMsg();         break;
+  case RFBSTATE_NORMAL:           reader_->readMsg();       break;
+  case RFBSTATE_QUERYING:
+    throw Exception("SConnection::processMsg: bogus data from client while "
+                    "querying");
+  case RFBSTATE_UNINITIALISED:
+    throw Exception("SConnection::processMsg: not initialised yet?");
+  default:
+    throw Exception("SConnection::processMsg: invalid state");
+  }
+}
+
+void SConnection::processVersionMsg()
+{
+  vlog.debug("reading protocol version");
+  bool done;
+  if (!cp.readVersion(is, &done)) {
+    state_ = RFBSTATE_INVALID;
+    throw Exception("reading version failed: not an RFB client?");
+  }
+  if (!done) return;
+
+  vlog.info("Client needs protocol version %d.%d",
+            cp.majorVersion, cp.minorVersion);
+
+  if (cp.majorVersion != 3) {
+    // unknown protocol version
+    char msg[256];
+    sprintf(msg,"Error: client needs protocol version %d.%d, server has %d.%d",
+            cp.majorVersion, cp.minorVersion,
+            defaultMajorVersion, defaultMinorVersion);
+    throwConnFailedException(msg);
+  }
+
+  if (cp.minorVersion != 3 && cp.minorVersion != 7 && cp.minorVersion != 8) {
+    vlog.error("Client uses unofficial protocol version %d.%d",
+               cp.majorVersion,cp.minorVersion);
+    if (cp.minorVersion >= 8)
+      cp.minorVersion = 8;
+    else if (cp.minorVersion == 7)
+      cp.minorVersion = 7;
+    else
+      cp.minorVersion = 3;
+    vlog.error("Assuming compatibility with version %d.%d",
+               cp.majorVersion,cp.minorVersion);
+  }
+
+  versionReceived();
+
+  std::list<rdr::U8> secTypes;
+  std::list<rdr::U8>::iterator i;
+  securityFactory->getSecTypes(&secTypes, reverseConnection);
+
+  if (cp.isVersion(3,3)) {
+
+    // cope with legacy 3.3 client only if "no authentication" or "vnc
+    // authentication" is supported.
+    for (i=secTypes.begin(); i!=secTypes.end(); i++) {
+      if (*i == secTypeNone || *i == secTypeVncAuth) break;
+    }
+    if (i == secTypes.end()) {
+      char msg[256];
+      sprintf(msg,"No supported security type for %d.%d client",
+              cp.majorVersion, cp.minorVersion);
+      throwConnFailedException(msg);
+    }
+
+    os->writeU32(*i);
+    if (*i == secTypeNone) os->flush();
+    state_ = RFBSTATE_SECURITY;
+    security = securityFactory->getSSecurity(*i, reverseConnection);
+    processSecurityMsg();
+    return;
+  }
+
+  // list supported security types for >=3.7 clients
+
+  if (secTypes.empty())
+    throwConnFailedException("No supported security types");
+
+  os->writeU8(secTypes.size());
+  for (i=secTypes.begin(); i!=secTypes.end(); i++)
+    os->writeU8(*i);
+  os->flush();
+  state_ = RFBSTATE_SECURITY_TYPE;
+}
+
+
+void SConnection::processSecurityTypeMsg()
+{
+  vlog.debug("processing security type message");
+  int secType = is->readU8();
+
+  // Verify that the requested security type should be offered
+  std::list<rdr::U8> secTypes;
+  std::list<rdr::U8>::iterator i;
+  securityFactory->getSecTypes(&secTypes, reverseConnection);
+  for (i=secTypes.begin(); i!=secTypes.end(); i++)
+    if (*i == secType) break;
+  if (i == secTypes.end())
+    throw Exception("Requested security type not available");
+
+  vlog.info("Client requests security type %s(%d)",
+            secTypeName(secType),secType);
+
+  try {
+    state_ = RFBSTATE_SECURITY;
+    security = securityFactory->getSSecurity(secType, reverseConnection);
+  } catch (rdr::Exception& e) {
+    throwConnFailedException(e.str());
+  }
+
+  processSecurityMsg();
+}
+
+void SConnection::processSecurityMsg()
+{
+  vlog.debug("processing security message");
+  try {
+    bool done = security->processMsg(this);
+    if (done) {
+      state_ = RFBSTATE_QUERYING;
+      queryConnection(security->getUserName());
+    }
+  } catch (AuthFailureException& e) {
+    vlog.error("AuthFailureException: %s", e.str());
+    os->writeU32(secResultFailed);
+    if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
+      os->writeString(e.str());
+    os->flush();
+    throw;
+  }
+}
+
+void SConnection::processInitMsg()
+{
+  vlog.debug("reading client initialisation");
+  reader_->readClientInit();
+}
+
+void SConnection::throwConnFailedException(const char* msg)
+{
+  vlog.info(msg);
+  if (state_ == RFBSTATE_PROTOCOL_VERSION) {
+    if (cp.majorVersion == 3 && cp.minorVersion == 3) {
+      os->writeU32(0);
+      os->writeString(msg);
+      os->flush();
+    } else {
+      os->writeU8(0);
+      os->writeString(msg);
+      os->flush();
+    }
+  }
+  state_ = RFBSTATE_INVALID;
+  throw ConnFailedException(msg);
+}
+
+void SConnection::writeConnFailedFromScratch(const char* msg,
+                                             rdr::OutStream* os)
+{
+  os->writeBytes("RFB 003.003\n", 12);
+  os->writeU32(0);
+  os->writeString(msg);
+  os->flush();
+}
+
+void SConnection::versionReceived()
+{
+}
+
+void SConnection::authSuccess()
+{
+}
+
+void SConnection::queryConnection(const char* userName)
+{
+  approveConnection(true);
+}
+
+void SConnection::approveConnection(bool accept, const char* reason)
+{
+  if (state_ != RFBSTATE_QUERYING)
+    throw Exception("SConnection::approveConnection: invalid state");
+
+  if (!reason) reason = "Authentication failure";
+
+  if (!cp.beforeVersion(3,8) || security->getType() != secTypeNone) {
+    if (accept) {
+      os->writeU32(secResultOK);
+    } else {
+      os->writeU32(secResultFailed);
+      if (!cp.beforeVersion(3,8)) // 3.8 onwards have failure message
+        os->writeString(reason);
+    }
+    os->flush();
+  }
+
+  if (accept) {
+    state_ = RFBSTATE_INITIALISATION;
+    reader_ = new SMsgReaderV3(this, is);
+    writer_ = new SMsgWriterV3(&cp, os);
+    authSuccess();
+  } else {
+    state_ = RFBSTATE_INVALID;
+    throw AuthFailureException(reason);
+  }
+}
+
+void SConnection::setInitialColourMap()
+{
+}
+
+void SConnection::clientInit(bool shared)
+{
+  writer_->writeServerInit();
+  state_ = RFBSTATE_NORMAL;
+}
+
+void SConnection::setPixelFormat(const PixelFormat& pf)
+{
+  SMsgHandler::setPixelFormat(pf);
+  readyForSetColourMapEntries = true;
+}
+
+void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
+{
+  if (!readyForSetColourMapEntries) {
+    readyForSetColourMapEntries = true;
+    if (!cp.pf().trueColour) {
+      setInitialColourMap();
+    }
+  }
+}