/** * 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()); } } }
/** 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())); } }
/** * Send INVITE message * * @param invite SIP INVITE * @throws SipException */ @Override /** M: Modified to resolve the 403 error issue.@{ */ protected void sendInvite(SipRequest invite) throws SipException { /** @} */ // Send INVITE request SipTransactionContext ctx = getImsService().getImsModule().getSipManager().sendSipMessageAndWait(invite); // Wait response ctx.waitResponse(getResponseTimeout()); // Analyze the received response if (ctx.isSipResponse()) { // A response has been received if (ctx.getStatusCode() == 200) { // 200 OK handle200OK(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 407) { // 407 Proxy Authentication Required handle407Authentication(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 422) { // 422 Session Interval Too Small handle422SessionTooSmall(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 603) { // 603 Invitation declined handleError( new FileSharingError( FileSharingError.SESSION_INITIATION_DECLINED, ctx.getReasonPhrase())); } else if (ctx.getStatusCode() == 487) { // 487 Invitation cancelled handleError( new FileSharingError( FileSharingError.SESSION_INITIATION_CANCELLED, ctx.getReasonPhrase())); } /** M: Modified to resolve the 403 error issue.@{ */ else if (ctx.getStatusCode() == 403) { handle403Forbidden(invite); } /** @} */ else { // Other error response handleError( new FileSharingError( FileSharingError.SESSION_INITIATION_FAILED, ctx.getStatusCode() + " " + ctx.getReasonPhrase())); } } else { if (logger.isActivated()) { logger.debug("No response received for INVITE"); } /** * M:ALPS00507513. ADDED to reslove issue of wrong prompt in case of file transfer timeout@{ */ // No response received: timeout handleError(new FileSharingError(FileSharingError.SESSION_INITIATION_TIMEOUT)); /** @}* */ } }
/** * Send INVITE message * * @param invite SIP INVITE * @throws SipException */ public void sendInvite(SipRequest invite) throws SipException { // Send INVITE request SipTransactionContext ctx = getImsService() .getImsModule() .getSipManager() .sendSipMessageAndWait(invite, getResponseTimeout()); // Analyze the received response if (ctx.isSipResponse()) { // A response has been received if (ctx.getStatusCode() == 200) { // 200 OK handle200OK(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 404) { // 404 session not found handle404SessionNotFound(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 407) { // 407 Proxy Authentication Required handle407Authentication(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 422) { // 422 Session Interval Too Small handle422SessionTooSmall(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 480) { // 480 Temporarily Unavailable handle480Unavailable(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 486) { // 486 busy handle486Busy(ctx.getSipResponse()); } else if (ctx.getStatusCode() == 487) { // 487 Invitation cancelled handle487Cancel(ctx.getSipResponse()); } else { if (ctx.getStatusCode() == 603) { // 603 Invitation declined handle603Declined(ctx.getSipResponse()); } else // Other error response handleDefaultError(ctx.getSipResponse()); } } else { // No response received: timeout handleError( new ImsSessionBasedServiceError( ImsSessionBasedServiceError.SESSION_INITIATION_FAILED, "timeout")); } }