@Override public synchronized void forwardTo(final Call call, final Map<String, String> headers) throws SignalException { if (!(call instanceof SIPCall)) { throw new UnsupportedOperationException("Cannot forward to non-SIPCall."); } if (_req.isInitial()) { throw new IllegalArgumentException("Cannot forward initial SIP request."); } final SIPCallImpl scall = (SIPCallImpl) call; if (!scall.isAnswered()) { throw new IllegalStateException("Cannot forward to no-answered call."); } this.checkState(); _forwarded = true; final SipSession session = scall.getSipSession(); final SipServletRequest req = session.createRequest(_req.getMethod()); SIPHelper.addHeaders(req, headers); SIPHelper.copyContent(_req, req); SIPHelper.linkSIPMessage(_req, req); try { req.send(); } catch (final IOException e) { throw new SignalException(e); } }
@Override protected void unmute(SIPCallImpl call) throws IOException, SdpException { final SIPCallImpl peer = (SIPCallImpl) call.getLastPeer(); SipServletRequest reInvite = call.getSipSession().createRequest("INVITE"); reInvite.setAttribute(SIPCallDelegate.SIPCALL_UNMUTE_REQUEST, "true"); reInvite.setContent(createSendrecvSDP(call, peer.getRemoteSdp()), "application/sdp"); reInvite.send(); }
@Override protected void handleReinvite( final SIPCallImpl call, final SipServletRequest req, final Map<String, String> headers) throws Exception { final SIPCallImpl peer = (SIPCallImpl) call.getLastPeer(); final SipServletRequest newReq = peer.getSipSession().createRequest(req.getMethod()); SIPHelper.addHeaders(newReq, headers); SIPHelper.copyContent(req, newReq); SIPHelper.linkSIPMessage(req, newReq); newReq.send(); }
@Override protected void hold(SIPCallImpl call, boolean send) throws MsControlException, IOException, SdpException { final SIPCallImpl peer = (SIPCallImpl) call.getLastPeer(); SipServletRequest reInvite = call.getSipSession().createRequest("INVITE"); reInvite.setAttribute(SIPCallDelegate.SIPCALL_HOLD_REQUEST, "true"); reInvite.setContent(createSendonlySDP(call, peer.getRemoteSdp()), "application/sdp"); reInvite.send(); peer.hold(); }
@Override protected JoinDelegate createJoinDelegate( final SIPCallImpl other, final JoinType type, final Direction direction) { JoinDelegate retval = null; if (type == JoinType.DIRECT) { if (isNoAnswered()) { if (other.isNoAnswered()) { if (other instanceof SIPOutgoingCall) { retval = new DirectNI2NOJoinDelegate(this, (SIPOutgoingCall) other, direction); } else if (other instanceof SIPIncomingCall) { retval = new DirectNI2NIJoinDelegate(this, (SIPIncomingCall) other, direction); } } else if (other.isAnswered()) { if (other instanceof SIPOutgoingCall) { retval = new DirectNI2AOJoinDelegate(this, (SIPOutgoingCall) other, direction); } else if (other instanceof SIPIncomingCall) { retval = new DirectNI2AIJoinDelegate(this, (SIPIncomingCall) other, direction); } } } else if (isAnswered()) { if (other.isNoAnswered()) { if (other instanceof SIPOutgoingCall) { retval = new DirectAI2NOJoinDelegate(this, (SIPOutgoingCall) other, direction); } else if (other instanceof SIPIncomingCall) { retval = new DirectNI2AIJoinDelegate((SIPIncomingCall) other, this, direction); } } else if (other.isAnswered()) { if (other instanceof SIPOutgoingCall) { retval = new DirectAI2AOJoinDelegate(this, (SIPOutgoingCall) other, direction); } else if (other instanceof SIPIncomingCall) { retval = new DirectAI2AIJoinDelegate(this, (SIPIncomingCall) other, direction); } } } } else { retval = new BridgeJoinDelegate(this, other, direction); } return retval; }
@Override public synchronized void onEvent(final SdpPortManagerEvent event) { if (getSIPCallState() == SIPCall.State.PROGRESSING) { try { final byte[] sdp = event.getMediaServerSdp(); this.setLocalSDP(sdp); final SipServletResponse res = getSipInitnalRequest().createResponse(SipServletResponse.SC_SESSION_PROGRESS); res.setContent(sdp, "application/sdp"); try { res.sendReliably(); } catch (final Rel100Exception e) { LOG.warn("", e); res.send(); } setSIPCallState(SIPCall.State.PROGRESSED); this.notifyAll(); } catch (final IOException e) { LOG.warn("", e); } } super.onEvent(event); }
@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; } }
@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; } } }