@Override protected void doInviteResponse( final SipServletResponse res, final SIPCallImpl call, final Map<String, String> headers) throws Exception { try { if (_call2.equals(call)) { if (SIPHelper.isProvisionalResponse(res)) { call.setSIPCallState(SIPCall.State.ANSWERING); if (res.getStatus() == SipServletResponse.SC_SESSION_PROGRESS) { if (SIPHelper.getRawContentWOException(res) != null) { ((SIPOutgoingCall) _call1) .call(res.getRawContent(), _call2.getSipSession().getApplicationSession()); _invitedCall1 = true; } try { res.createPrack().send(); } catch (Rel100Exception ex) { LOG.warn(ex.getMessage()); } catch (IllegalStateException ex) { LOG.warn(ex.getMessage()); } } } else if (SIPHelper.isSuccessResponse(res)) { _response = res; if (!_invitedCall1) { ((SIPOutgoingCall) _call1) .call(res.getRawContent(), _call2.getSipSession().getApplicationSession()); } } else if (SIPHelper.isErrorResponse(res)) { Exception ex = getExceptionByResponse(res); done(getJoinCompleteCauseByResponse(res), ex); _call2.disconnect(true, getCallCompleteCauseByResponse(res), ex, null); } } else if (_call1.equals(call)) { if (SIPHelper.isProvisionalResponse(res)) { call.setSIPCallState(SIPCall.State.ANSWERING); if (res.getStatus() == SipServletResponse.SC_SESSION_PROGRESS) { if (SIPHelper.getRawContentWOException(res) != null) { SipServletRequest ack2 = null; if (_response != null) { final SipServletResponse origRes = _response; _response = null; ack2 = origRes.createAck(); SIPHelper.copyContent(res, ack2); } ack2.send(); _ackedCall2 = true; } try { res.createPrack().send(); } catch (Rel100Exception ex) { LOG.warn("", ex); } } } else if (SIPHelper.isSuccessResponse(res)) { final SipServletRequest ack1 = res.createAck(); ack1.send(); if (!_ackedCall2) { SipServletRequest ack2 = null; if (_response != null) { final SipServletResponse origRes = _response; _response = null; ack2 = origRes.createAck(); SIPHelper.copyContent(res, ack2); } ack2.send(); } _call2.setSIPCallState(State.ANSWERED); _call1.setSIPCallState(State.ANSWERED); _call1.linkCall(_call2, JoinType.DIRECT, _direction); done(JoinCompleteEvent.Cause.JOINED, null); } else if (SIPHelper.isErrorResponse(res)) { Exception ex = getExceptionByResponse(res); done(getJoinCompleteCauseByResponse(res), ex); _call1.disconnect(true, getCallCompleteCauseByResponse(res), ex, null); _call2.disconnect(true, getCallCompleteCauseByResponse(res), ex, null); } } } catch (final Exception e) { done(JoinCompleteEvent.Cause.ERROR, e); _call1.fail(e); _call2.fail(e); throw e; } }
/** * @param response * @throws IOException */ public static void forwardResponse(final SipServletResponse response) throws IOException { if (logger.isInfoEnabled()) { logger.info(String.format("B2BUA: Got response: \n %s", response)); } CallDetailRecordsDao records = daoManager.getCallDetailRecordsDao(); // container handles CANCEL related responses no need to forward them if (response.getStatus() == 487 || (response.getStatus() == 200 && response.getMethod().equalsIgnoreCase("CANCEL"))) { if (logger.isDebugEnabled()) { logger.debug("response to CANCEL not forwarding"); } // Update CallDetailRecord SipServletRequest request = (SipServletRequest) getLinkedSession(response).getAttribute(B2BUA_LAST_REQUEST); CallDetailRecord callRecord = records.getCallDetailRecord((Sid) request.getSession().getAttribute(CDR_SID)); if (callRecord != null) { logger.info("CDR found! Updating"); callRecord = callRecord.setStatus(CallStateChanged.State.CANCELED.name()); final DateTime now = DateTime.now(); callRecord = callRecord.setEndTime(now); final int seconds = (int) (DateTime.now().getMillis() - callRecord.getStartTime().getMillis()) / 1000; callRecord = callRecord.setDuration(seconds); records.updateCallDetailRecord(callRecord); } return; } // forward the response response.getSession().setAttribute(B2BUA_LAST_RESPONSE, response); SipServletRequest request = (SipServletRequest) getLinkedSession(response).getAttribute(B2BUA_LAST_REQUEST); SipServletResponse resp = request.createResponse(response.getStatus()); CallDetailRecord callRecord = records.getCallDetailRecord((Sid) request.getSession().getAttribute(CDR_SID)); if (response.getContent() != null) { final byte[] sdp = response.getRawContent(); String offer = null; if (response.getContentType().equalsIgnoreCase("application/sdp")) { // Issue 306: https://telestax.atlassian.net/browse/RESTCOMM-306 Registration registration = daoManager.getRegistrationsDao().getRegistration(callRecord.getTo()); final String externalIp = registration.getLocation().split(":")[1].split("@")[1]; try { logger.debug("Got original address from Registration :" + externalIp); offer = patch(sdp, externalIp); } catch (SdpException e) { logger.error("Unexpected exception while patching sdp ", e); } if (offer != null) { resp.setContent(offer, response.getContentType()); } else { resp.setContent(sdp, response.getContentType()); } } } resp.send(); // CallDetailRecord callRecord = records.getCallDetailRecord((Sid) // request.getSession().getAttribute(CDR_SID)); if (callRecord != null) { logger.info("CDR found! Updating"); if (!request.getMethod().equalsIgnoreCase("BYE")) { if (response.getStatus() == 100 || response.getStatus() == 180) { callRecord = callRecord.setStatus(CallStateChanged.State.RINGING.name()); } else if (response.getStatus() == 200 || response.getStatus() == 202) { callRecord = callRecord.setStatus(CallStateChanged.State.IN_PROGRESS.name()); callRecord = callRecord.setAnsweredBy(((SipURI) response.getTo().getURI()).getUser()); final DateTime now = DateTime.now(); callRecord = callRecord.setStartTime(now); } else if (response.getStatus() == 486 || response.getStatus() == 600) { callRecord = callRecord.setStatus(CallStateChanged.State.BUSY.name()); } else if (response.getStatus() > 400) { callRecord = callRecord.setStatus(CallStateChanged.State.FAILED.name()); } } else { callRecord = callRecord.setStatus(CallStateChanged.State.COMPLETED.name()); final DateTime now = DateTime.now(); callRecord = callRecord.setEndTime(now); final int seconds = (int) ((DateTime.now().getMillis() - callRecord.getStartTime().getMillis()) / 1000); callRecord = callRecord.setDuration(seconds); } records.updateCallDetailRecord(callRecord); } }
@Override protected void handleReinviteResponse( final SIPCallImpl call, final SipServletResponse res, final Map<String, String> headers) { if (res.getRequest().getAttribute(SIPCallDelegate.SIPCALL_HOLD_REQUEST) != null || res.getRequest().getAttribute(SIPCallDelegate.SIPCALL_UNHOLD_REQUEST) != null || res.getRequest().getAttribute(SIPCallDelegate.SIPCALL_DEAF_REQUEST) != null) { try { res.createAck().send(); if (call.getHoldState() == HoldState.Holding) { call.setHoldState(HoldState.Held); } else if (call.getHoldState() == HoldState.UnHolding) { call.setHoldState(HoldState.None); } else if (call.getDeafState() == HoldState.Deafing) { call.setDeafState(HoldState.Deafed); } else if (call.getDeafState() == HoldState.Undeafing) { call.setDeafState(HoldState.None); } } catch (IOException e) { LOG.error("IOException when sending back ACK.", e); call.setHoldState(HoldState.None); call.setDeafState(HoldState.None); call.fail(e); } finally { call.notify(); } } else if (res.getRequest().getAttribute(SIPCallDelegate.SIPCALL_MUTE_REQUEST) != null || res.getRequest().getAttribute(SIPCallDelegate.SIPCALL_UNMUTE_REQUEST) != null) { // send ACK. try { res.createAck().send(); // send the received SDP to peer. final SIPCallImpl peer = (SIPCallImpl) call.getLastPeer(); synchronized (peer) { if (call.getMuteState() == HoldState.Muting) { peer.setDeafState(HoldState.Deafing); } else { peer.setDeafState(HoldState.Undeafing); } SipServletRequest reInvite = peer.getSipSession().createRequest("INVITE"); reInvite.setAttribute(SIPCallDelegate.SIPCALL_DEAF_REQUEST, "true"); reInvite.setContent(res.getRawContent(), "application/sdp"); reInvite.send(); while (peer.getDeafState() != HoldState.Deafed && peer.getDeafState() != HoldState.None) { try { peer.wait(); } catch (InterruptedException e) { LOG.warn( "InterruptedException when wait make peer deaf, the peer's DeafState " + peer.getDeafState()); } } // set call deaf state if (call.getMuteState() == HoldState.Muting) { peer.setDeafState(HoldState.Deafed); call.setMuteState(HoldState.Muted); } else if (call.getMuteState() == HoldState.UnMuting) { peer.setDeafState(HoldState.None); call.setMuteState(HoldState.None); } } } catch (IOException e1) { LOG.error("IOException", e1); call.setMuteState(HoldState.None); call.fail(e1); } finally { call.notify(); } } else { try { final SipServletRequest req = res.getRequest(); final SipServletRequest newReq = (SipServletRequest) SIPHelper.getLinkSIPMessage(req); if (newReq != null) { SIPHelper.unlinkSIPMessage(req); final SipServletResponse newRes = newReq.createResponse(res.getStatus(), res.getReasonPhrase()); SIPHelper.addHeaders(newRes, headers); SIPHelper.copyContent(res, newRes); if (SIPHelper.isReinvite(newRes)) { newRes.getSession().setAttribute(REINVITE_PEER_RES, res); } newRes.send(); } } catch (final Exception e) { LOG.warn("", e); return; } } }