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.apache.commons.logging.Log;
023 import org.apache.commons.logging.LogFactory;
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 Log LOG = LogFactory.getLog(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() * 1000);
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 " + endpoint.getAddress() + " using " + endpoint.getProtocol() + " protocol");
094 }
095 this.transport.listen();
096 LOG.info("Started OID poller on " + endpoint.getAddress() + " using " + endpoint.getProtocol() + " protocol");
097 }
098
099 @Override
100 protected void doStop() throws Exception {
101 // stop listening to the transport
102 if (this.transport != null && this.transport.isListening()) {
103 if (LOG.isDebugEnabled()) {
104 LOG.info("Stopping OID poller on " + targetAddress);
105 }
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 }