⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snmp.java

📁 snmp4j
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
    if (pdu.size() == 0) {
      logger.error("Illegal report PDU received from " + e.getPeerAddress() +
                   " missing report variable binding");
      return;
    }
    VariableBinding vb = pdu.get(0);
    if (vb == null) {
      logger.error("Received illegal REPORT PDU from " + e.getPeerAddress());
      return;
    }
    OID firstOID = vb.getOid();
    boolean resend = false;
    if (request.requestStatus < request.maxRequestStatus) {
      switch (request.requestStatus) {
        case 0:
          if (SnmpConstants.usmStatsUnknownEngineIDs.equals(firstOID)) {
            resend = true;
          }
          else if (SnmpConstants.usmStatsNotInTimeWindows.equals(firstOID)) {
            request.requestStatus++;
            resend = true;
          }
          break;
        case 1:
          if (SnmpConstants.usmStatsNotInTimeWindows.equals(firstOID)) {
            resend = true;
          }
          break;
      }
    }
    // if legal report PDU received, then resend request
    if (resend) {
      logger.debug("Send new request after report.");
      request.requestStatus++;
      try {
        PduHandle resentHandle =
          sendMessage(request.pdu, request.target, e.getTransportMapping());
        // make sure reference to handle is hold until request is finished,
        // because otherwise cache information may get lost (WeakHashMap)
        request.key = resentHandle;
      }
      catch (IOException iox) {
        logger.error("Failed to send message to " + request.target + ": " +
                     iox.getMessage());
        return;
      }
    }
    else {
      boolean intime = request.cancel();
      // remove pending request
      // (sync is not needed as request is already canceled)
      pendingRequests.remove(handle);
      if (intime) {
        // return report
        request.listener.onResponse(new ResponseEvent(this,
            e.getPeerAddress(),
            request.pdu,
            pdu,
            request.userObject));
      }
      else {
        // silently drop late report
        if (logger.isInfoEnabled()) {
          logger.info("Received late report from " +
                      e.getPeerAddress() +
                      " with request ID " + pdu.getRequestID());
        }
      }
    }
  }

  /**
   * Removes a <code>CommandResponderEvent</code> from this SNMP session.
   * @param listener
   *    a previously added <code>CommandResponder</code> instance.
   */
  public synchronized void removeCommandResponder(CommandResponder listener) {
    if (commandResponderListeners != null &&
        commandResponderListeners.contains(listener)) {
      Vector v = (Vector) commandResponderListeners.clone();
      v.removeElement(listener);
      commandResponderListeners = v;
    }
  }

  /**
   * Adds a <code>CommandResponder</code> to this SNMP session.
   * The command responder will then be informed about incoming SNMP PDUs of
   * any kind that are not related to any outstanding requests of this SNMP
   * session.
   *
   * @param listener CommandResponder
   *    the <code>CommandResponder</code> instance to be added.
   */
  public synchronized void addCommandResponder(CommandResponder listener) {
    Vector v = (commandResponderListeners == null) ?
        new Vector(2) : (Vector) commandResponderListeners.clone();
    if (!v.contains(listener)) {
      v.addElement(listener);
      commandResponderListeners = v;
    }
  }

  /**
   * Fires a <code>CommandResponderEvent</code> event to inform listeners about
   * a received PDU. If a listener has marked the event as processed further
   * listeners will not be informed about the event.
   * @param event
   *    a <code>CommandResponderEvent</code>.
   */
  protected void fireProcessPdu(CommandResponderEvent event) {
    if (commandResponderListeners != null) {
      Vector listeners = commandResponderListeners;
      int count = listeners.size();
      for (int i = 0; i < count; i++) {
        ((CommandResponder) listeners.elementAt(i)).processPdu(event);
        // if event is marked as processed the event is not forwarded to
        // remaining listeners
        if (event.isProcessed()) {
          return;
        }
      }
    }
  }

  /**
   * Gets the timeout model associated with this SNMP session.
   * @return
   *    a TimeoutModel instance (never <code>null</code>).
   * @see #setTimeoutModel(TimeoutModel timeoutModel)
   */
  public TimeoutModel getTimeoutModel() {
    return timeoutModel;
  }

  /**
   * Sets the timeout model for this SNMP session. The default timeout model
   * sends retries whenever the time specified by the <code>timeout</code>
   * parameter of the target has elapsed without a response beeing received for
   * the request. By specifying a different timeout model this behaviour can
   * be changed.
   * @param timeoutModel
   *    a <code>TimeoutModel</code> instance (must not be <code>null</code>).
   */
  public void setTimeoutModel(TimeoutModel timeoutModel) {
    if (timeoutModel == null) {
      throw new NullPointerException("Timeout model cannot be null");
    }
    this.timeoutModel = timeoutModel;
  }

  class PendingRequest extends TimerTask {

    private PduHandle key;
    private int retryCount;
    private ResponseListener listener;
    private Object userObject;

    private PDU pdu;
    private Target target;
    private TransportMapping transport;

    private int requestStatus = 0;
    // Maximum request status - allows to receive up to two reports and then
    // send the original request again. A value of 0 is used for discovery.
    private int maxRequestStatus = 2;

    private volatile boolean finished = false;


    public PendingRequest(PduHandle key,
                          ResponseListener listener,
                          Object userObject,
                          PDU pdu,
                          Target target,
                          TransportMapping transport) {
      this.key = key;
      this.userObject = userObject;
      this.listener = listener;
      this.retryCount = target.getRetries();
      this.pdu = pdu;
      this.target = target;
      this.transport = transport;
    }

    private PendingRequest(PendingRequest other) {
      this.key = other.key;
      this.userObject = other.userObject;
      this.listener = other.listener;
      this.retryCount = other.retryCount - 1;
      this.pdu = other.pdu;
      this.target = other.target;
      this.requestStatus = other.requestStatus;
    }

    /**
     * run
     */
    public synchronized void run() {
      if ((!finished) && (retryCount > 0)) {
        retryCount--;
        try {
          sendMessage(pdu, target, transport);
          logger.debug("Running pending request with handle: " + key);
          PendingRequest nextRetry = new PendingRequest(this);
          synchronized (sync) {
            pendingRequests.put(key, nextRetry);
            long delay =
                timeoutModel.getRetryTimeout(target.getRetries() - retryCount,
                                             target.getRetries(),
                                             target.getTimeout());
            timer.schedule(nextRetry, delay);
          }
        }
        catch (IOException ex) {
          finished = true;
          logger.error("Failed to send SNMP message to " + target.toString() +
                       ": " +
                       ex.getMessage());
          messageDispatcher.releaseStateReference(target.getVersion(), key);
          listener.onResponse(new ResponseEvent(Snmp.this, null,
                                                pdu, null, userObject,
                                                ex));
        }
      }
      else if (!finished) {
        finished = true;
        pendingRequests.remove(key);

        // request timed out
        if (logger.isDebugEnabled()) {
          logger.debug("Request timed out: " + key.getTransactionID());
        }
        messageDispatcher.releaseStateReference(target.getVersion(), key);
        listener.onResponse(new ResponseEvent(Snmp.this, null,
                                              pdu, null, userObject));
      }
    }

    public synchronized boolean setFinished() {
      boolean currentState = finished;
      this.finished = true;
      return currentState;
    }

    public void setMaxRepuestStatus(int maxRepuestStatus) {
      this.maxRequestStatus = maxRepuestStatus;
    }

    public int getMaxRepuestStatus() {
      return maxRequestStatus;
    }

  }

  class AsyncRequestKey {
    private PDU request;
    private ResponseListener listener;

    public AsyncRequestKey(PDU request, ResponseListener listener) {
      this.request = request;
      this.listener = listener;
    }

    /**
     * Indicates whether some other object is "equal to" this one.
     *
     * @param obj the reference object with which to compare.
     * @return <code>true</code> if this object is the same as the obj argument;
     *   <code>false</code> otherwise.
     */
    public boolean equals(Object obj) {
      if (obj instanceof AsyncRequestKey) {
        AsyncRequestKey other = (AsyncRequestKey) obj;
        return (request.equals(other.request) && listener.equals(other.listener));
      }
      return false;
    }

    public int hashCode() {
      return request.hashCode();
    }
  }

  class SyncResponseListener implements ResponseListener {

    private ResponseEvent response = null;

    /**
     * onResponse
     *
     * @param event ResponseEvent
     */
    public synchronized void onResponse(ResponseEvent event) {
      this.response = event;
      this.notify();
    }

    public ResponseEvent getResponse() {
      return response;
    }

  }


  class NotificationDispatcher implements CommandResponder {
    // A mapping of transport addresses to transport mappings of notification
    // listeners
    private Hashtable notificationListeners = new Hashtable(10);
    private Hashtable notificationTransports = new Hashtable(10);

    public NotificationDispatcher() {
    }

    public synchronized void addNotificationListener(Address listenAddress,
                                                     TransportMapping transport,
                                                     CommandResponder listener){
      notificationListeners.put(listenAddress, transport);
      notificationTransports.put(transport, listener);
    }

    public synchronized boolean
        removeNotificationListener(Address listenAddress)
    {
      TransportMapping tm =
          (TransportMapping)notificationListeners.remove(listenAddress);
      if (tm == null) {
        return false;
      }
      tm.removeMessageDispatcher(messageDispatcher);

      try {
        tm.close();
      }
      catch (IOException ex) {
        logger.error(ex);
        if (logger.isDebugEnabled()) {
          ex.printStackTrace();
        }
      }
      return true;
    }

    public synchronized void closeAll() {
      notificationTransports.clear();
      for (Iterator it = notificationListeners.values().iterator();
           it.hasNext();) {
        TransportMapping tm = (TransportMapping) it.next();
        try {
          tm.close();
        }
        catch (IOException ex) {
          logger.error(ex);
          if (logger.isDebugEnabled()) {
            ex.printStackTrace();
          }
        }
      }
      notificationListeners.clear();
    }

    public synchronized void processPdu(CommandResponderEvent event) {
      CommandResponder listener = (CommandResponder)
           notificationTransports.get(event.getTransportMapping());
       if (listener != null) {
         listener.processPdu(event);
       }
    }
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -