/**
   * Place to put some hacks if needed on incoming requests.
   *
   * @param event the incoming request event.
   * @return status <code>true</code> if we don't need to process this message, just discard it and
   *     <code>false</code> otherwise.
   */
  private boolean applyNonConformanceHacks(RequestEvent event) {
    Request request = event.getRequest();
    try {
      /*
       * Max-Forwards is required, yet there are UAs which do not
       * place it. SipProvider#getNewServerTransaction(Request)
       * will throw an exception in the case of a missing
       * Max-Forwards header and this method will eventually just
       * log it thus ignoring the whole event.
       */
      if (request.getHeader(MaxForwardsHeader.NAME) == null) {
        // it appears that some buggy providers do send requests
        // with no Max-Forwards headers, as we are at application level
        // and we know there will be no endless loops
        // there is no problem of adding headers and process normally
        // this messages
        MaxForwardsHeader maxForwards =
            SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
        request.setHeader(maxForwards);
      }
    } catch (Throwable ex) {
      logger.warn("Cannot apply incoming request modification!", ex);
    }

    try {
      // using asterisk voice mail initial notify for messages
      // is ok, but on the fly received messages their notify comes
      // without subscription-state, so we add it in order to be able to
      // process message.
      if (request.getMethod().equals(Request.NOTIFY)
          && request.getHeader(EventHeader.NAME) != null
          && ((EventHeader) request.getHeader(EventHeader.NAME))
              .getEventType()
              .equals(OperationSetMessageWaitingSipImpl.EVENT_PACKAGE)
          && request.getHeader(SubscriptionStateHeader.NAME) == null) {
        request.addHeader(
            new HeaderFactoryImpl().createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE));
      }
    } catch (Throwable ex) {
      logger.warn("Cannot apply incoming request modification!", ex);
    }

    try {
      // receiving notify message without subscription state
      // used for keep-alive pings, they have done their job
      // and are no more need. Skip processing them to avoid
      // filling logs with unneeded exceptions.
      if (request.getMethod().equals(Request.NOTIFY)
          && request.getHeader(SubscriptionStateHeader.NAME) == null) {
        return true;
      }
    } catch (Throwable ex) {
      logger.warn("Cannot apply incoming request modification!", ex);
    }

    return false;
  }
Exemple #2
0
  /**
   * Attach any custom headers pre configured for the account. Added only to message Requests. The
   * header account properties are of form: ConfigHeader.N.Name=HeaderName
   * ConfigHeader.N.Value=HeaderValue ConfigHeader.N.Method=SIP_MethodName (optional) Where N is the
   * index of the header, multiple custom headers can be added. Name is the header name to use and
   * Value is its value. The optional property is whether to use a specific request method to attach
   * headers to or if missing we will attach it to all requests.
   *
   * @param message the message that we'd like to attach custom headers to.
   * @param protocolProvider the protocol provider to check for configured custom headers.
   */
  static void attachConfigHeaders(
      Message message, ProtocolProviderServiceSipImpl protocolProvider) {
    if (message instanceof Response) return;

    Request request = (Request) message;

    Map<String, String> props = protocolProvider.getAccountID().getAccountProperties();

    Map<String, Map<String, String>> headers = new HashMap<String, Map<String, String>>();

    // parse the properties into the map where the index is the key
    for (Map.Entry<String, String> entry : props.entrySet()) {
      String pName = entry.getKey();
      String prefStr = entry.getValue();
      String name;
      String ix;

      if (!pName.startsWith(ACC_PROPERTY_CONFIG_HEADER) || prefStr == null) continue;

      prefStr = prefStr.trim();

      if (pName.contains(".")) {
        pName = pName.replaceAll(ACC_PROPERTY_CONFIG_HEADER + ".", "");
        name = pName.substring(pName.lastIndexOf('.') + 1).trim();

        if (!pName.contains(".")) continue;

        ix = pName.substring(0, pName.lastIndexOf('.')).trim();
      } else continue;

      Map<String, String> headerValues = headers.get(ix);

      if (headerValues == null) {
        headerValues = new HashMap<String, String>();
        headers.put(ix, headerValues);
      }

      headerValues.put(name, prefStr);
    }

    // process the found custom headers
    for (Map<String, String> headerValues : headers.values()) {
      String method = headerValues.get(ACC_PROPERTY_CONFIG_HEADER_METHOD);

      // if there is a method setting and is different from
      // current request method skip this header
      // if any of the required properties are missing skip (Name & Value)
      if ((method != null && !request.getMethod().equalsIgnoreCase(method))
          || !headerValues.containsKey(ACC_PROPERTY_CONFIG_HEADER_NAME)
          || !headerValues.containsKey(ACC_PROPERTY_CONFIG_HEADER_VALUE)) continue;

      try {
        String name = headerValues.get(ACC_PROPERTY_CONFIG_HEADER_NAME);
        String value = processParams(headerValues.get(ACC_PROPERTY_CONFIG_HEADER_VALUE), request);

        Header h = request.getHeader(name);

        // makes possible overriding already created headers which
        // are not custom one
        // RouteHeader is used by ProxyRouter/DefaultRouter and we
        // cannot use it as custom header if we want to add it
        if ((h != null && !(h instanceof CustomHeader)) || name.equals(SIPHeaderNames.ROUTE)) {
          request.setHeader(protocolProvider.getHeaderFactory().createHeader(name, value));
        } else request.addHeader(new CustomHeaderList(name, value));
      } catch (Exception e) {
        logger.error("Cannot create custom header", e);
      }
    }
  }