예제 #1
0
  public void processResponse(ResponseEvent responseReceivedEvent) {
    System.out.println("Got a response");
    Response response = (Response) responseReceivedEvent.getResponse();
    Transaction tid = responseReceivedEvent.getClientTransaction();

    System.out.println(
        "Response received with client transaction id " + tid + ":\n" + response.getStatusCode());
    if (tid == null) {
      System.out.println("Stray response -- dropping ");
      return;
    }
    System.out.println("transaction state is " + tid.getState());
    System.out.println("Dialog = " + tid.getDialog());
    System.out.println("Dialog State is " + tid.getDialog().getState());

    try {
      if (response.getStatusCode() == Response.OK
          && ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
              .getMethod()
              .equals(Request.INVITE)) {
        // Request cancel = inviteTid.createCancel();
        // ClientTransaction ct =
        //  sipProvider.getNewClientTransaction(cancel);
        // ct.sendRequest();
        Dialog dialog = tid.getDialog();
        CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
        Request ackRequest = dialog.createAck(cseq.getSeqNumber());
        System.out.println("Sending ACK");
        dialog.sendAck(ackRequest);

        // Send a Re INVITE but this time force it
        // to use UDP as the transport. Else, it will
        // Use whatever transport was used to create
        // the dialog.
        if (reInviteCount == 0) {
          Request inviteRequest = dialog.createRequest(Request.INVITE);
          ((SipURI) inviteRequest.getRequestURI()).removeParameter("transport");
          ((ViaHeader) inviteRequest.getHeader(ViaHeader.NAME)).setTransport("udp");
          inviteRequest.addHeader(contactHeader);
          try {
            Thread.sleep(100);
          } catch (Exception ex) {
          }
          ClientTransaction ct = udpProvider.getNewClientTransaction(inviteRequest);
          dialog.sendRequest(ct);
          reInviteCount++;
        }
      }
    } catch (Exception ex) {
      ex.printStackTrace();
      System.exit(0);
    }
  }
예제 #2
0
  public void processResponse(ResponseEvent responseReceivedEvent) {

    // Log.info("Registering response...." + sipCallId);

    Response response = (Response) responseReceivedEvent.getResponse();
    int statusCode = response.getStatusCode();
    String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod();

    Log.debug("Got response " + response);

    if (statusCode == Response.OK) {
      isRegistered = true;

      Log.info(
          "Voice bridge successfully registered with "
              + registrar
              + " for "
              + proxyCredentials.getXmppUserName());
      PluginImpl.sipRegisterStatus = "Registered ok with " + proxyCredentials.getHost();

      sipServerCallback.removeSipListener(sipCallId);

    } else if (statusCode == Response.UNAUTHORIZED
        || statusCode == Response.PROXY_AUTHENTICATION_REQUIRED) {

      if (method.equals(Request.REGISTER)) {
        CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);

        if (cseq.getSequenceNumber() < 2) {

          ClientTransaction regTrans =
              SipService.handleChallenge(
                  response, responseReceivedEvent.getClientTransaction(), proxyCredentials);

          if (regTrans != null) {
            try {
              regTrans.sendRequest();

            } catch (Exception e) {

              Log.info("Registration failed, cannot send transaction " + e);
              PluginImpl.sipRegisterStatus = "Registration error " + e.toString();
            }

          } else {
            Log.info("Registration failed, cannot create transaction");
            PluginImpl.sipRegisterStatus = "Registration cannot create transaction";
          }

        } else {
          Log.info("Registration failed " + responseReceivedEvent);
          PluginImpl.sipRegisterStatus = "Registration failed";
        }
      }

    } else {
      Log.info("Unrecognized response:  " + response);
    }
  }
예제 #3
0
 public void processResponse(ResponseEvent responseEvent) {
   ClientTransaction ct = responseEvent.getClientTransaction();
   Response response = responseEvent.getResponse();
   ServerTransaction st = (ServerTransaction) ct.getApplicationData();
   try {
     Response otherResponse =
         messageFactory.createResponse(response.getStatusCode(), st.getRequest());
     if (response.getStatusCode() == 200 && ct.getRequest().getMethod().equals("INVITE")) {
       Address address =
           addressFactory.createAddress("B2BUA <sip:" + myAddress + ":" + myPort + ">");
       ContactHeader contactHeader = headerFactory.createContactHeader(address);
       response.addHeader(contactHeader);
       ToHeader toHeader = (ToHeader) otherResponse.getHeader(ToHeader.NAME);
       if (toHeader.getTag() == null)
         toHeader.setTag(new Long(counter.getAndIncrement()).toString());
       otherResponse.addHeader(contactHeader);
     }
     st.sendResponse(otherResponse);
   } catch (Exception e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
   }
 }
예제 #4
0
  public void processResponse(ResponseEvent responseReceivedEvent) {
    // System.out.println("Got a response");
    Response response = (Response) responseReceivedEvent.getResponse();
    Transaction tid = responseReceivedEvent.getClientTransaction();

    // System.out.println("Response received with client transaction id "
    // + tid + ":\n" + response);

    try {
      if (response.getStatusCode() == Response.OK
          && ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
              .getMethod()
              .equals(Request.INVITE)) {

        Dialog dialog = tid.getDialog();
        Request request = tid.getRequest();
        dialog.sendAck(request);
      }

    } catch (Exception ex) {
      ex.printStackTrace();
      System.exit(0);
    }
  }
예제 #5
0
  /**
   * handles the INVITED state.
   *
   * @param response the response
   * @param clientTransaction the client transaction
   * @throws SipException SIP stack related error
   */
  private void handleCallParticipantInvited(Response response, ClientTransaction clientTransaction)
      throws ParseException, SipException, InvalidArgumentException {
    FromHeader fromHeader = (FromHeader) response.getHeader(FromHeader.NAME);

    String displayName = fromHeader.getAddress().getDisplayName();

    int statusCode = response.getStatusCode();

    Logger.println(
        "handleCallParticipantInvited "
            + cp
            + " status "
            + statusCode
            + " "
            + response.getReasonPhrase());
    Logger.println("handleCallParticipantInvited , displayname " + displayName);

    CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);

    if (sipCallId.equals(callIdHeader.getCallId())
        && displayName.equals(cp.getDisplayName())
        && (statusCode == Response.OK || statusCode == Response.SESSION_PROGRESS)
        && ((CSeqHeader) response.getHeader(CSeqHeader.NAME)).getMethod().equals(Request.INVITE)) {
      if (statusCode == Response.SESSION_PROGRESS) {
        /*
         * For some calls, we never get an OK.  Instead we just get
         * SESSION_PROGRESS.  In order to handle these calls, we treat
         * SESSION_PROGRESS as OK.  If an OK arrives later, we'll
         * send an ACK.  This flag allows us to enable or
         * disable this workaround for each call.
         *
         * The problem with always treating SESSION_PROGRESS as OK
         * is that in a conference everybody will hear the ringing sound
         * which the remote call sends until the call is actually answered.
         * This can be avoided if joinConfirmation is specified.
         * The other problem is that if we treat SESSION_PROGRESS
         * as though the call has been answered, then we'll start
         * playing the treatment before a person really answers to
         * hear the treatment.
         */

        if (cp.getHandleSessionProgress() == false) {
          Logger.writeFile("Call " + cp + " Ignoring SESSION_PROGRESS");
          return;
        }

        Logger.writeFile("Call " + cp + " Treating SESSION_PROGRESS as OK");
      }

      if (response.getRawContent() == null) {
        Logger.error("Call " + cp + " no SDP in OK Response!");
        cancelRequest("SIP error!  no SDP in OK Response!");
        return;
      }

      this.clientTransaction = clientTransaction;

      if (statusCode == Response.OK) {
        gotOk = true;
        Logger.writeFile("Call " + cp + " Got OK, call answered\n" + response);
      }

      ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);

      /*
       * We got an OK response.
       *
       * send an ACK back to the CallParticipant
       */

      if (statusCode == Response.OK) {
        sipUtil.sendAck(clientTransaction);
        ackSent = true;
      }

      if (callAnswered) {
        Logger.writeFile("Call " + cp + " done processing OK");
        return;
      }

      /*
       * Remember the IP and port of where to send data to
       * the CallParticipant.
       */

      sdpBody = new String(response.getRawContent());

      SdpInfo sdpInfo;

      try {
        sdpInfo = sipUtil.getSdpInfo(sdpBody, false);

      } catch (ParseException e) {

        Logger.error("Call " + cp + " Invalid SDP in OK Response! " + e.getMessage());
        cancelRequest("SIP error!  Invalid SDP in OK Response!");
        return;
      }

      MediaInfo mediaInfo = sdpInfo.getMediaInfo();
      InetSocketAddress isa =
          new InetSocketAddress(sdpInfo.getRemoteHost(), sdpInfo.getRemotePort());
      InetSocketAddress rtcpAddress = sdpInfo.getRtcpAddress();
      setEndpointAddress(
          isa,
          mediaInfo.getPayload(),
          sdpInfo.getTransmitMediaInfo().getPayload(),
          sdpInfo.getTelephoneEventPayload(),
          rtcpAddress);

      /*
       * The CallParticipant has answered.
       * If join confirmation is required, we remain in the
       * INVITED state.  We set the callAnswered flag so that
       * if the join confirmation times out we know to
       * send a BYE rather than a CANCEL.
       */

      callAnswered = true;

      if (cp.getJoinConfirmationTimeout() == 0) {
        setState(CallState.ANSWERED);
      }

      /*
       * Start treatment if any and wait for it to finish.
       * When the treatment finishes, notification will
       * be delivered to our parent which will indicate
       * we're ready for the conference.
       *
       * If there's no treatment to be played, we're ready now
       * unless we're waiting for join confirmation..
       */
      initializeCallAnsweredTreatment();

      if (callAnsweredTreatment != null) {
        startCallAnsweredTreatment();
      } else {

        if (cp.getJoinConfirmationTimeout() == 0) {
          setState(CallState.ESTABLISHED);
        }
      }

    } else {
      Logger.writeFile("Call " + cp + " Ignoring response: " + response.getReasonPhrase());

      if (Logger.logLevel >= Logger.LOG_SIP) {
        Logger.println("Call " + cp + " Response: " + response);
      }
    }
  }
예제 #6
0
  public synchronized void processResponse(ResponseEvent responseReceivedEvent) {

    try {
      Response response = (Response) responseReceivedEvent.getResponse();
      ClientTransaction clientTransaction = responseReceivedEvent.getClientTransaction();

      int statusCode = response.getStatusCode();

      FromHeader fromHeader = (FromHeader) response.getHeader(FromHeader.NAME);

      String displayName = fromHeader.getAddress().getDisplayName();

      if (Logger.logLevel >= Logger.LOG_SIP) {
        Logger.println(
            "Response:  statusCode "
                + statusCode
                + " state "
                + getCallState()
                + " fromHeader "
                + displayName
                + " call participant "
                + cp.getName());
      }

      if (reasonCallTerminated != null) {
        /*
         * Ignore OK and Request Terminated.
         * XXX what's the symbol for 487?
         */
        if (statusCode != Response.OK && statusCode != 487) {
          if (Logger.logLevel >= Logger.LOG_SIP) {
            Logger.println("Call " + cp + ":  request cancelled, ignoring response");
          }
        }

        CallIdHeader callIdHeader = (CallIdHeader) response.getHeader("Call-Id");

        String sipCallId = callIdHeader.getCallId();
        sipServerCallback.removeSipListener(sipCallId);
        return;
      }

      /*
       * Some type of global failure that prevents the
       * CallParticipant from being contacted, report failure.
       */
      if (forceGatewayError) {
        statusCode = 500;
        forceGatewayError = false;
      }

      if (statusCode >= 500 && getState() == CallState.INVITED) {
        Logger.error(
            "Call " + cp + " gateway error:  " + statusCode + " " + response.getReasonPhrase());
        cancelRequest("gateway error: " + statusCode + " " + response.getReasonPhrase());
        return;

      } else if (statusCode == Response.PROXY_AUTHENTICATION_REQUIRED
          || statusCode == Response.UNAUTHORIZED) {

        if (cp.getProxyCredentials() != null) {
          try {
            SipServer.handleChallenge(response, clientTransaction, cp.getProxyCredentials())
                .sendRequest();

          } catch (Exception e) {

            Logger.println("Proxy authentification failed  " + e);
          }
        }
        return;

      } else if (statusCode >= 400) {

        // if we get a busy or an unknown error, play busy.
        Logger.println("Call " + cp + " got status code :" + statusCode);

        cp.setCallEndTreatment(null);
        cp.setConferenceJoinTreatment(null);
        cp.setConferenceLeaveTreatment(null);

        /*
         * play busy treatment, but deallocate any resources
         * held up by ringBack first, if any.
         */
        // stopCallAnsweredTreatment();

        if (statusCode == Response.BUSY_HERE) {
          try {
            if (busyTreatment != null) {
              addTreatment(busyTreatment);
              // busyTreatment.waitForTreatment();
            } else {
              Logger.println("Unable to play busy treatment!!!");
            }
          } catch (Exception e) {
            Logger.error("can't start busy treatment!" + sdpBody);
          }

          CallEvent callEvent = new CallEvent(CallEvent.BUSY_HERE);

          callEvent.setInfo(response.getReasonPhrase());

          sendCallEventNotification(callEvent);
        }

        // sipUtil.sendBye(clientTransaction);
        cancelRequest(response.getReasonPhrase());
        return;
      }

      /* state machine */
      switch (getState()) {
          /*
           * CallParticipant picked up, send treatment if any,
           * and wait for it to finish.
           */
        case CallState.INVITED:
          if (rejectCall) {
            Logger.error(
                "Call " + cp + " gateway error:  " + statusCode + " " + response.getReasonPhrase());

            cancelRequest("gateway error: " + statusCode + " " + response.getReasonPhrase());
            return;
          }

          handleCallParticipantInvited(response, clientTransaction);
          break;

          /*
           * Call established, the ACK needs to be resent.
           * According to Ranga, this is done by the NIST SIP Stack.
           */
        case CallState.ESTABLISHED:
          if (statusCode == Response.OK) {
            gotOk = true;

            Logger.writeFile("Call " + cp + " Got OK, ESTABLISHED");

            if (ackSent == false) {
              sipUtil.sendAck(clientTransaction);
              ackSent = true;
            }
          }
          break;

        case CallState.ENDED:
          break; // ignore the response

        default:
          Logger.error("Process Response bad state " + getState() + "\n" + response);
      }
    } catch (SipException e) {
      Logger.exception("Call " + cp + " SIP Stack error ", e);

      cancelRequest("processResponse:  SIP Stack error " + e.getMessage());
    } catch (Exception e) {
      Logger.exception("processResponse:  " + cp, e);

      cancelRequest("processResponse:  SIP Stack error " + e.getMessage());
    }
  }
예제 #7
0
  /**
   * Implements {@link MethodProcessor#processResponse(ResponseEvent)}. Handles only responses to
   * SUBSCRIBE requests because they are the only requests concerning event package subscribers (and
   * the only requests sent by them, for that matter) and if the processing of a given response
   * requires event package-specific handling, delivers the response to the matching
   * <tt>Subscription</tt> instance. Examples of such event package-specific handling include
   * letting the respective <tt>Subscription</tt> handle the success or failure in the establishment
   * of a subscription.
   *
   * @param responseEvent a <tt>ResponseEvent</tt> specifying the SIP <tt>Response</tt> to be
   *     processed
   * @return <tt>true</tt> if the SIP <tt>Response</tt> specified by <tt>responseEvent</tt> was
   *     processed; otherwise, <tt>false</tt>
   */
  @Override
  public boolean processResponse(ResponseEvent responseEvent) {
    Response response = responseEvent.getResponse();

    CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
    if (cseqHeader == null) {
      logger.error("An incoming response did not contain a CSeq header");
      return false;
    }
    if (!Request.SUBSCRIBE.equals(cseqHeader.getMethod())) return false;

    ClientTransaction clientTransaction = responseEvent.getClientTransaction();
    Request request = clientTransaction.getRequest();

    /*
     * Don't handle responses to requests not coming from this event
     * package.
     */
    if (request != null) {
      EventHeader eventHeader = (EventHeader) request.getHeader(EventHeader.NAME);
      if ((eventHeader == null) || !eventPackage.equalsIgnoreCase(eventHeader.getEventType()))
        return false;
    }

    // Find the subscription.
    CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);
    String callId = callIdHeader.getCallId();
    Subscription subscription = getSubscription(callId);

    // if it's the response to an unsubscribe message, we just ignore it
    // whatever the response is however if we need to handle a
    // challenge, we do it
    ExpiresHeader expHeader = response.getExpires();
    int statusCode = response.getStatusCode();
    SipProvider sourceProvider = (SipProvider) responseEvent.getSource();
    if (((expHeader != null) && (expHeader.getExpires() == 0))
        || (subscription == null)) // this handle the unsubscription
    // case where we removed the contact
    // from subscribedContacts
    {
      boolean processed = false;

      if ((statusCode == Response.UNAUTHORIZED)
          || (statusCode == Response.PROXY_AUTHENTICATION_REQUIRED)) {
        try {
          processAuthenticationChallenge(clientTransaction, response, sourceProvider);
          processed = true;
        } catch (OperationFailedException e) {
          logger.error("can't handle the challenge", e);
        }
      } else if ((statusCode != Response.OK) && (statusCode != Response.ACCEPTED)) processed = true;

      // any other cases (200/202) will imply a NOTIFY, so we will
      // handle the end of a subscription there
      return processed;
    }

    if ((statusCode >= Response.OK) && (statusCode < Response.MULTIPLE_CHOICES)) {
      // OK (200/202)
      if ((statusCode == Response.OK) || (statusCode == Response.ACCEPTED)) {
        if (expHeader == null) {
          // not conform to rfc3265
          logger.error("no Expires header in this response");
          return false;
        }

        SubscriptionRefreshTask refreshTask = new SubscriptionRefreshTask(subscription);
        subscription.setTimerTask(refreshTask);

        int refreshDelay = expHeader.getExpires();
        // try to keep a margin if the refresh delay allows it
        if (refreshDelay >= (2 * refreshMargin)) refreshDelay -= refreshMargin;
        timer.schedule(refreshTask, refreshDelay * 1000);

        // do it to remember the dialog in case of a polling
        // subscription (which means no call to finalizeSubscription)
        subscription.setDialog(clientTransaction.getDialog());

        subscription.processSuccessResponse(responseEvent, statusCode);
      }
    } else if ((statusCode >= Response.MULTIPLE_CHOICES) && (statusCode < Response.BAD_REQUEST)) {
      if (logger.isInfoEnabled())
        logger.info(
            "Response to subscribe to "
                + subscription.getAddress()
                + ": "
                + response.getReasonPhrase());
    } else if (statusCode >= Response.BAD_REQUEST) {
      // if the response is a 423 response, just re-send the request
      // with a valid expires value
      if (statusCode == Response.INTERVAL_TOO_BRIEF) {
        MinExpiresHeader min = (MinExpiresHeader) response.getHeader(MinExpiresHeader.NAME);

        if (min == null) {
          logger.error("no minimal expires value in this 423 " + "response");
          return false;
        }

        ExpiresHeader exp = request.getExpires();

        try {
          exp.setExpires(min.getExpires());
        } catch (InvalidArgumentException e) {
          logger.error("can't set the new expires value", e);
          return false;
        }

        ClientTransaction transac = null;
        try {
          transac = protocolProvider.getDefaultJainSipProvider().getNewClientTransaction(request);
        } catch (TransactionUnavailableException e) {
          logger.error("can't create the client transaction", e);
          return false;
        }

        try {
          transac.sendRequest();
        } catch (SipException e) {
          logger.error("can't send the new request", e);
          return false;
        }

        return true;
        // UNAUTHORIZED (401/407)
      } else if ((statusCode == Response.UNAUTHORIZED)
          || (statusCode == Response.PROXY_AUTHENTICATION_REQUIRED)) {
        try {
          processAuthenticationChallenge(clientTransaction, response, sourceProvider);
        } catch (OperationFailedException e) {
          logger.error("can't handle the challenge", e);

          removeSubscription(callId, subscription);
          subscription.processFailureResponse(responseEvent, statusCode);
        }
        // 408 480 486 600 603 : non definitive reject
        // others: definitive reject (or not implemented)
      } else {
        if (logger.isDebugEnabled()) logger.debug("error received from the network:\n" + response);

        removeSubscription(callId, subscription);
        subscription.processFailureResponse(responseEvent, statusCode);
      }
    }

    return true;
  }