icmpplugin.java

来自「opennms得相关源码 请大家看看」· Java 代码 · 共 331 行

JAVA
331
字号
//// This file is part of the OpenNMS(R) Application.//// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc.  All rights reserved.// OpenNMS(R) is a derivative work, containing both original code, included code and modified// code that was published under the GNU General Public License. Copyrights for modified // and included code are below.//// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.//// Copyright (C) 1999-2001 Oculan Corp.  All rights reserved.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.                                                            //// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//       // For more information contact: //      OpenNMS Licensing       <license@opennms.org>//      http://www.opennms.org///      http://www.opennms.com///// Tab Size = 8//package org.opennms.netmgt.capsd;import java.io.IOException;import java.net.DatagramPacket;import java.net.InetAddress;import java.util.Collections;import java.util.Map;import java.util.TreeMap;import org.apache.log4j.Category;import org.opennms.core.queue.FifoQueueImpl;import org.opennms.core.utils.ThreadCategory;import org.opennms.netmgt.ping.Packet;import org.opennms.netmgt.ping.Reply;import org.opennms.netmgt.ping.ReplyReceiver;import org.opennms.netmgt.utils.ParameterMap;import org.opennms.protocols.icmp.IcmpSocket;/** * This class provides Capsd with the ability to check for ICMP support on new * interfaces as them are passed into the system. In order to minimize the * number of sockets and threads, this class creates a daemon thread to handle * all responses and a single socket for sending echo request to various hosts. *  * @author <A HREF="mailto:weave@oculan.com">Weave </a> * @author <A HREF="http://www.opennms.org/">OpenNMS </A> *  */public final class IcmpPlugin extends AbstractPlugin {    /**     * The name of the protocol that is supported by this plugin     */    private static final String PROTOCOL_NAME = "ICMP";    /**     * Default retries.     */    private static final int DEFAULT_RETRY = 2;    /**     * Default timeout. Specifies how long (in milliseconds) to block waiting     * for data from the monitored interface.     */    private static final int DEFAULT_TIMEOUT = 800;    /**     * The filter identifier for the ping reply receiver     */    private static final short FILTER_ID = (short) (new java.util.Random(System.currentTimeMillis())).nextInt();    /**     * The sequence number for pings     */    private static short m_seqid = (short) 0xbeef;    /**     * The singular reply receiver     */    private static ReplyReceiver m_receiver = null; // delayed creation    /**     * The ICMP socket used to send/receive replies     */    private static IcmpSocket m_icmpSock = null; // delayed creation    /**     * The set used to lookup thread identifiers The map of long thread     * identifiers to Packets that must be signaled. The mapped objects are     * instances of the {@link org.opennms.netmgt.ping.Reply Reply}class.     */    private static Map m_waiting = Collections.synchronizedMap(new TreeMap());    /**     * The thread used to receive and process replies.     */    private static Thread m_worker = null;    /**     * This class is used to encapsulate a ping request. A request consist of     * the pingable address and a signaled state.     *      */    private static final class Ping {        /**         * The address being pinged         */        private final InetAddress m_addr;        /**         * The state of the ping         */        private boolean m_signaled;        /**         * Constructs a new ping object         */        Ping(InetAddress addr) {            m_addr = addr;        }        /**         * Returns true if signaled.         */        synchronized boolean isSignaled() {            return m_signaled;        }        /**         * Sets the signaled state and awakes the blocked threads.         */        synchronized void signal() {            m_signaled = true;            notifyAll();        }        /**         * Returns true if the passed address is the target of the ping.         */        boolean isTarget(InetAddress addr) {            return m_addr.equals(addr);        }    }    /**     * Construts a new monitor.     */    public IcmpPlugin() throws IOException {        synchronized (IcmpPlugin.class) {            if (m_worker == null) {                // Create a receiver queue                //                final FifoQueueImpl q = new FifoQueueImpl();                // Open a socket                //                m_icmpSock = new IcmpSocket();                // Start the receiver                //                m_receiver = new ReplyReceiver(m_icmpSock, q, FILTER_ID);                m_receiver.start();                // Start the processor                //                m_worker = new Thread(new Runnable() {                    public void run() {                        for (;;) {                            Reply pong = null;                            try {                                pong = (Reply) q.remove();                            } catch (InterruptedException ex) {                                break;                            } catch (Exception ex) {                                ThreadCategory.getInstance(this.getClass()).error("Error processing response queue", ex);                            }                            Long key = new Long(pong.getPacket().getTID());                            Ping ping = (Ping) m_waiting.get(key);                            if (ping != null && ping.isTarget(pong.getAddress()))                                ping.signal();                        }                    }                }, "IcmpPlugin-Receiver");                m_worker.setDaemon(true);                m_worker.start();            }        }    }    /**     * Builds a datagram compatable with the ping ReplyReceiver class.     */    private synchronized static DatagramPacket getDatagram(InetAddress addr, long tid) {        Packet iPkt = new Packet(tid);        iPkt.setIdentity(FILTER_ID);        iPkt.setSequenceId(m_seqid++);        iPkt.computeChecksum();        byte[] data = iPkt.toBytes();        return new DatagramPacket(data, data.length, addr, 0);    }    /**     * This method is used to ping a remote host to test for ICMP support. If     * the remote host responds within the specified period, defined by retries     * and timeouts, then a value of true is returned to the caller.     *      * @param ipv4Addr     *            The address to poll.     * @param retries     *            The number of times to retry     * @param timeout     *            The time to wait between each retry.     *      * @return True if the host is reachable and responsed with an echo reply.     *      */    private boolean isPingable(InetAddress ipv4Addr, int retries, long timeout) {        Category log = ThreadCategory.getInstance(this.getClass());        // Find an appropritate thread id        //        Long tidKey = null;        long tid = (long) Thread.currentThread().hashCode();        synchronized (m_waiting) {            while (m_waiting.containsKey(tidKey = new Long(tid)))                ++tid;        }        DatagramPacket pkt = getDatagram(ipv4Addr, tid);        Ping reply = new Ping(ipv4Addr);        m_waiting.put(tidKey, reply);        for (int attempts = 0; attempts <= retries && !reply.isSignaled(); ++attempts) {            // Send the datagram and wait            //            synchronized (reply) {                try {                    m_icmpSock.send(pkt);                } catch (IOException ioE) {                    log.info("isPingable: Failed to send to address " + ipv4Addr, ioE);                    break;                } catch (Throwable t) {                    log.info("isPingable: Undeclared throwable exception caught sending to " + ipv4Addr, t);                    break;                }                try {                    reply.wait(timeout);                } catch (InterruptedException ex) {                    // interrupted so return, reset interrupt.                    //                    Thread.currentThread().interrupt();                    break;                }            }        }        m_waiting.remove(tidKey);        boolean pingable = false;        if (reply.isSignaled())            pingable = true;        return pingable;    }    /**     * Returns the name of the protocol that this plugin checks on the target     * system for support.     *      * @return The protocol name for this plugin.     */    public String getProtocolName() {        return PROTOCOL_NAME;    }    /**     * Returns true if the protocol defined by this plugin is supported. If the     * protocol is not supported then a false value is returned to the caller.     *      * @param address     *            The address to check for support.     *      * @return True if the protocol is supported by the address.     */    public boolean isProtocolSupported(InetAddress address) {        return isPingable(address, DEFAULT_RETRY, DEFAULT_TIMEOUT);    }    /**     * Returns true if the protocol defined by this plugin is supported. If the     * protocol is not supported then a false value is returned to the caller.     * The qualifier map passed to the method is used by the plugin to return     * additional information by key-name. These key-value pairs can be added to     * service events if needed.     *      * @param address     *            The address to check for support.     * @param qualifiers     *            The map where qualification are set by the plugin.     *      * @return True if the protocol is supported by the address.     */    public boolean isProtocolSupported(InetAddress address, Map qualifiers) {        int retries = DEFAULT_RETRY;        int timeout = DEFAULT_TIMEOUT;        if (qualifiers != null) {            retries = ParameterMap.getKeyedInteger(qualifiers, "retry", DEFAULT_RETRY);            timeout = ParameterMap.getKeyedInteger(qualifiers, "timeout", DEFAULT_TIMEOUT);        }        return isPingable(address, retries, timeout);    }}

⌨️ 快捷键说明

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