Logo Search packages:      
Sourcecode: kmess version File versions  Download package

void P2PApplication::gotMessage ( const MimeMessage message  )  [virtual, inherited]

Parse an incoming message

Parameters:
message A reference to a P2PMessage object.

Implements Application.

Definition at line 683 of file p2papplication.cpp.

References P2PMessage::getAckMessageID(), P2PMessage::getDataOffset(), P2PMessage::getDataSize(), P2PMessage::getFlags(), P2PMessage::getMessageID(), P2PMessage::getSessionID(), P2PMessage::getTotalSize(), P2PApplication::gotAck(), P2PApplication::gotClosingAck(), P2PApplication::gotDataFragment(), P2PApplication::gotDataPreparation(), P2PApplication::gotErrorAck(), P2PApplication::gotNegotiationFragment(), P2PApplication::gotTimeoutAck(), P2PMessage::isAck(), P2PMessage::isClosingAck(), P2PMessage::isError(), P2PMessage::isFileData(), P2PMessage::isFragment(), P2PMessage::isLastFragment(), P2PMessage::isPictureData(), P2PMessage::isWaiting(), P2PApplication::sendP2PAck(), and P2PApplication::sendSlpError().

{
#ifdef KMESSTEST
  ASSERT( message.isA("P2PMessage") ); // QObject function
#endif

  // If we were explicitly waiting for a packet, stop the timer
  waitingTimer_->stop();


  // Convert the message
  const P2PMessage &p2pMessage = static_cast<const P2PMessage>(message);

  // Store some message parameters for Acknowledgement later
  originalAckMessageID_ = p2pMessage.getAckMessageID();
  originalDataSize_     = p2pMessage.getDataSize();
  originalMessageID_    = p2pMessage.getMessageID();
  originalSessionID_    = p2pMessage.getSessionID();
  originalTotalSize_    = p2pMessage.getTotalSize();


#ifdef KMESSDEBUG_P2PAPPLICATION_GENERAL
  kdDebug() << "P2PApplication: Message size: " << p2pMessage.getDataSize()
                           << " Total size: "   << p2pMessage.getTotalSize()
                           << " Offset: "       << p2pMessage.getDataOffset() << endl;
#endif


  // If this object was initialized to handle a Bad packet.
  if(getMode() == APP_MODE_ERROR_HANDLER)
  {
    // Make an exception for SLP packets
    bool isSlpMessage = (p2pMessage.getSessionID() == 0 &&
                         p2pMessage.getFlags()     == 0);
    if(! isSlpMessage)
    {
      // We received an unknown message, this object was initialized to send the correct response.
      shouldSendAck_ = true;  // ASSERT in sendP2PAck would fail otherwise
      sendP2PAck(P2PMessage::MSN_FLAG_ERROR);
      endApplication( i18n("The invitation was cancelled.  The contact sent bad data, or KMess doesn't support it.") );
      return;
    }
  }


  // Handle ACKs before everything else.
  // The application can be terminated here.
  if(p2pMessage.isAck())
  {
    gotAck(p2pMessage);
    return;
  }
  else if(p2pMessage.isClosingAck())
  {
    gotClosingAck(p2pMessage);
    return;
  }
  else if(p2pMessage.isError())
  {
    gotErrorAck(p2pMessage);
    return;
  }
  else if(p2pMessage.isWaiting())
  {
    gotTimeoutAck(p2pMessage);
    return;
  }


  // Send the ack if needed (also applies to INVITE messages)
  shouldSendAck_ = p2pMessage.isLastFragment();


  // Session ID is 0? -> the clients negotiate for session.
  if(p2pMessage.getSessionID() == 0)
  {
    if(p2pMessage.getFlags() == 0)
    {
      // If this object was initialized to handle a Bad packet.
      if(getMode() == APP_MODE_ERROR_HANDLER)
      {
        // This object was initialized to send an error response for an unknown packet (at SLP level).
        emit appInitMessage( i18n("The transfer failed.  The contact sent bad data, or KMess doesn't support it.") );
        sendSlpError("500 Internal Error"); // Waits for ACK and terminates
        return;
      }


      // Parse the fragment
      gotNegotiationFragment(p2pMessage);
    }
    else
    {
      kdWarning() << "P2PApplication: P2P message can't be handled, "
                  << "unknown negotiation message type (flags="   << p2pMessage.getFlags()
                                                   << " contact=" << contactHandle_ << ")." << endl;

      // Don't know what to do with a negotiation message with flags set.
      sendP2PAck(P2PMessage::MSN_FLAG_ERROR);
      endApplication( i18n("The transfer failed.  The contact sent bad data, or KMess doesn't support it.") );
      return;
    }
  }
  // Session ID not zero? -> clients exchange data in the session
  else
  {
    // Check for data preparation messages
    if(p2pMessage.getFlags()     == 0
    && p2pMessage.getDataSize()  == 4
    && p2pMessage.getTotalSize() == 4)
    {
      gotDataPreparation(p2pMessage);
    }
    // Check for data messages
    else if(p2pMessage.isPictureData() ||
            p2pMessage.isFileData()    ||
            p2pMessage.isFragment())
    {
      // HACK: The last p2pMessage.isFragment() check is to
      // support broken Kopete 0.9.2 code. (has no flag set)

      gotDataFragment(p2pMessage);
    }
    else
    {
      // Unknown p2p message
      kdWarning() << "P2PApplication: P2P message can't be handled, "
                  << " unknown data message type (flags="   << p2pMessage.getFlags()
                                             << " contact=" << contactHandle_ << ")." << endl;

      // Got an P2P binary message we can't handle. (some new kind of flag..?)
      shouldSendAck_ = true;  // ASSERT in sendP2PAck would fail otherwise
      sendP2PAck(P2PMessage::MSN_FLAG_ERROR);
      endApplication( i18n("The transfer failed.  The contact sent bad data, or KMess doesn't support it.") );
      return;
    }
  }

#ifdef KMESSTEST
  // At the end of this method, we should have sent the ACK..!
  ASSERT( ! shouldSendAck_ );
#endif
}


Generated by  Doxygen 1.6.0   Back to index