Beispiel #1
0
  /**
   * Receive CANCEL request
   *
   * @param cancel CANCEL request
   */
  public void receiveCancel(SipRequest cancel) {
    if (logger.isActivated()) {
      logger.info("ABC Receive a CANCEL message from the remote");
    }

    if (getDialogPath().isSigEstablished()) {
      if (logger.isActivated()) {
        logger.info(
            "Ignore the received CANCEL message from the remote (session already established)");
      }
      return;
    }

    // Close media session
    closeMediaSession();

    // Update dialog path
    getDialogPath().sessionCancelled();

    // Send a 487 Request terminated
    try {
      if (logger.isActivated()) {
        logger.info("Send 487 Request terminated");
      }
      SipResponse terminatedResp =
          SipMessageFactory.createResponse(
              getDialogPath().getInvite(), getDialogPath().getLocalTag(), 487);
      getImsService().getImsModule().getSipManager().sendSipResponse(terminatedResp);
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Can't send 487 error response", e);
      }
    }

    // Remove the current session
    getImsService().removeSession(this);

    // Set invitation status
    invitationStatus = ImsServiceSession.INVITATION_CANCELED;

    // Unblock semaphore
    synchronized (waitUserAnswer) {
      waitUserAnswer.notifyAll();
    }

    // Notify listeners
    for (int i = 0; i < getListeners().size(); i++) {
      getListeners().get(i).handleSessionTerminatedByRemote();
    }

    // Request capabilities to the remote
    getImsService()
        .getImsModule()
        .getCapabilityService()
        .requestContactCapabilities(getDialogPath().getRemoteParty());
  }
 /**
  * Send a 180 Ringing response to the remote party
  *
  * @param request SIP request
  * @param localTag Local tag
  */
 public void send180Ringing(SipRequest request, String localTag) {
   try {
     SipResponse progress = SipMessageFactory.createResponse(request, localTag, 180);
     getImsService().getImsModule().getSipManager().sendSipResponse(progress);
   } catch (Exception e) {
     if (logger.isActivated()) {
       logger.error("Can't send a 180 Ringing response");
     }
   }
 }
  /**
   * Handle 422 response
   *
   * @param resp 422 response
   */
  private void handle422SessionTooSmall(SipResponse resp) {
    try {
      // 422 response received
      if (logger.isActivated()) {
        logger.info("422 response received");
      }

      // Extract the Min-SE value
      int minExpire = SipUtils.getMinSessionExpirePeriod(resp);
      if (minExpire == -1) {
        if (logger.isActivated()) {
          logger.error("Can't read the Min-SE value");
        }
        handleError(
            new FileSharingError(FileSharingError.UNEXPECTED_EXCEPTION, "No Min-SE value found"));
        return;
      }

      // Set the min expire value
      getDialogPath().setMinSessionExpireTime(minExpire);

      // Set the expire value
      getDialogPath().setSessionExpireTime(minExpire);

      // Increment the Cseq number of the dialog path
      getDialogPath().incrementCseq();

      // Create a new INVITE with the right expire period
      if (logger.isActivated()) {
        logger.info("Send new INVITE");
      }
      SipRequest invite =
          SipMessageFactory.createInvite(
              getDialogPath(),
              InstantMessagingService.FT_FEATURE_TAGS,
              getDialogPath().getLocalContent());

      // Set the Authorization header
      getAuthenticationAgent().setAuthorizationHeader(invite);

      // Reset initial request in the dialog path
      getDialogPath().setInvite(invite);

      // Send INVITE request
      sendInvite(invite);

    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Session initiation has failed", e);
      }

      // Unexpected error
      handleError(new FileSharingError(FileSharingError.UNEXPECTED_EXCEPTION, e.getMessage()));
    }
  }
 /**
  * Send a 415 "Unsupported Media Type" to the remote party
  *
  * @param request SIP request
  */
 public void send415Error(SipRequest request) {
   try {
     if (logger.isActivated()) {
       logger.info("Send 415 Unsupported Media Type");
     }
     SipResponse resp = SipMessageFactory.createResponse(request, 415);
     // TODO: set Accept-Encoding header
     getImsService().getImsModule().getSipManager().sendSipResponse(resp);
   } catch (Exception e) {
     if (logger.isActivated()) {
       logger.error("Can't send 415 error response", e);
     }
   }
 }
 /**
  * Send a 486 "Busy" to the remote party
  *
  * @param request SIP request
  * @param localTag Local tag
  */
 public void send486Busy(SipRequest request, String localTag) {
   try {
     // Send a 486 Busy error
     if (logger.isActivated()) {
       logger.info("Send 486 Busy");
     }
     SipResponse resp = SipMessageFactory.createResponse(request, localTag, 486);
     getImsService().getImsModule().getSipManager().sendSipResponse(resp);
   } catch (Exception e) {
     if (logger.isActivated()) {
       logger.error("Can't send 486 Busy response", e);
     }
   }
 }
 /**
  * Send an error response to the remote party
  *
  * @param request SIP request
  * @param localTag Local tag
  * @param code Response code
  */
 public void sendErrorResponse(SipRequest request, String localTag, int code) {
   try {
     // Send  error
     if (logger.isActivated()) {
       logger.info("Send " + code + " error response");
     }
     SipResponse resp = SipMessageFactory.createResponse(request, localTag, code);
     getImsService().getImsModule().getSipManager().sendSipResponse(resp);
   } catch (Exception e) {
     if (logger.isActivated()) {
       logger.error("Can't send error response", e);
     }
   }
 }
  /**
   * Create INVITE request
   *
   * @param content Content part
   * @return Request
   * @throws SipException
   */
  private SipRequest createInviteRequest(String content) throws SipException {
    SipRequest invite =
        SipMessageFactory.createInvite(
            getDialogPath(), getFeatureTags(), getAcceptContactTags(), content);

    // Test if there is a subject
    if (getSubject() != null) {
      // Add a subject header
      invite.addHeader(SubjectHeader.NAME, StringUtils.encodeUTF8(getSubject()));
    }

    // Add a contribution ID header
    invite.addHeader(ChatUtils.HEADER_CONTRIBUTION_ID, getContributionID());

    return invite;
  }
  /**
   * Handle 407 Proxy Authentication Required
   *
   * @param resp 407 response
   */
  public void handle407Authentication(SipResponse resp) {
    try {
      if (logger.isActivated()) {
        logger.info("407 response received");
      }

      // Set the remote tag
      getDialogPath().setRemoteTag(resp.getToTag());

      // Update the authentication agent
      getAuthenticationAgent().readProxyAuthenticateHeader(resp);

      // Increment the Cseq number of the dialog path
      getDialogPath().incrementCseq();

      // Create a second INVITE request with the right token
      if (logger.isActivated()) {
        logger.info("Send second INVITE");
      }
      SipRequest invite =
          SipMessageFactory.createInvite(
              getDialogPath(),
              InstantMessagingService.FT_FEATURE_TAGS,
              getDialogPath().getLocalContent());

      // Reset initial request in the dialog path
      getDialogPath().setInvite(invite);

      // Set the Proxy-Authorization header
      getAuthenticationAgent().setProxyAuthorizationHeader(invite);

      // Send INVITE request
      sendInvite(invite);

    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Session initiation has failed", e);
      }

      // Unexpected error
      handleError(new FileSharingError(FileSharingError.UNEXPECTED_EXCEPTION, e.getMessage()));
    }
  }
  /**
   * Receive a capability request (options procedure)
   *
   * @param options Received options message
   */
  public void receiveCapabilityRequest(SipRequest options) {
    String contact = SipUtils.getAssertedIdentity(options);

    if (logger.isActivated()) {
      logger.debug("OPTIONS request received during a call from " + contact);
    }

    try {
      // Create 200 OK response
      String ipAddress =
          getImsModule().getCurrentNetworkInterface().getNetworkAccess().getIpAddress();
      boolean richcall = getImsModule().getCallManager().isRichcallSupportedWith(contact);
      SipResponse resp =
          SipMessageFactory.create200OkOptionsResponse(
              options,
              getImsModule().getSipManager().getSipStack().getLocalContact(),
              CapabilityUtils.getSupportedFeatureTags(richcall),
              CapabilityUtils.buildSdp(ipAddress, richcall));

      // Send 200 OK response
      getImsModule().getSipManager().sendSipResponse(resp);
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Can't send 200 OK for OPTIONS", e);
      }
    }

    // Extract capabilities from the request
    Capabilities capabilities = CapabilityUtils.extractCapabilities(options);
    logger.debug("capabilities = " + capabilities);
    if (capabilities.isImSessionSupported()) {
      // The contact is RCS capable
      ContactsManager.getInstance()
          .setContactCapabilities(
              contact,
              capabilities,
              ContactInfo.RCS_CAPABLE,
              ContactInfo.REGISTRATION_STATUS_ONLINE);
      /** M: Added to fix the issue that RCS-e icon does not display in contact list of People.@{ */
      capabilities.setRcseContact(true);
      /** @} */
    } else {
      // The contact is not RCS
      ContactsManager.getInstance()
          .setContactCapabilities(
              contact, capabilities, ContactInfo.NOT_RCS, ContactInfo.REGISTRATION_STATUS_UNKNOWN);
      /** M: Added to fix the issue that RCS-e icon does not display in contact list of People.@{ */
      capabilities.setRcseContact(false);
      /** @} */
    }
    /** M: Added to fix the issue that RCS-e icon does not display in contact list of People.@{ */
    if (logger.isActivated()) {
      logger.debug(
          "receiveCapabilityRequest setRcseContact contact: "
              + contact
              + " "
              + capabilities.isImSessionSupported());
    }
    /** @} */
    // Notify listener
    getImsModule().getCore().getListener().handleCapabilitiesNotification(contact, capabilities);
  }
  /**
   * Add a list of participants to the session
   *
   * @param participants List of participants
   */
  public void addParticipants(List<String> participants) {
    try {
      if (participants.size() == 1) {
        addParticipant(participants.get(0));
        return;
      }

      if (logger.isActivated()) {
        logger.debug("Add " + participants.size() + " participants to the session");
      }

      // Re-use INVITE dialog path
      SessionAuthenticationAgent authenticationAgent = getAuthenticationAgent();

      // Increment the Cseq number of the dialog path
      getDialogPath().incrementCseq();

      // Send REFER request
      if (logger.isActivated()) {
        logger.debug("Send REFER");
      }
      SipRequest refer = SipMessageFactory.createRefer(getDialogPath(), participants);
      SipTransactionContext ctx =
          getImsService().getImsModule().getSipManager().sendSipMessageAndWait(refer);

      // Wait response
      if (logger.isActivated()) {
        logger.debug("Wait response");
      }
      ctx.waitResponse(SipManager.TIMEOUT);

      // Analyze received message
      if (ctx.getStatusCode() == 407) {
        // 407 response received
        if (logger.isActivated()) {
          logger.debug("407 response received");
        }

        // Set the Proxy-Authorization header
        authenticationAgent.readProxyAuthenticateHeader(ctx.getSipResponse());

        // Increment the Cseq number of the dialog path
        getDialogPath().incrementCseq();

        // Create a second REFER request with the right token
        if (logger.isActivated()) {
          logger.info("Send second REFER");
        }
        refer = SipMessageFactory.createRefer(getDialogPath(), participants);

        // Set the Authorization header
        authenticationAgent.setProxyAuthorizationHeader(refer);

        // Send REFER request
        ctx = getImsService().getImsModule().getSipManager().sendSipMessageAndWait(refer);

        // Wait response
        if (logger.isActivated()) {
          logger.debug("Wait response");
        }
        ctx.waitResponse(SipManager.TIMEOUT);

        // Analyze received message
        if ((ctx.getStatusCode() >= 200) && (ctx.getStatusCode() < 300)) {
          // 200 OK response
          if (logger.isActivated()) {
            logger.debug("20x OK response received");
          }

          // Notify listeners
          for (int i = 0; i < getListeners().size(); i++) {
            ((ChatSessionListener) getListeners().get(i)).handleAddParticipantSuccessful();
          }
        } else {
          // Error
          if (logger.isActivated()) {
            logger.debug("REFER has failed (" + ctx.getStatusCode() + ")");
          }

          // Notify listeners
          for (int i = 0; i < getListeners().size(); i++) {
            ((ChatSessionListener) getListeners().get(i))
                .handleAddParticipantFailed(ctx.getReasonPhrase());
          }
        }
      } else if ((ctx.getStatusCode() >= 200) && (ctx.getStatusCode() < 300)) {
        // 200 OK received
        if (logger.isActivated()) {
          logger.debug("20x OK response received");
        }

        // Notify listeners
        for (int i = 0; i < getListeners().size(); i++) {
          ((ChatSessionListener) getListeners().get(i)).handleAddParticipantSuccessful();
        }
      } else {
        // Error responses
        if (logger.isActivated()) {
          logger.debug("No response received");
        }

        // Notify listeners
        for (int i = 0; i < getListeners().size(); i++) {
          ((ChatSessionListener) getListeners().get(i))
              .handleAddParticipantFailed(ctx.getReasonPhrase());
        }
      }
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("REFER request has failed", e);
      }

      // Notify listeners
      for (int i = 0; i < getListeners().size(); i++) {
        ((ChatSessionListener) getListeners().get(i)).handleAddParticipantFailed(e.getMessage());
      }
    }
  }
  private SipRequest createSipInvite() {
    logger.debug("createSipInvite()");
    // Set setup mode
    String localSetup = createSetupOffer();
    if (logger.isActivated()) {
      logger.debug("Local setup attribute is " + localSetup);
    }

    // Set local port
    int localMsrpPort = 9; // See RFC4145, Page 4

    // Create the MSRP manager
    String localIpAddress =
        getImsService()
            .getImsModule()
            .getCurrentNetworkInterface()
            .getNetworkAccess()
            .getIpAddress();
    msrpMgr = new MsrpManager(localIpAddress, localMsrpPort);

    // Build SDP part
    String ntpTime = SipUtils.constructNTPtime(System.currentTimeMillis());
    String ipAddress = getDialogPath().getSipStack().getLocalIpAddress();
    /** M: add for MSRPoTLS @{ */
    String protocol = getCurrentProtocol();
    String sdp = null;
    if (PROTOCOL_TLS.equals(protocol)) {
      sdp =
          "v=0"
              + SipUtils.CRLF
              + "o=- "
              + ntpTime
              + " "
              + ntpTime
              + " IN IP4 "
              + ipAddress
              + SipUtils.CRLF
              + "s=-"
              + SipUtils.CRLF
              + "c=IN IP4 "
              + ipAddress
              + SipUtils.CRLF
              + "t=0 0"
              + SipUtils.CRLF
              + "m=message "
              + localMsrpPort
              + " TCP/TLS/MSRP *"
              + SipUtils.CRLF
              + "a=path:"
              + msrpMgr.getLocalMsrpsPath()
              + SipUtils.CRLF
              + "a=fingerprint:"
              + KeyStoreManager.getFingerPrint()
              + SipUtils.CRLF
              + "a=setup:"
              + localSetup
              + SipUtils.CRLF
              + "a=accept-types: "
              + getContent().getEncoding()
              + SipUtils.CRLF
              + "a=file-transfer-id:"
              + getFileTransferId()
              + SipUtils.CRLF
              + "a=file-disposition:attachment"
              + SipUtils.CRLF
              + "a=sendonly"
              + SipUtils.CRLF;
    } else {
      sdp =
          "v=0"
              + SipUtils.CRLF
              + "o=- "
              + ntpTime
              + " "
              + ntpTime
              + " IN IP4 "
              + ipAddress
              + SipUtils.CRLF
              + "s=-"
              + SipUtils.CRLF
              + "c=IN IP4 "
              + ipAddress
              + SipUtils.CRLF
              + "t=0 0"
              + SipUtils.CRLF
              + "m=message "
              + localMsrpPort
              + " TCP/MSRP *"
              + SipUtils.CRLF
              + "a=path:"
              + msrpMgr.getLocalMsrpPath()
              + SipUtils.CRLF
              + "a=setup:"
              + localSetup
              + SipUtils.CRLF
              + "a=accept-types: "
              + getContent().getEncoding()
              + SipUtils.CRLF
              + "a=file-transfer-id:"
              + getFileTransferId()
              + SipUtils.CRLF
              + "a=file-disposition:attachment"
              + SipUtils.CRLF
              + "a=sendonly"
              + SipUtils.CRLF;
    }
    int maxSize = FileSharingSession.getMaxFileSharingSize();
    if (maxSize > 0) {
      sdp += "a=max-size:" + maxSize + SipUtils.CRLF;
    }

    /** @} */
    // Set File-selector attribute
    String selector = getFileSelectorAttribute();
    if (selector != null) {
      sdp += "a=file-selector:" + selector + SipUtils.CRLF;
    }

    // Set File-location attribute
    String location = getFileLocationAttribute();
    if (location != null) {
      sdp += "a=file-location:" + location + SipUtils.CRLF;
    }

    // Set the local SDP part in the dialog path
    getDialogPath().setLocalContent(sdp);

    // Create an INVITE request
    if (logger.isActivated()) {
      logger.info("Create INVITE");
    }
    try {
      SipRequest invite;
      invite =
          SipMessageFactory.createInvite(
              getDialogPath(), InstantMessagingService.FT_FEATURE_TAGS, sdp);
      // Set the Authorization header
      getAuthenticationAgent().setAuthorizationHeader(invite);

      // Set initial request in the dialog path
      getDialogPath().setInvite(invite);
      return invite;
    } catch (SipException e) {
      e.printStackTrace();
    } catch (CoreException e) {
      e.printStackTrace();
    }
    logger.error("Create sip invite failed, return null.");
    return null;
  }
Beispiel #12
0
  /** Background processing */
  public void run() {
    try {
      if (logger.isActivated()) {
        logger.info("Initiate a new 1-1 chat session as terminating");
      }

      // Send message delivery report if requested
      if ((ChatUtils.isImdnDeliveredRequested(getDialogPath().getInvite()))
          || (ChatUtils.isFileTransferOverHttp(getDialogPath().getInvite()))) {
        // Check notification disposition
        String msgId = ChatUtils.getMessageId(getDialogPath().getInvite());
        if (msgId != null) {
          // Send message delivery status via a SIP MESSAGE
          getImdnManager()
              .sendMessageDeliveryStatusImmediately(
                  getDialogPath().getRemoteParty(),
                  msgId,
                  ImdnDocument.DELIVERY_STATUS_DELIVERED,
                  SipUtils.getRemoteInstanceID(getDialogPath().getInvite()));
        }
      }

      // Check if Auto-accept (FT HTTP force auto-accept for the chat session)
      if (RcsSettings.getInstance().isChatAutoAccepted()
          || ChatUtils.getHttpFTInfo(getDialogPath().getInvite()) != null) {
        if (logger.isActivated()) {
          logger.info("Auto accept chat invitation");
        }
      } else {
        if (logger.isActivated()) {
          logger.info("Accept manually chat invitation");
        }

        // Send a 180 Ringing response
        send180Ringing(getDialogPath().getInvite(), getDialogPath().getLocalTag());

        // Wait invitation answer
        int answer = waitInvitationAnswer();
        if (answer == ImsServiceSession.INVITATION_REJECTED) {
          if (logger.isActivated()) {
            logger.info("Session has been rejected by user");
          }

          // Remove the current session
          getImsService().removeSession(this);

          // Notify listeners
          for (int i = 0; i < getListeners().size(); i++) {
            getListeners().get(i).handleSessionAborted(ImsServiceSession.TERMINATION_BY_USER);
          }
          return;
        } else if (answer == ImsServiceSession.INVITATION_NOT_ANSWERED) {
          if (logger.isActivated()) {
            logger.info("Session has been rejected on timeout");
          }

          // Ringing period timeout
          send486Busy(getDialogPath().getInvite(), getDialogPath().getLocalTag());

          // Remove the current session
          getImsService().removeSession(this);

          // Notify listeners
          for (int i = 0; i < getListeners().size(); i++) {
            getListeners().get(i).handleSessionAborted(ImsServiceSession.TERMINATION_BY_TIMEOUT);
          }
          return;
        } else if (answer == ImsServiceSession.INVITATION_CANCELED) {
          if (logger.isActivated()) {
            logger.info("Session has been canceled");
          }
          return;
        }
      }

      // Parse the remote SDP part
      String remoteSdp = getDialogPath().getInvite().getSdpContent();
      SdpParser parser = new SdpParser(remoteSdp.getBytes());
      Vector<MediaDescription> media = parser.getMediaDescriptions();
      MediaDescription mediaDesc = media.elementAt(0);
      MediaAttribute attr1 = mediaDesc.getMediaAttribute("path");
      String remotePath = attr1.getValue();
      String remoteHost = SdpUtils.extractRemoteHost(parser.sessionDescription, mediaDesc);
      int remotePort = mediaDesc.port;

      // Extract the "setup" parameter
      String remoteSetup = "passive";
      MediaAttribute attr2 = mediaDesc.getMediaAttribute("setup");
      if (attr2 != null) {
        remoteSetup = attr2.getValue();
      }
      if (logger.isActivated()) {
        logger.info("Remote setup attribute is " + remoteSetup);
      }

      // Set setup mode
      String localSetup = createSetupAnswer(remoteSetup);
      if (logger.isActivated()) {
        logger.debug("Local setup attribute is " + localSetup);
      }

      // Set local port
      int localMsrpPort;
      if (localSetup.equals("active")) {
        localMsrpPort = 9; // See RFC4145, Page 4
      } else {
        localMsrpPort = getMsrpMgr().getLocalMsrpPort();
      }

      // Build SDP part
      String ntpTime = SipUtils.constructNTPtime(System.currentTimeMillis());
      String ipAddress = getDialogPath().getSipStack().getLocalIpAddress();
      String sdp = null;
      if (isSecureProtocolMessage()) {
        sdp =
            "v=0"
                + SipUtils.CRLF
                + "o=- "
                + ntpTime
                + " "
                + ntpTime
                + " "
                + SdpUtils.formatAddressType(ipAddress)
                + SipUtils.CRLF
                + "s=-"
                + SipUtils.CRLF
                + "c="
                + SdpUtils.formatAddressType(ipAddress)
                + SipUtils.CRLF
                + "t=0 0"
                + SipUtils.CRLF
                + "m=message "
                + localMsrpPort
                + " "
                + getMsrpMgr().getLocalSocketProtocol()
                + " *"
                + SipUtils.CRLF
                + "a=accept-types:"
                + getAcceptTypes()
                + SipUtils.CRLF
                + "a=accept-wrapped-types:"
                + getWrappedTypes()
                + SipUtils.CRLF
                + "a=setup:"
                + localSetup
                + SipUtils.CRLF
                + "a=path:"
                + getMsrpMgr().getLocalMsrpPath()
                + SipUtils.CRLF
                + "a=fingerprint:"
                + KeyStoreManager.getFingerPrint()
                + SipUtils.CRLF
                + "a=sendrecv"
                + SipUtils.CRLF;
      } else {
        sdp =
            "v=0"
                + SipUtils.CRLF
                + "o=- "
                + ntpTime
                + " "
                + ntpTime
                + " "
                + SdpUtils.formatAddressType(ipAddress)
                + SipUtils.CRLF
                + "s=-"
                + SipUtils.CRLF
                + "c="
                + SdpUtils.formatAddressType(ipAddress)
                + SipUtils.CRLF
                + "t=0 0"
                + SipUtils.CRLF
                + "m=message "
                + localMsrpPort
                + " "
                + getMsrpMgr().getLocalSocketProtocol()
                + " *"
                + SipUtils.CRLF
                + "a=accept-types:"
                + getAcceptTypes()
                + SipUtils.CRLF
                + "a=accept-wrapped-types:"
                + getWrappedTypes()
                + SipUtils.CRLF
                + "a=setup:"
                + localSetup
                + SipUtils.CRLF
                + "a=path:"
                + getMsrpMgr().getLocalMsrpPath()
                + SipUtils.CRLF
                + "a=sendrecv"
                + SipUtils.CRLF;
      }

      // Set the local SDP part in the dialog path
      getDialogPath().setLocalContent(sdp);

      // Test if the session should be interrupted
      if (isInterrupted()) {
        if (logger.isActivated()) {
          logger.info("Session has been interrupted: end of processing");
        }
        return;
      }

      // Create the MSRP server session
      if (localSetup.equals("passive")) {
        // Passive mode: client wait a connection
        MsrpSession session = getMsrpMgr().createMsrpServerSession(remotePath, this);
        session.setFailureReportOption(false);
        session.setSuccessReportOption(false);

        // Open the connection
        Thread thread =
            new Thread() {
              public void run() {
                try {
                  // Open the MSRP session
                  getMsrpMgr().openMsrpSession();

                  // Send an empty packet
                  sendEmptyDataChunk();
                } catch (IOException e) {
                  if (logger.isActivated()) {
                    logger.error("Can't create the MSRP server session", e);
                  }
                }
              }
            };
        thread.start();
      }

      // Create a 200 OK response
      if (logger.isActivated()) {
        logger.info("Send 200 OK");
      }
      SipResponse resp = null;
      if (!RcsSettings.getInstance().isCPMSupported()) {
        resp = SipMessageFactory.create200OkInviteResponse(getDialogPath(), getFeatureTags(), sdp);
      } else {
        if (logger.isActivated()) {
          logger.info("TerminatingFOne2OneSession2  CPMS");
        }
        resp =
            SipMessageFactory.createCpm200OkInviteResponse(
                getDialogPath(), getCpimFeatureTags(), sdp);
      }

      if (RcsSettings.getInstance().isCPMSupported()) {
        if (logger.isActivated()) {
          logger.info("TerminatingFOne2OneSession3  CPMS");
        }
        if (getContributionID() != null) {
          resp.addHeader(ChatUtils.HEADER_CONTRIBUTION_ID, getContributionID());
        }
        if (getConversationID() != null) {
          resp.addHeader(ChatUtils.HEADER_CONVERSATION_ID, getConversationID());
        }
        if (getInReplyID() != null) {
          resp.addHeader(ChatUtils.HEADER_INREPLY_TO_CONTRIBUTION_ID, getInReplyID());
        }
      }

      // The signalisation is established
      getDialogPath().sigEstablished();

      // Send response
      SipTransactionContext ctx =
          getImsService().getImsModule().getSipManager().sendSipMessageAndWait(resp);

      // Analyze the received response
      if (ctx.isSipAck()) {
        // ACK received
        if (logger.isActivated()) {
          logger.info("ACK request received");
        }

        // The session is established
        getDialogPath().sessionEstablished();

        // Create the MSRP client session
        if (localSetup.equals("active")) {
          // Active mode: client should connect
          MsrpSession session =
              getMsrpMgr().createMsrpClientSession(remoteHost, remotePort, remotePath, this);
          session.setFailureReportOption(false);
          session.setSuccessReportOption(false);

          // Open the MSRP session
          getMsrpMgr().openMsrpSession();

          // Send an empty packet
          sendEmptyDataChunk();
        }

        // Notify listeners
        for (int i = 0; i < getListeners().size(); i++) {
          getListeners().get(i).handleSessionStarted();
        }

        if (logger.isActivated()) {
          logger.info(
              "ABC ACK request received Dialog expire time: "
                  + getDialogPath().getSessionExpireTime());
        }

        // Start session timer
        if (getSessionTimerManager().isSessionTimerActivated(resp)) {
          getSessionTimerManager()
              .start(SessionTimerManager.UAS_ROLE, getDialogPath().getSessionExpireTime());
        }

        // Start the activity manager
        getActivityManager().start();

      } else {
        if (logger.isActivated()) {
          logger.info("No ACK received for INVITE");
        }

        // No response received: timeout
        handleError(new ChatError(ChatError.SESSION_INITIATION_FAILED));
      }
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Session initiation has failed", e);
      }

      // Unexpected error
      handleError(new ChatError(ChatError.UNEXPECTED_EXCEPTION, e.getMessage()));
    }
  }