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);
    }
  }
  /**
   * Sends a request from the TI, generates a response at the RI side, sends it back and checks
   * whether it arrives at the TI.
   */
  public void testReceiveResponse() {
    try {
      // 1. Create and send the original request

      Request invite = createTiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      try {
        // Send using TI and collect using RI
        eventCollector.collectRequestEvent(riSipProvider);
        tiSipProvider.sendRequest(invite);
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
          throw new TckInternalError("The sent request was not received by the RI!");
      } catch (TooManyListenersException ex) {
        throw new TckInternalError(
            "A TooManyListenersException was thrown while trying to add "
                + "a SipListener to an RI SipProvider.",
            ex);
      } catch (SipException ex) {
        throw new TiUnexpectedError("The TI failed to send the request!", ex);
      }
      Request receivedRequest = receivedRequestEvent.getRequest();
      // 2. Create and send the response
      Response ok = null;
      try {
        ok = riMessageFactory.createResponse(Response.OK, receivedRequest);
        addStatus(receivedRequest, ok);
      } catch (ParseException ex) {
        throw new TckInternalError("Failed to create an OK response!", ex);
      }
      // Send the response using the RI and collect using TI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Error while trying to add riSipProvider");
      }
      try {
        riSipProvider.sendResponse(ok);
      } catch (SipException ex) {
        throw new TckInternalError("Could not send back the response", ex);
      }
      waitForMessage();
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      // 3. Now ... do we like what we got?
      assertNotNull("The TI failed to receive the response!", responseEvent);
      assertNotNull("The TI failed to receive the response!", responseEvent.getResponse());
      assertNull(
          "The TI had implicitly created a client transaction! "
              + "Transactions should only be created explicitly using "
              + "the SipProvider.getNewXxxTransaction() method.",
          responseEvent.getClientTransaction());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
Example #3
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);
    }
  }
  /**
   * Dispatches the event received from a JAIN-SIP <tt>SipProvider</tt> to one of our "candidate
   * recipient" listeners.
   *
   * @param event the event received for a <tt>SipProvider</tt>.
   */
  public void processResponse(ResponseEvent event) {
    try {
      // we don't have to accept the transaction since we
      // created the request
      ClientTransaction transaction = event.getClientTransaction();
      if (logger.isTraceEnabled())
        logger.trace(
            "received response: "
                + event.getResponse().getStatusCode()
                + " "
                + event.getResponse().getReasonPhrase());

      if (transaction == null) {
        logger.warn("Transaction is null, probably already expired!");
        return;
      }

      ProtocolProviderServiceSipImpl service = getServiceData(transaction);
      if (service != null) {
        // Mark the dialog for the dispatching of later in-dialog
        // responses. If there is no dialog then the initial request
        // sure is marked otherwise we won't have found the service with
        // getServiceData(). The request has to be marked in case we
        // receive one more response in an out-of-dialog transaction.
        if (event.getDialog() != null) {
          SipApplicationData.setApplicationData(
              event.getDialog(), SipApplicationData.KEY_SERVICE, service);
        }
        service.processResponse(event);
      } else {
        logger.error(
            "We received a response which "
                + "wasn't marked, please report this to "
                + "*****@*****.**");
      }
    } catch (Throwable exc) {
      // any exception thrown within our code should be caught here
      // so that we could log it rather than interrupt stack activity with
      // it.
      this.logApplicationException(DialogTerminatedEvent.class, exc);
    }
  }
Example #5
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();
   }
 }
Example #6
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);
    }
  }
Example #7
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());
    }
  }
  /** Tests creating of ACK requests. */
  public void testCreateAck() {
    try {
      // 1. Create and send the original request

      Request invite = createTiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      ClientTransaction tran = null;
      try {
        tran = tiSipProvider.getNewClientTransaction(invite);
        eventCollector.collectRequestEvent(riSipProvider);
        tran.sendRequest();
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
          throw new TiUnexpectedError("The sent request was not received by the RI!");
      } catch (TooManyListenersException ex) {
        throw new TckInternalError(
            "A TooManyListenersException was thrown while trying to add "
                + "a SipListener to an RI SipProvider.",
            ex);
      } catch (SipException ex) {
        throw new TiUnexpectedError("The TI failed to send the request!", ex);
      }
      Request receivedRequest = receivedRequestEvent.getRequest();
      // 2. Create and send the response
      Response ok = null;
      try {
        ok = riMessageFactory.createResponse(Response.OK, receivedRequest);
      } catch (ParseException ex) {
        throw new TckInternalError("Failed to create an OK response!", ex);
      }
      // Send the response using the RI and collect using TI
      try {
        eventCollector.collectResponseEvent(tiSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError("Error while trying to add riSipProvider");
      }
      try {
        riSipProvider.sendResponse(ok);
      } catch (SipException ex) {
        throw new TckInternalError("Could not send back the response", ex);
      }
      waitForMessage();
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      // 3. Now let's create the ack
      if (responseEvent == null || responseEvent.getResponse() == null)
        throw new TiUnexpectedError("The TI failed to receive the response!");
      if (responseEvent.getClientTransaction() != tran)
        throw new TiUnexpectedError(
            "The TI has associated a new ClientTransaction to a response "
                + "instead of using existing one!");
      Request ack = null;
      try {
        ack = tran.createAck();
      } catch (SipException ex) {
        ex.printStackTrace();
        fail("A SipException was thrown while creating an ack request");
      }
      assertNotNull("ClientTransaction.createAck returned null!", ack);
      assertEquals(
          "The created request did not have a CANCEL method.", ack.getMethod(), Request.ACK);
      assertEquals(
          "Request-URIs of the original and the ack request do not match",
          ack.getRequestURI(),
          invite.getRequestURI());
      assertEquals(
          "Call-IDs of the original and the ack request do not match",
          ack.getHeader(CallIdHeader.NAME),
          invite.getHeader(CallIdHeader.NAME));
      assertEquals(
          "ToHeaders of the original and the ack request do not match",
          ack.getHeader(ToHeader.NAME),
          invite.getHeader(ToHeader.NAME));
      assertTrue(
          "The CSeqHeader's sequence number of the original and " + "the ack request do not match",
          ((CSeqHeader) ack.getHeader(CSeqHeader.NAME)).getSequenceNumber()
              == ((CSeqHeader) invite.getHeader(CSeqHeader.NAME)).getSequenceNumber());
      assertEquals(
          "The CSeqHeader's method of the ack request was not ACK",
          ((CSeqHeader) ack.getHeader(CSeqHeader.NAME)).getMethod(),
          Request.ACK);
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }

    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
  /**
   * Sends a request from the RI, generates a response at the TI side, sends it back and checks
   * whether it arrives at the RI.
   */
  public void testSendResponse() {
    try {
      // 1. Create and send the original request

      Request invite = createRiInviteRequest(null, null, null);
      RequestEvent receivedRequestEvent = null;
      try {
        // Send using RI and collect using TI
        eventCollector.collectRequestEvent(tiSipProvider);
        riSipProvider.sendRequest(invite);
        waitForMessage();
        receivedRequestEvent = eventCollector.extractCollectedRequestEvent();
        if (receivedRequestEvent == null || receivedRequestEvent.getRequest() == null)
          throw new TiUnexpectedError("The sent request was not received by the RI!");
      } catch (TooManyListenersException ex) {
        throw new TiUnexpectedError(
            "A TooManyListenersException was thrown while trying to add "
                + "a SipListener to a TI SipProvider.",
            ex);
      } catch (SipException ex) {
        throw new TckInternalError("The RI failed to send the request!", ex);
      }
      Request receivedRequest = receivedRequestEvent.getRequest();
      // 2. Create and send the response
      // Create an ok response. We are not testing the message factory so let's
      // not leave it a chance to mess something up and specify the response
      // as completely as possible.
      List via = new LinkedList();
      via.add(receivedRequest.getHeader(ViaHeader.NAME));
      Response ok = null;
      try {
        ok =
            tiMessageFactory.createResponse(
                Response.OK,
                (CallIdHeader) receivedRequest.getHeader(CallIdHeader.NAME),
                (CSeqHeader) receivedRequest.getHeader(CSeqHeader.NAME),
                (FromHeader) receivedRequest.getHeader(FromHeader.NAME),
                (ToHeader) receivedRequest.getHeader(ToHeader.NAME),
                via,
                (MaxForwardsHeader) receivedRequest.getHeader(MaxForwardsHeader.NAME));
        addStatus(receivedRequest, ok);
      } catch (ParseException ex) {
        throw new TiUnexpectedError("Failed to create an OK response!", ex);
      }
      // Send the response using the TI and collect using RI
      try {
        eventCollector.collectResponseEvent(riSipProvider);
      } catch (TooManyListenersException ex) {
        throw new TckInternalError("Error while trying to add riSipProvider");
      }
      try {
        tiSipProvider.sendResponse(ok);
      } catch (SipException ex) {
        ex.printStackTrace();
        fail("A SipException occurred while trying to send an ok response.");
      }
      waitForMessage();
      ResponseEvent responseEvent = eventCollector.extractCollectedResponseEvent();
      assertNotNull("The sent response was not received by the RI!", responseEvent);
      assertNotNull("The sent response was not received by the RI!", responseEvent.getResponse());
    } catch (Throwable exc) {
      exc.printStackTrace();
      fail(exc.getClass().getName() + ": " + exc.getMessage());
    }
    assertTrue(new Exception().getStackTrace()[0].toString(), true);
  }
    /**
     * Process a response from a distant contact.
     *
     * @param responseEvent the <tt>ResponseEvent</tt> containing the newly received SIP response.
     * @return <tt>true</tt> if the specified event has been handled by this processor and shouldn't
     *     be offered to other processors registered for the same method; <tt>false</tt>, otherwise
     */
    @Override
    public boolean processResponse(ResponseEvent responseEvent) {
      synchronized (messageProcessors) {
        for (SipMessageProcessor listener : messageProcessors)
          if (!listener.processResponse(responseEvent, sentMsg)) return true;
      }

      Request req = responseEvent.getClientTransaction().getRequest();
      int status = responseEvent.getResponse().getStatusCode();
      // content of the response
      String content = null;

      try {
        content = new String(req.getRawContent(), getCharset(req));
      } catch (UnsupportedEncodingException exc) {
        if (logger.isDebugEnabled()) logger.debug("failed to convert the message charset", exc);
        content = new String(req.getRawContent());
      }

      // to who did we send the original message ?
      ToHeader toHeader = (ToHeader) req.getHeader(ToHeader.NAME);

      if (toHeader == null) {
        // should never happen
        logger.error("send a request without a to header");
        return false;
      }

      Contact to = opSetPersPresence.resolveContactID(toHeader.getAddress().getURI().toString());

      if (to == null) {
        logger.error(
            "Error received a response from an unknown contact : "
                + toHeader.getAddress().getURI().toString()
                + " : "
                + responseEvent.getResponse().getStatusCode()
                + " "
                + responseEvent.getResponse().getReasonPhrase());

        // error for delivering the message
        fireMessageDeliveryFailed(
            // we don't know what message it concerns
            createMessage(content), to, MessageDeliveryFailedEvent.INTERNAL_ERROR);
        return false;
      }

      // we retrieve the original message
      String key = ((CallIdHeader) req.getHeader(CallIdHeader.NAME)).getCallId();

      Message newMessage = sentMsg.get(key);

      if (newMessage == null) {
        // should never happen
        logger.error("Couldn't find the message sent");

        // error for delivering the message
        fireMessageDeliveryFailed(
            // we don't know what message it is
            createMessage(content), to, MessageDeliveryFailedEvent.INTERNAL_ERROR);
        return true;
      }

      // status 401/407 = proxy authentification
      if (status >= 400 && status != 401 && status != 407) {
        if (logger.isInfoEnabled())
          logger.info(
              responseEvent.getResponse().getStatusCode()
                  + " "
                  + responseEvent.getResponse().getReasonPhrase());

        // error for delivering the message
        MessageDeliveryFailedEvent evt =
            new MessageDeliveryFailedEvent(
                newMessage,
                to,
                MessageDeliveryFailedEvent.NETWORK_FAILURE,
                System.currentTimeMillis(),
                responseEvent.getResponse().getStatusCode()
                    + " "
                    + responseEvent.getResponse().getReasonPhrase());
        fireMessageEvent(evt);
        sentMsg.remove(key);
      } else if (status == 401 || status == 407) {
        // proxy ask for authentification
        if (logger.isDebugEnabled())
          logger.debug(
              "proxy asks authentication : "
                  + responseEvent.getResponse().getStatusCode()
                  + " "
                  + responseEvent.getResponse().getReasonPhrase());

        ClientTransaction clientTransaction = responseEvent.getClientTransaction();
        SipProvider sourceProvider = (SipProvider) responseEvent.getSource();

        try {
          processAuthenticationChallenge(
              clientTransaction, responseEvent.getResponse(), sourceProvider);
        } catch (OperationFailedException ex) {
          logger.error("can't solve the challenge", ex);

          // error for delivering the message
          MessageDeliveryFailedEvent evt =
              new MessageDeliveryFailedEvent(
                  newMessage,
                  to,
                  MessageDeliveryFailedEvent.NETWORK_FAILURE,
                  System.currentTimeMillis(),
                  ex.getMessage());
          fireMessageEvent(evt);
          sentMsg.remove(key);
        }
      } else if (status >= 200) {
        if (logger.isDebugEnabled())
          logger.debug(
              "Ack received from the network : "
                  + responseEvent.getResponse().getStatusCode()
                  + " "
                  + responseEvent.getResponse().getReasonPhrase());

        // we delivered the message
        MessageDeliveredEvent msgDeliveredEvt =
            new MessageDeliveredEvent(newMessage, to, System.currentTimeMillis());

        fireMessageEvent(msgDeliveredEvt);

        // we don't need this message anymore
        sentMsg.remove(key);
      }

      return true;
    }
  /**
   * 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;
  }