Logo Search packages:      
Sourcecode: kmess version File versions

msnwebcamconnection.cpp

/***************************************************************************
                          msnwebcamconnection.cpp -  description
                             -------------------
    begin                : Sun 08 31 2008
    copyright            : (C) 2008 by Diederik van der Boor
    email                : "vdboor" --at-- "codingdomain.com"
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "msnwebcamconnection.h"

#include <QBuffer>

#include "../../kmessdebug.h"
#include "../p2pmessage.h"   // only for P2PMessage::insertBytes()


#ifdef KMESSDEBUG_WEBCAMCONNECTION
  #define KMESSDEBUG_WEBCAMCONNECTION_GENERAL
  // note that enabling the KMESSDEBUG_WEBCAMCONNECTION_RECEIVING makes file transfer slow and inresponsive.
  #define KMESSDEBUG_WEBCAMCONNECTION_RECEIVING
#endif



/**
 * The constructor
 *
 * @param  contactHandle  Email address of the contact.
 * @param  recipientId    Negotiated ID of the recipient, used for authentication.
 * @param  sessionId      Negotiated ID of the session, used for authentication.
 */
00041 MsnWebcamConnection::MsnWebcamConnection(const QString &contactHandle, uint recipientId, uint sessionId)
 : DirectConnectionBase(0)
 , contactHandle_(contactHandle)
 , firstMessage_(true)
 , receiveMode_( MODE_AUTHENTICATION )
 , recipientId_(recipientId)
 , remainingBlockBytes_(0)
 , sessionId_(sessionId)
{
  setObjectName( "MsnWebcamConnection[" + contactHandle + "]" );

  buffer_.open( QIODevice::ReadWrite );
}



/**
 * The destructor
 */
00060 MsnWebcamConnection::~MsnWebcamConnection()
{
#ifdef KMESSDEBUG_WEBCAMCONNECTION_GENERAL
  kDebug() << "DESTROYED. [handle=" << contactHandle_ << "]";
#endif
}



// Return the contact handle
const QString& MsnWebcamConnection::getContactHandle() const
{
  return contactHandle_;
}



// Send the handshake packets
bool MsnWebcamConnection::initialize()
{
  // When this is the server, nothing needs to be sent.
  if(isServer())
  {
    return isConnected();
  }

#ifdef KMESSDEBUG_WEBCAMCONNECTION_GENERAL
  kDebug() << "sending preamble message";
#endif
#ifdef KMESS_NETWORK_WINDOW
  KMESS_NET_INIT(this, "CAM " + getRemoteIp());
#endif
  firstMessage_ = false;

  // Mark the time we received the message, to detect timeouts
  lastActivity_.start();

  // Send the authentication packet.
  QString message( "recipientid=" + QString::number( recipientId_ ) + "&sessionid=" + QString::number( sessionId_ ) + "\r\n\r\n" );
  return writeBlock( message.toUtf8() );
}



// Send the message to the contact
bool MsnWebcamConnection::sendMessage(const QByteArray &message)
{
#ifdef KMESSDEBUG_WEBCAMCONNECTION_GENERAL
  kDebug() << "sending message block (size=" << message.size() << ", handle=" << contactHandle_ << ")";
#endif
#ifdef KMESSTEST
  KMESS_ASSERT( message.size() <= 1352 );  // max message size for official client
  KMESS_ASSERT( ! hasTemporaryWriteError() );
#endif

  // KMESS_NET_SENT is called by the base class already.

  // Mark the time we received the message, to detect timeouts
  lastActivity_.start();

  // Send the message size in advance
  QByteArray lengthField( 4, 0x00 );
  P2PMessage::insertBytes( lengthField, message.size(), 0 );
  if( ! writeBlock( lengthField ) && ! hasTemporaryWriteError() )
  {
    kWarning() << "Unable to send the preamble block "
                   "(contact=" << contactHandle_ << ")." << endl;
    return false;
  }

  // Send the actual block
  return writeBlock( message );
}



// This is called when data is received from the socket.
void MsnWebcamConnection::slotSocketDataReceived()
{
  // Same algorithm as MsnDirectConnection::slotSocketDataReceived()
  QString command;
  int newBlockSize = 0;

  while( true )
  {
    // See what can be read from the socket.
    qint64 noBytesRead = readBlock( buffer_ );
    if( noBytesRead == 0 )
    {
#ifdef KMESSDEBUG_WEBCAMCONNECTION_GENERAL
      kDebug() << "Socket buffer is empty, will wait for new data (read=" << noBytesRead << ").";
#endif
      return;
    }
    else if( noBytesRead < 0 )
    {
#ifdef KMESSDEBUG_WEBCAMCONNECTION_GENERAL
      kDebug() << "Socket read returned an error (read=" << noBytesRead << ").";
#endif
      return;
    }

    switch( receiveMode_ )
    {
      case MODE_AUTHENTICATION:
        // See if a string with 2 newlines is received.
        // Assume it will be received in 1 packet, since the connection is just starting and the size is very small.
        newBlockSize = buffer_.buffer().indexOf("\r\n\r\n");
        if( newBlockSize == -1 )
        {
          kWarning() << "Received corrupt authentication command for the webcam connection (contact=" << contactHandle_ << ").";
          closeConnection();
          return;
        }

#ifdef KMESS_NETWORK_WINDOW
        KMESS_NET_RECEIVED( this, buffer_.buffer().left( newBlockSize + 4 ) );
#endif

        // Convert to a string.
        command = buffer_.read( newBlockSize + 4 ).left( newBlockSize );
#ifdef KMESSDEBUG_WEBCAMCONNECTION_GENERAL
        kDebug() << "Received authentication command: " << command;
#endif

        if( isServer() )
        {
          // Server, we should receive the authentication now.
          QString expectedAuthentication( "recipientid=" + QString::number( recipientId_ ) + "&sessionid=" + QString::number( sessionId_ ) );
          if( command != expectedAuthentication )
          {
            kWarning() << "Received invalid authentication command for the webcam connection (received=" << command << " expected=" << expectedAuthentication << "contact=" << contactHandle_ << ").";
            closeConnection();
            return;
          }

          // Authentication is correct, report to client.
          writeBlock("connected\r\n\r\n");

          // Switch mode, and notify calling class.
          receiveMode_ = MODE_HEADER;
          setAuthorized( true );
        }
        else
        {
          // Client, we should get a "connected" response back.
          if( command != "connected" )
          {
            kWarning() << "Received invalid authentication response for the webcam connection (received=" << command << "expected=\"connected\" contact=" << contactHandle_ << ").";
            closeConnection();
            return;
          }

          // Switch mode, and notify calling class.
          receiveMode_ = MODE_HEADER;
          setAuthorized( true );
        }

        break;


      case MODE_HEADER:

        break;


      case MODE_V_FRAME:

        break;

    }
  }
}



#include "msnwebcamconnection.moc"

Generated by  Doxygen 1.6.0   Back to index