/**
  * Parses the header.
  *
  * @return parsed Expires header
  * @exception ParseException if a parsing error occurs
  */
 public Header parse() throws ParseException {
   ExpiresHeader expires = new ExpiresHeader();
   if (debug) dbg_enter("parse");
   try {
     lexer.match(TokenTypes.EXPIRES);
     lexer.SPorHT();
     lexer.match(':');
     lexer.SPorHT();
     String nextId = lexer.getNextId();
     lexer.match('\n');
     try {
       int delta = Integer.parseInt(nextId);
       expires.setExpires(delta);
       return expires;
     } catch (NumberFormatException ex) {
       throw createParseException("bad integer format");
     }
   } finally {
     if (debug) dbg_leave("parse");
   }
 }
  public void processOK(Response responseCloned, ClientTransaction clientTransaction) {
    try {
      logger.debug("Processing OK for SUBSCRIBE in progress...");

      ExpiresHeader expiresHeader = (ExpiresHeader) responseCloned.getHeader(ExpiresHeader.NAME);
      if (expiresHeader != null && expiresHeader.getExpires() == 0) {
        logger.debug(
            "DEBUG, IMSubscribeProcessing, processOK(), we got" + " the OK for the unsubscribe...");
      } else {

        // We have to create or update the presentity!
        PresenceManager presenceManager = imUA.getPresenceManager();
        String presentityURL = IMUtilities.getKey(responseCloned, "To");

        Dialog dialog = clientTransaction.getDialog();
        if (dialog != null) presenceManager.addPresentity(presentityURL, responseCloned, dialog);
        else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processOK(), the"
                  + " dialog for the SUBSCRIBE we sent is null!!!"
                  + " No presentity added....");
        }

        // WE have to create a new Buddy in the GUI!!!
        InstantMessagingGUI imGUI = imUA.getInstantMessagingGUI();
        BuddyList buddyList = imGUI.getBuddyList();
        if (!buddyList.hasBuddy(presentityURL)) {
          buddyList.addBuddy(presentityURL, "offline");
        } else {
          logger.debug("The buddy is already in the Buddy list...");
        }
      }
      logger.debug("Processing OK for SUBSCRIBE completed...");
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  public void processSubscribe(Request request, ServerTransaction serverTransaction) {
    logger.debug("Processing SUBSCRIBE in progress ");
    try {

      MessageFactory messageFactory = imUA.getMessageFactory();
      HeaderFactory headerFactory = imUA.getHeaderFactory();
      AddressFactory addressFactory = imUA.getAddressFactory();
      Dialog dialog = serverTransaction.getDialog();

      // ********** Terminating subscriptions **********
      ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(ExpiresHeader.NAME);
      if (expiresHeader != null && expiresHeader.getExpires() == 0) {
        if (dialog != null) {
          // Terminating an existing subscription
          Response response = messageFactory.createResponse(Response.OK, request);
          serverTransaction.sendResponse(response);
          IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
          imNotifyProcessing.sendNotify(response, null, dialog);
          return;
        } else {
          // Terminating an non existing subscription
          Response response =
              messageFactory.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, request);
          serverTransaction.sendResponse(response);
          return;
        }
      }

      // ********** Non-terminating subscriptions ************

      // send a 202 Accepted while waiting for authorization from user
      Response response = messageFactory.createResponse(Response.ACCEPTED, request);
      // Tag:
      ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
      if (toHeader.getTag() == null)
        toHeader.setTag(new Integer((int) (Math.random() * 10000)).toString());
      serverTransaction.sendResponse(response);
      logger.debug(response.toString());

      // We have to ask the user to authorize the guy to be in his buddy
      // list
      String presentityURL = IMUtilities.getKey(request, "From");
      SipProvider sipProvider = imUA.getSipProvider();
      InstantMessagingGUI imGUI = imUA.getInstantMessagingGUI();
      boolean authorization = imGUI.getAuthorizationForBuddy(presentityURL);
      if (authorization) {
        logger.debug(
            "DEBUG: SubscribeProcessing, processSubscribe(), " + " Response 202 Accepted sent.");

        // We have to create or update the subscriber!
        PresenceManager presenceManager = imUA.getPresenceManager();
        String subscriberURL = IMUtilities.getKey(request, "From");

        if (dialog != null) presenceManager.addSubscriber(subscriberURL, response, dialog);
        else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processSubscribe(), the"
                  + " dialog for the SUBSCRIBE we received is null!!! No subscriber added....");
          return;
        }

        // Let's see if this buddy is in our buddy list
        // if not let's ask to add him!
        BuddyList buddyList = imGUI.getBuddyList();
        ListenerInstantMessaging listenerIM = imGUI.getListenerInstantMessaging();
        if (!buddyList.hasBuddy(subscriberURL)) {
          // Let's ask:
          listenerIM.addContact(subscriberURL);
        }

        /** ********************** send NOTIFY ************************* */
        // We send a NOTIFY for any of our status but offline
        String localStatus = listenerIM.getLocalStatus();
        if (!localStatus.equals("offline")) {
          IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
          Subscriber subscriber = presenceManager.getSubscriber(subscriberURL);
          // Response okSent=subscriber.getOkSent();

          subscriberURL = subscriber.getSubscriberName();

          String contactAddress = imUA.getIMAddress() + ":" + imUA.getIMPort();

          String subStatus = listenerIM.getLocalStatus();
          String status = null;
          if (subStatus.equals("offline")) status = "closed";
          else status = "open";
          String xmlBody =
              imNotifyProcessing.xmlPidfParser.createXMLBody(
                  status, subStatus, subscriberURL, contactAddress);
          imNotifyProcessing.sendNotify(response, xmlBody, dialog);
        }
      } else {
        // User did not authorize subscription. Terminate it!
        logger.debug(
            "DEBUG, IMSubsribeProcessing, processSubscribe(), " + " Subscription declined!");
        logger.debug(
            "DEBUG, IMSubsribeProcessing, processSubscribe(), "
                + " Sending a Notify with Subscribe-state=terminated");

        IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
        if (dialog != null) {
          imNotifyProcessing.sendNotify(response, null, dialog);
          logger.debug(
              "DEBUG, IMSubsribeProcessing, processSubscribe(), "
                  + " Sending a Notify with Subscribe-state=terminated");
        } else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processSubscribe(), the"
                  + " dialog for the SUBSCRIBE we received is null!!! \n"
                  + "   No terminating Notify sent");
        }
        imNotifyProcessing.sendNotify(response, null, dialog);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
예제 #4
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;
  }