@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;
    }
  }
Beispiel #2
0
  /**
   * @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;
      }
    }
  }