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

void P2PApplication::sendCancelMessage ( const ApplicationCancelReason  cancelReason  )  [protected, virtual, inherited]

Send a cancel message.

The application will be terminated later, either directly or after the contact ACKed the error.

The following cancelReason values are supported:

  • CANCEL_INVITATION The user declined the invitation. This sends an SLP 603 Decline message.

  • CANCEL_ABORT / CANCEL_FAILED The user aborted the session. If called from contactStarted1_ContactInvitesUser() with CANCEL_FAILED, this sends an SLP 500 Internal Error message. Otherwise it sends a SLP BYE or P2P error message.

  • CANCEL_NOT_INSTALLED The requested service/application is not installed. This sends an SLP 500 Internal Error message.

  • CANCEL_TIMEOUT There was a timeout waiting for the contact to accept or send certain P2P data. This sends an P2P message with the "waiting flag" set (type 4) and terminates the application direclty. This reason is used internally by certain timeout functions.

  • CANCEL_INVALID_SLP_CONTENT_TYPE Sends an "MSNSLP 500 Internal Error" message back, but with a null Content-Type value set.

The error messages which send an SLP message can only be used from contactStarted1_ContactInvitesUser() and userStarted2_ContactAccepts(). Once the MSNSLP error message is sent, P2PApplication waits for the contact to ACK, and terminates the application afterwards. Hence, you don't have to call endApplication() at all.

When an MSNSLP error is sent at a different moment, this will likely result in undefined responses from the other client (or the error message could be ignored). If KMess is compiled in debug mode, an assertion in sendSlpError() detects this.

The CANCEL_ABORT reason is the only valid response to reject a data-preparation message in the userStarted3_UserPrepares() method. If KMess is compiled in debug mode, an assertion will be triggered otherwise.

Parameters:
cancelReason The reason why the application is cancelled.

Implements Application.

Definition at line 2553 of file p2papplication.cpp.

References P2PApplicationBase::abortDataSending(), Application::CANCEL_ABORT, Application::CANCEL_FAILED, Application::CANCEL_INVALID_SLP_CONTENT_TYPE, Application::CANCEL_INVITATION, Application::CANCEL_NOT_INSTALLED, Application::CANCEL_TIMEOUT, P2PApplicationBase::endApplicationLater(), Application::getContactHandle(), P2PApplicationBase::getWaitingState(), P2PApplicationBase::hasUnAckedMessage(), Application::isUserStartedApp(), P2PApplicationBase::isWaitingState(), P2PApplicationBase::P2P_MSG_SESSION_INVITATION, P2PApplicationBase::P2P_WAIT_USER_ACCEPT, P2PApplicationBase::sendP2PAbort(), P2PApplicationBase::sendP2PWaitingError(), P2PApplication::sendSlpBye(), and P2PApplication::sendSlpError().

Referenced by contactStarted1_ContactInvitesUser(), P2PApplication::contactStarted1_ContactInvitesUser(), MsnObjectTransferP2P::contactStarted1_ContactInvitesUser(), FileTransferP2P::contactStarted1_ContactInvitesUser(), MsnObjectTransferP2P::contactStarted1_gotDisplayPictureRequest(), MsnObjectTransferP2P::contactStarted1_gotEmoticonRequest(), MsnObjectTransferP2P::contactStarted2_UserAccepts(), FileTransferP2P::contactStarted2_UserAccepts(), P2PApplication::gotAck_slpSessionOk(), MsnObjectTransferP2P::gotData(), FileTransferP2P::gotData(), P2PApplication::gotSlpInvite(), P2PApplication::gotSlpOk(), P2PApplication::gotSlpSessionInvitation(), P2PApplication::gotSlpTransferInvitation(), P2PApplication::showTimeoutMessage(), P2PApplication::userAborted(), and P2PApplication::userRejected().

{
#ifdef KMESSDEBUG_P2PAPPLICATION_GENERAL
  kDebug() << "request to abort "
            << "(reason=" << cancelReason << ", state=" << (int) getWaitingState() << ").";
#endif

  // I don't care what the reason is if you had
  // to send the data-preparation ACK
  if( userShouldAcknowledge_ )
  {
#ifdef KMESSTEST
    KMESS_ASSERT( cancelReason == CANCEL_ABORT);
#endif

    // Cancelled the data preparation message
    sendP2PAbort();
    userShouldAcknowledge_ = false;

    // TODO: send bye here to? wait for bye? just terminate?
    kWarning() << "data-preparation stage failed "
                  "(contact=" << getContactHandle() <<
                  " session=" << sessionID_ <<
                  " class="   << metaObject()->className() <<
                  " action=endapplicationlater).";
    endApplicationLater();
    return;
  }


  switch(cancelReason)
  {
    // Declined the invitation
    case CANCEL_INVITATION:
#ifdef KMESSTEST
      KMESS_ASSERT( ! invitationContentType_.isEmpty() );
      KMESS_ASSERT( invitationSessionID_ != 0 );
#endif

      // Use the cancel-reason to send the correct message:
      sendSlpError("603 Decline", invitationSessionID_, invitationContentType_);
      return;


    // Timeout waiting for some P2P data
    // ...or timeout waiting for contact to accept.
    case CANCEL_TIMEOUT:
      // Timeout handling occurs via slotCleanup(), not here.
      kWarning() << "CANCEL_TIMEOUT is not supported here "
                    "(state="   << (int) getWaitingState() <<
                    " contact=" << getContactHandle() <<
                    " session=" << sessionID_ <<
                    " class="   << metaObject()->className() <<
                    " action=send0x04,endapplicationlater)";

      // Send the low-level error message that the session is waiting for something!
      sendP2PWaitingError();
      endApplicationLater();
      return;


    // The application type is not installed
    case CANCEL_NOT_INSTALLED:
      if( gotSlpMessage_)
      {
        // Usually this particular error is invoked from Application::contactStarted1_ContactInvitesUser().
        sendSlpError("500 Internal Error", invitationSessionID_, "null");
      }
      else
      {
        kWarning() << "CANCEL_NOT_INSTALLED is not supported here "
                      "(state="   << (int) getWaitingState() <<
                      " contact=" << getContactHandle() <<
                      " session=" << sessionID_ <<
                      " class="   << metaObject()->className() <<
                      " action=return)";
      }
      return;


    // User or application wants to abort
    case CANCEL_ABORT:
    case CANCEL_FAILED:
      // Make sure sending is aborted.
      abortDataSending();

      // Determine which error message to send back.
      if( gotSlpMessage_ )
      {
        // A: Special case for SLP messages.
        if( isWaitingState( P2P_WAIT_USER_ACCEPT ) && cancelReason == CANCEL_ABORT )
        {
#ifdef KMESSDEBUG_P2PAPPLICATION_GENERAL
          kDebug() << "Cancelling after receiving an SLP INVITE, "
                    << "sending BYE back.";
#endif
#ifdef KMESSTEST
          KMESS_ASSERT( isUserStartedApp() );
#endif
          // Send bye early, contact should detect this.
          sendSlpBye();
        }
        else
        {
#ifdef KMESSDEBUG_P2PAPPLICATION_GENERAL
          kDebug() << "Aborting after receiving an SLP message, "
                    << "sending 500 Internal Error back.";
#endif
          // Cancelled while in SLP negotiate mode.
          // Include the original content-type to tell the other
          // client that part of the message was not in error.
          sendSlpError("500 Internal Error", invitationSessionID_, invitationContentType_);
        }
      }
      else if( isUserStartedApp() )
      {
        // B: User started application
#ifdef KMESSDEBUG_P2PAPPLICATION_GENERAL
        kDebug() << "P2PApplication::sendCancelMessage() Cancelling an application "
                  << "we've started ourselves, sending BYE early.";
#endif
        // Mark the logs if there is something weird going on.
        // It's possible the contact doesn't receive the INVITE anymore
        // while KMess can't detect yet it's closed.
        // This happens sometimes when KMess sent a file before which was aborted by WLM.
        if( hasUnAckedMessage( P2P_MSG_SESSION_INVITATION ) )
        {
          kWarning() << "aborting while INVITE ack was not received "
                        "(state="   << (int) getWaitingState() <<
                        " contact=" << getContactHandle() <<
                        " session=" << sessionID_ <<
                        " class="   << metaObject()->className() <<
                        " action=continue,sendslpbye).";
        }

        // Send bye early, contact should detect this.
        sendSlpBye();
      }
      else
      {
        // C: Contact started application
#ifdef KMESSDEBUG_P2PAPPLICATION_GENERAL
        kDebug() << "P2PApplication::sendCancelMessage() Cancelling an application "
                  << "started by the other contact, sending BYE early.";
#endif
        // Send bye early, contact should detect this.
        sendSlpBye();

        //  TODO: after the message is ACKed, the contact sends a 0x40 "I've sent the bye early" message.
        // KMess does not do this here.
      }

      return;


    // Invalid content type received
    case CANCEL_INVALID_SLP_CONTENT_TYPE:
#ifdef KMESSTEST
      KMESS_ASSERT( gotSlpMessage_ );
#endif
      // Send an 500 error message without content-type set
      sendSlpError("500 Internal Error");
      return;


    // Last option, unknown cancel message
    default:
      kWarning() << "unknown cancelReason used "
                    "(contact=" << getContactHandle() <<
                    " session=" << sessionID_ <<
                    " class="   << metaObject()->className() <<
                    " action=send0x08).";

      // Initiate primitive abort.
      sendP2PAbort();
  }
}


Generated by  Doxygen 1.6.0   Back to index