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/CConnection.cxx b/common/rfb/CConnection.cxx
new file mode 100644
index 0000000..36778f0
--- /dev/null
+++ b/common/rfb/CConnection.cxx
@@ -0,0 +1,276 @@
+/* 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/CMsgReaderV3.h>
+#include <rfb/CMsgWriterV3.h>
+#include <rfb/CSecurity.h>
+#include <rfb/secTypes.h>
+#include <rfb/CConnection.h>
+#include <rfb/util.h>
+
+#include <rfb/LogWriter.h>
+
+using namespace rfb;
+
+static LogWriter vlog("CConnection");
+
+CConnection::CConnection()
+  : is(0), os(0), reader_(0), writer_(0),
+    shared(false), security(0), nSecTypes(0), clientSecTypeOrder(false),
+    state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false)
+{
+}
+
+CConnection::~CConnection()
+{
+  if (security) security->destroy();
+  deleteReaderAndWriter();
+}
+
+void CConnection::deleteReaderAndWriter()
+{
+  delete reader_;
+  reader_ = 0;
+  delete writer_;
+  writer_ = 0;
+}
+
+void CConnection::setStreams(rdr::InStream* is_, rdr::OutStream* os_)
+{
+  is = is_;
+  os = os_;
+}
+
+void CConnection::addSecType(rdr::U8 secType)
+{
+  if (nSecTypes == maxSecTypes)
+    throw Exception("too many security types");
+  secTypes[nSecTypes++] = secType;
+}
+
+void CConnection::setClientSecTypeOrder(bool clientOrder) {
+  clientSecTypeOrder = clientOrder;
+}
+
+void CConnection::initialiseProtocol()
+{
+  state_ = RFBSTATE_PROTOCOL_VERSION;
+}
+
+void CConnection::processMsg()
+{
+  switch (state_) {
+
+  case RFBSTATE_PROTOCOL_VERSION: processVersionMsg();       break;
+  case RFBSTATE_SECURITY_TYPES:   processSecurityTypesMsg(); break;
+  case RFBSTATE_SECURITY:         processSecurityMsg();      break;
+  case RFBSTATE_SECURITY_RESULT:  processSecurityResultMsg(); break;
+  case RFBSTATE_INITIALISATION:   processInitMsg();          break;
+  case RFBSTATE_NORMAL:           reader_->readMsg();        break;
+  case RFBSTATE_UNINITIALISED:
+    throw Exception("CConnection::processMsg: not initialised yet?");
+  default:
+    throw Exception("CConnection::processMsg: invalid state");
+  }
+}
+
+void CConnection::processVersionMsg()
+{
+  vlog.debug("reading protocol version");
+  bool done;
+  if (!cp.readVersion(is, &done)) {
+    state_ = RFBSTATE_INVALID;
+    throw Exception("reading version failed: not an RFB server?");
+  }
+  if (!done) return;
+
+  vlog.info("Server supports RFB protocol version %d.%d",
+            cp.majorVersion, cp.minorVersion);
+
+  // The only official RFB protocol versions are currently 3.3, 3.7 and 3.8
+  if (cp.beforeVersion(3,3)) {
+    char msg[256];
+    sprintf(msg,"Server gave unsupported RFB protocol version %d.%d",
+            cp.majorVersion, cp.minorVersion);
+    vlog.error(msg);
+    state_ = RFBSTATE_INVALID;
+    throw Exception(msg);
+  } else if (useProtocol3_3 || cp.beforeVersion(3,7)) {
+    cp.setVersion(3,3);
+  } else if (cp.afterVersion(3,8)) {
+    cp.setVersion(3,8);
+  }
+
+  cp.writeVersion(os);
+  state_ = RFBSTATE_SECURITY_TYPES;
+
+  vlog.info("Using RFB protocol version %d.%d",
+            cp.majorVersion, cp.minorVersion);
+}
+
+
+void CConnection::processSecurityTypesMsg()
+{
+  vlog.debug("processing security types message");
+
+  int secType = secTypeInvalid;
+
+  if (cp.isVersion(3,3)) {
+
+    // legacy 3.3 server may only offer "vnc authentication" or "none"
+
+    secType = is->readU32();
+    if (secType == secTypeInvalid) {
+      throwConnFailedException();
+
+    } else if (secType == secTypeNone || secType == secTypeVncAuth) {
+      int j;
+      for (j = 0; j < nSecTypes; j++)
+        if (secTypes[j] == secType) break;
+      if (j == nSecTypes)
+        secType = secTypeInvalid;
+    } else {
+      vlog.error("Unknown 3.3 security type %d", secType);
+      throw Exception("Unknown 3.3 security type");
+    }
+
+  } else {
+
+    // >=3.7 server will offer us a list
+
+    int nServerSecTypes = is->readU8();
+    if (nServerSecTypes == 0)
+      throwConnFailedException();
+
+    int secTypePos = nSecTypes;
+    for (int i = 0; i < nServerSecTypes; i++) {
+      rdr::U8 serverSecType = is->readU8();
+      vlog.debug("Server offers security type %s(%d)",
+                 secTypeName(serverSecType),serverSecType);
+
+      // If we haven't already chosen a secType, try this one
+      // If we are using the client's preference for types,
+      // we keep trying types, to find the one that matches and
+      // which appears first in the client's list of supported types.
+      if (secType == secTypeInvalid || clientSecTypeOrder) {
+        for (int j = 0; j < nSecTypes; j++) {
+          if (secTypes[j] == serverSecType && j < secTypePos) {
+            secType = secTypes[j];
+            secTypePos = j;
+            break;
+          }
+        }
+        // NB: Continue reading the remaining server secTypes, but ignore them
+      }
+    }
+
+    // Inform the server of our decision
+    if (secType != secTypeInvalid) {
+      os->writeU8(secType);
+      os->flush();
+      vlog.debug("Choosing security type %s(%d)",secTypeName(secType),secType);
+    }
+  }
+
+  if (secType == secTypeInvalid) {
+    state_ = RFBSTATE_INVALID;
+    vlog.error("No matching security types");
+    throw Exception("No matching security types");
+  }
+
+  state_ = RFBSTATE_SECURITY;
+  security = getCSecurity(secType);
+  processSecurityMsg();
+}
+
+void CConnection::processSecurityMsg()
+{
+  vlog.debug("processing security message");
+  if (security->processMsg(this)) {
+    state_ = RFBSTATE_SECURITY_RESULT;
+    processSecurityResultMsg();
+  }
+}
+
+void CConnection::processSecurityResultMsg()
+{
+  vlog.debug("processing security result message");
+  int result;
+  if (cp.beforeVersion(3,8) && security->getType() == secTypeNone) {
+    result = secResultOK;
+  } else {
+    if (!is->checkNoWait(1)) return;
+    result = is->readU32();
+  }
+  switch (result) {
+  case secResultOK:
+    securityCompleted();
+    return;
+  case secResultFailed:
+    vlog.debug("auth failed");
+    break;
+  case secResultTooMany:
+    vlog.debug("auth failed - too many tries");
+    break;
+  default:
+    throw Exception("Unknown security result from server");
+  }
+  CharArray reason;
+  if (cp.beforeVersion(3,8))
+    reason.buf = strDup("Authentication failure");
+  else
+    reason.buf = is->readString();
+  state_ = RFBSTATE_INVALID;
+  throw AuthFailureException(reason.buf);
+}
+
+void CConnection::processInitMsg()
+{
+  vlog.debug("reading server initialisation");
+  reader_->readServerInit();
+}
+
+void CConnection::throwConnFailedException()
+{
+  state_ = RFBSTATE_INVALID;
+  CharArray reason;
+  reason.buf = is->readString();
+  throw ConnFailedException(reason.buf);
+}
+
+void CConnection::securityCompleted()
+{
+  state_ = RFBSTATE_INITIALISATION;
+  reader_ = new CMsgReaderV3(this, is);
+  writer_ = new CMsgWriterV3(&cp, os);
+  vlog.debug("Authentication success!");
+  authSuccess();
+  writer_->writeClientInit(shared);
+}
+
+void CConnection::authSuccess()
+{
+}
+
+void CConnection::serverInit()
+{
+  state_ = RFBSTATE_NORMAL;
+  vlog.debug("initialisation done");
+}