001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.snmp;
018    
019    import org.apache.camel.Exchange;
020    import org.apache.camel.Processor;
021    import org.apache.camel.impl.ScheduledPollConsumer;
022    import org.slf4j.Logger;
023    import org.slf4j.LoggerFactory;
024    import org.snmp4j.CommunityTarget;
025    import org.snmp4j.PDU;
026    import org.snmp4j.Snmp;
027    import org.snmp4j.TransportMapping;
028    import org.snmp4j.event.ResponseEvent;
029    import org.snmp4j.event.ResponseListener;
030    import org.snmp4j.mp.MPv3;
031    import org.snmp4j.security.SecurityModels;
032    import org.snmp4j.security.SecurityProtocols;
033    import org.snmp4j.security.USM;
034    import org.snmp4j.smi.Address;
035    import org.snmp4j.smi.GenericAddress;
036    import org.snmp4j.smi.OID;
037    import org.snmp4j.smi.OctetString;
038    import org.snmp4j.smi.VariableBinding;
039    import org.snmp4j.transport.DefaultTcpTransportMapping;
040    import org.snmp4j.transport.DefaultUdpTransportMapping;
041    
042    public class SnmpOIDPoller extends ScheduledPollConsumer implements ResponseListener {
043    
044        private static final transient Logger LOG = LoggerFactory.getLogger(SnmpOIDPoller.class);
045    
046        private Address targetAddress;
047        private TransportMapping transport;
048        private Snmp snmp;
049        private USM usm;
050        private CommunityTarget target;
051        private PDU pdu;
052        private SnmpEndpoint endpoint;
053    
054        public SnmpOIDPoller(SnmpEndpoint endpoint, Processor processor) {
055            super(endpoint, processor);
056            this.endpoint = endpoint;
057            // convert delay from seconds to millis
058            setDelay(endpoint.getDelay() * 1000L);
059        }
060    
061        @Override
062        protected void doStart() throws Exception {
063            super.doStart();
064    
065            this.targetAddress = GenericAddress.parse(this.endpoint.getAddress());
066    
067            // either tcp or udp
068            if ("tcp".equals(endpoint.getProtocol())) {
069                this.transport = new DefaultTcpTransportMapping();
070            } else if ("udp".equals(endpoint.getProtocol())) {
071                this.transport = new DefaultUdpTransportMapping();
072            } else {
073                throw new IllegalArgumentException("Unknown protocol: " + endpoint.getProtocol());
074            }
075    
076            this.snmp = new Snmp(this.transport);
077            this.usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
078            SecurityModels.getInstance().addSecurityModel(usm);
079    
080            // setting up target
081            target = new CommunityTarget();
082            target.setCommunity(new OctetString(this.endpoint.getSnmpCommunity()));
083            target.setAddress(targetAddress);
084            target.setRetries(this.endpoint.getRetries());
085            target.setTimeout(this.endpoint.getTimeout());
086            target.setVersion(this.endpoint.getSnmpVersion());
087    
088            // creating PDU
089            this.pdu = new PDU();
090    
091            // listen to the transport
092            if (LOG.isDebugEnabled()) {
093                LOG.debug("Starting OID poller on {} using {} protocol", endpoint.getAddress(), endpoint.getProtocol());
094            }
095            this.transport.listen();
096            if (LOG.isInfoEnabled()) {
097                LOG.info("Started OID poller on {} using {} protocol", endpoint.getAddress(), endpoint.getProtocol());
098            }
099        }
100    
101        @Override
102        protected void doStop() throws Exception {
103            // stop listening to the transport
104            if (this.transport != null && this.transport.isListening()) {
105                LOG.info("Stopping OID poller on {}", targetAddress);
106                this.transport.close();
107                LOG.info("Stopped OID poller on {}", targetAddress);
108            }
109    
110            super.doStop();
111        }
112    
113        @Override
114        protected int poll() throws Exception {
115            this.pdu.clear();
116            this.pdu.setType(PDU.GET);
117    
118            // prepare the request items
119            for (OID oid : this.endpoint.getOids()) {
120                this.pdu.add(new VariableBinding(oid));
121            }
122    
123            // send the request
124            snmp.send(pdu, target, null, this);
125    
126            return 1;
127        }
128    
129        public void onResponse(ResponseEvent event) {
130            // Always cancel async request when response has been received
131            // otherwise a memory leak is created! Not canceling a request
132            // immediately can be useful when sending a request to a broadcast address.
133            ((Snmp)event.getSource()).cancel(event.getRequest(), this);
134    
135            // check for valid response
136            if (event.getRequest() == null || event.getResponse() == null) {
137                // ignore null requests/responses
138                LOG.debug("Received invalid SNMP event. Request: " + event.getRequest() + " / Response: " + event.getResponse());
139                return;
140            }
141            
142            PDU pdu = event.getResponse();
143            processPDU(pdu);
144        }
145    
146        /**
147         * processes the pdu message
148         * 
149         * @param pdu the pdu
150         */
151        public void processPDU(PDU pdu) {
152            if (LOG.isDebugEnabled()) {
153                LOG.debug("Received response event for {} : {}", this.endpoint.getAddress(), pdu);
154            }
155            Exchange exchange = endpoint.createExchange(pdu);
156            try {
157                getProcessor().process(exchange);
158            } catch (Exception e) {
159                getExceptionHandler().handleException(e);
160            }
161        }
162    
163        /** * @return Returns the target.
164         */
165        public CommunityTarget getTarget() {
166            return this.target;
167        }
168    
169        /**
170         * @param target The target to set.
171         */
172        public void setTarget(CommunityTarget target) {
173            this.target = target;
174        }
175    }