/**
 * Client send:
 * 2           - U8          - shared flag
 *
 * Server send:
 * 2           - U16         - framebuffer-width
 * 2           - U16         - framebuffer-height
 * 16          - PixelFormat - server-pixel-format
 * 4           - U32         - name-length
 * name-length - U8 array    - name-string
 */
void RemoteViewerCore::clientAndServerInit()
{
  if (m_sharedFlag) {
    m_logWriter.info(_T("Setting share flag in on..."));
  } else {
    m_logWriter.info(_T("Setting share flag is off..."));
  }
  m_output->writeUInt8(m_sharedFlag);
  m_output->flush();
  m_logWriter.debug(_T("Shared flag is set"));

  UINT16 width = m_input->readUInt16();
  UINT16 height = m_input->readUInt16();
  Dimension screenDimension(width, height);
  PixelFormat serverPixelFormat = readPixelFormat();
  
  {
    AutoLock al(&m_fbLock);
    setFbProperties(&screenDimension, &serverPixelFormat);
  }

  UINT32 sizeInBytes = m_input->readUInt32();
  std::vector<const char> buffer(sizeInBytes + 1);
  m_input->read(&buffer.front(), sizeInBytes);
  buffer[sizeInBytes] = '\0';
  AnsiStringStorage ansiStr;
  ansiStr.setString(&buffer[0]);
  ansiStr.toStringStorage(&m_remoteDesktopName);
  m_logWriter.info(_T("Server remote name: %s"), m_remoteDesktopName.getString());

  if (m_isTight) {
    m_logWriter.detail(_T("Reading tight capabilities"));
    readCapabilities();
  }
}
void ClipboardExchange::execute()
{
  while (!isTerminating()) {
    m_newClipWaiter.waitForEvent();

    if (m_hasNewClip && !isTerminating() && !m_viewOnly) {

      try {
        AutoLock al(m_output);
        m_output->writeUInt8(ServerMsgDefs::SERVER_CUT_TEXT); // type
        m_output->writeUInt8(0); // pad
        m_output->writeUInt16(0); // pad

        AnsiStringStorage charBuff;
        {
          AutoLock al(&m_storedClipMut);
          charBuff.fromStringStorage(&m_storedClip);
          m_hasNewClip = false;
        }
        size_t strLength = charBuff.getLength();
        m_output->writeUInt32((UINT32)strLength);
        m_output->writeFully(charBuff.getString(), strLength);

        m_output->flush();
      } catch (Exception &e) {
        m_log->error(_T("The clipboard thread force to terminate because")
                   _T(" it caught the error: %s"), e.getMessage());
        terminate();
      }
    }
  }
}
void RemoteViewerCore::handshake()
{
  char serverProtocol[13];
  serverProtocol[12] = 0;
  m_input->readFully(serverProtocol, 12);

  m_major = strtol(&serverProtocol[4], 0, 10);
  m_minor = strtol(&serverProtocol[8], 0, 10);
  m_isTight = false;

  m_logWriter.info(_T("Server sent protocol version: %s"), getProtocolString().getString());
  if (!isRfbProtocolString(serverProtocol) || 
      m_major < 3 ||
      (m_major == 3 && m_minor < 3)) {
    StringStorage error;
    AnsiStringStorage protocolAnsi(serverProtocol);
    StringStorage protocol;
    protocolAnsi.toStringStorage(&protocol);
    error.format(_T("Unsupported protocol: %s"), protocol.getString());
    m_logWriter.error(_T("%s"), error.getString());
    throw Exception(error.getString());
  }

  // if version is 4.0 or later, then set version 3.8.
  if (m_major > 3) {
    m_major = 3;
    m_minor = 8;
  } else { // else set version from list 3.3, 3.7, 3.8.
    // select minor version:
    if (m_minor < 7) {
      m_minor = 3;
    }
    if (m_minor >= 8) {
     m_minor = 8;
    }
  }

  m_logWriter.info(_T("Send to server protocol version: %s"), getProtocolString().getString());

  AnsiStringStorage clientProtocolAnsi;
  clientProtocolAnsi.fromStringStorage(&getProtocolString());
  m_output->writeFully(clientProtocolAnsi.getString(), 12);
  m_output->flush();
}