5 Nov 2009 11:32
Re: random problem sending command over TCP
Hi Frank,
No, it seems we are not using
TransportStateListener.connectionStateChanged (I could not find any
reference to TransportStateListener in the whole code).
We use SNMP4J in a straight forward way: configure and init an SNMP object
for the whole application life, use it to send commands.
Please find enclosed the source for the class we use (to send a command we
call the "sendCommand" method, that's where the application hangs (but
only a few times, it works ok 99% of the time)
(I still have to check with version 1.10.2, hope to be able to do it soon)
Thanks
import java.io.IOException;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.event.CounterListener;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.CounterSupport;
import org.snmp4j.mp.DefaultCounterListener;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthMD5;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.PrivDES;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import aaa.bbbbbb.xxxxx.business.channel.ControlChannel;
import aaa.bbbbbb.xxxxx.business.dialog.ComandosResolver;
import aaa.bbbbbb.xxxxx.commands.Comando;
import aaa.bbbbbb.xxxxx.exceptions.AccesoDenegadoException;
import aaa.bbbbbb.xxxxx.exceptions.ClientUnreachableException;
import aaa.bbbbbb.xxxxx.exceptions.CommandNotFoundException;
import aaa.bbbbbb.xxxxx.exceptions.InternalErrorException;
import aaa.bbbbbb.xxxxx.exceptions.RespuestaErrorGenerico;
import aaa.bbbbbb.xxxxx.exceptions.RespuestaInvalidaException;
import aaa.bbbbbb.xxxxx.exceptions.SintaxisIncorrectaException;
import aaa.bbbbbb.xxxxx.model.Client;
import aaa.bbbbbb.xxxxx.util.log4j.SourcesLogger;
public class SnmpChannel implements ControlChannel {
private SourcesLogger logger = new SourcesLogger(getClass());
private String commandPort = "/161";
public void setCommandPort(String commandPort) {
this.commandPort = commandPort;
}
private int timeout = 10 * 1000;
public void setTimeout(int timeout) {
this.timeout = timeout * 1000;
}
private int retries = 3;
public void setRetries(int retries) {
this.retries = retries;
}
private String community = "ppp";
public void setCommunity(String community) {
this.community = community;
}
private boolean soportaVersion3 = false;
public void setV3(boolean soportaVersion3) {
this.soportaVersion3 = soportaVersion3;
}
private String securityName = "";
public void setSecurityName(String securityName) {
this.securityName = securityName;
}
private String authProtocol = "";
public void setAuthProtocol(String authProtocol) {
this.authProtocol = authProtocol;
}
private String authPassphrase = "";
public void setAuthPassphrase(String authPassphrase) {
this.authPassphrase = authPassphrase;
}
private String privProtocol = "";
public void setPrivProtocol(String privProtocol) {
this.privProtocol = privProtocol;
}
private String privPassphrase = "";
public void setPrivPassphrase(String privPassphrase) {
this.privPassphrase = privPassphrase;
}
private Control2SNMP snmpConversionService;
public void setControl2SNMP(Control2SNMP snmpConversionService) {
this.snmpConversionService = snmpConversionService;
}
private ComandosResolver theComandosResolver;
public void setComandosResolver(ComandosResolver
comandosResolver){
theComandosResolver = comandosResolver;
}
private Snmp snmp;
private final CounterListener counterListener = new
DefaultCounterListener();
private TransportMapping transportMapping;
public boolean startup() {
try {
logger.getLogger().warn(
logger.fromServer("Starting
SNMP"));
CounterSupport.getInstance().addCounterListener(counterListener);
snmp = createSnmpSession();
snmp.listen();
logger
.getLogger()
.warn(
logger
.fromServer("SNMP started"));
return true;
} catch (Exception exception) {
logger.getLogger().error(logger.fromServer(exception.toString()));
exception.printStackTrace();
return false;
}
}
public void shutdown() {
try {
logger.getLogger().warn(
logger.fromServer("closing
SNMP"));
CounterSupport.getInstance().removeCounterListener(counterListener);
snmp.close();
} catch (Exception exception) {
logger.getLogger().warn(logger.fromServer(exception.toString()));
exception.printStackTrace();
}
}
public Comando sendCommand(Client client, Comando comando)
throws ClientUnreachableException,
AccesoDenegadoException,
SintaxisIncorrectaException,
RespuestaInvalidaException, CommandNotFoundException,
RespuestaErrorGenerico, InternalErrorException
{
final ResponseEvent responseEvent ;
try {
final PDU pdu = comando2PDU(comando);
if(pdu == null){
throw new InternalErrorException("PDU not
found");
}
final String ip = client.getIp();
final Target target = createTarget(ip);
responseEvent = snmp.send(pdu, target);
} catch (Exception e) {
throw new InternalErrorException("Exception with
command: " + e + " " + e.getMessage());
}
if (responseEvent == null) {
throw new ClientUnreachableException("Answer
null");
}
if (responseEvent.getResponse() == null) {
throw new ClientUnreachableException("Answer
null");
}
final PDU pduResponse = responseEvent.getResponse();
if(pduResponse.getType() != PDU.REPORT
&& pduResponse.getType() != PDU.RESPONSE){
throw new RespuestaInvalidaException("Unknown
answer: pduResponse.getType()= " +
pduResponse.getType());
}
if (pduResponse.getType() == PDU.REPORT) {
throw new AccesoDenegadoException("SNMP REPORT: "
+ pduResponse.toString());
}
if (pduResponse.getErrorStatus() != PDU.noError) {
if (pduResponse.getErrorStatus() ==
PDU.authorizationError) {
throw new AccesoDenegadoException("SNMP
answer: autorizationError status");
}
if(pduResponse.getErrorStatus() == PDU.badValue){
throw new
SintaxisIncorrectaException("SNMP answer: badValue status");
}
if(pduResponse.getErrorStatus() == PDU.noSuchName
|| pduResponse.getErrorStatus() ==
PDU.readOnly){
throw new CommandNotFoundException("SNMP
answer: noSuchName/readOnly status");
}
boolean posibleMsgError =
pduResponse.getErrorStatus() == PDU.genErr && !comando.isGet()? true :
false;
throw new RespuestaErrorGenerico(posibleMsgError,
"SNMP answer: " +
pduResponse.getErrorStatusText());
}
if (pduResponse.getVariableBindings().size() == 0) {
throw new RespuestaInvalidaException("SNMP answer
with no varBind");
}
try{
final VariableBinding variableBinding =
pduResponse.get(0);
String res =
snmpConversionService.getStringValue(variableBinding);
comando.setResultado(res);
return comando;
}catch(Exception e){
throw new RespuestaInvalidaException("Exception
parsing answer: "+ e + " " +e.getMessage());
}
}
private Snmp createSnmpSession() throws IOException {
logger.getLogger().debug(logger.fromServer("Creating SNMP
session"));
transportMapping = new DefaultTcpTransportMapping();
final Snmp snmp = new Snmp(transportMapping);
if (soportaVersion3) {
final USM usm = new
USM(SecurityProtocols.getInstance(),
new
OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
addUsmUser(snmp);
logger.getLogger().debug(
logger.fromServer("SNMP session
created"));
}
return snmp;
}
private void addUsmUser(Snmp snmp) {
logger.getLogger().debug(
logger.fromServer("Creating SNMP user " +
securityName
+ ", Protocolo " +
authProtocol));
snmp.getUSM().addUser(
new OctetString(securityName),
new UsmUser(new OctetString(securityName),
authProtocol
.equals("MD5") ?
AuthMD5.ID : AuthSHA.ID,
authPassphrase.length() !=
0 ? new OctetString(
authPassphrase) : null,
privProtocol.length() != 0
? PrivDES.ID : null,
privPassphrase.length() !=
0 ? new OctetString(
privPassphrase) : null));
}
private Target createTarget(String ip) {
Target target = null;
if (soportaVersion3) {
target = createSecuredUserTarget(ip);
} else {
target = createCommunityTarget(ip);
}
target.setTimeout(timeout);
target.setRetries(retries);
return target;
}
private Target createSecuredUserTarget(String ip) {
final UserTarget userTarget = new UserTarget();
if (authPassphrase != null && authPassphrase.length() !=
0) {
if (privPassphrase != null &&
privPassphrase.length() != 0) {
userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV);
} else {
userTarget.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
}
} else {
userTarget.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
}
userTarget.setSecurityName(new OctetString(securityName));
userTarget.setVersion(SnmpConstants.version3);
userTarget.setAddress(new TcpAddress(ip + commandPort));
return userTarget;
}
private Target createCommunityTarget(String ip) {
final CommunityTarget communityTarget = new
CommunityTarget();
communityTarget.setCommunity(new OctetString(community));
communityTarget.setAddress(new TcpAddress(ip +
commandPort));
return communityTarget;
}
private PDU comando2PDU(Comando cmd) {
final PDU pdu = soportaVersion3 ? new ScopedPDU() : new
PDU();
pdu.setType(cmd.isGet() ? PDU.GET : PDU.SET);
final String mibId =
theComandosResolver.getMibIdFromDBCodigo(cmd.getCodigoComando());
if(mibId == null){
return null;
}
final OID oid = snmpConversionService.findOID(mibId);
if(oid == null){
return null;
}
final VariableBinding variableBinding = new
VariableBinding(oid);
if (cmd.isGet() == false) {
variableBinding.setVariable(snmpConversionService
.createSNMPVariable(cmd.getParam()));
}
pdu.add(variableBinding);
return pdu;
}
}
RSS Feed