📄 abstractsnmpcontext.java
字号:
// NAME// $RCSfile: AbstractSnmpContext.java,v $// DESCRIPTION// [given below in javadoc format]// DELTA// $Revision: 3.30 $// CREATED// $Date: 2006/06/19 10:45:09 $// COPYRIGHT// Westhawk Ltd// TO DO///* * Copyright (C) 2000 - 2006 by Westhawk Ltd * <a href="www.westhawk.co.uk">www.westhawk.co.uk</a> * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted, provided * that the above copyright notices appear in all copies and that * both the copyright notice and this permission notice appear in * supporting documentation. * This software is provided "as is" without express or implied * warranty. * author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a> */package uk.co.westhawk.snmp.stack;import java.io.*;import java.util.*;import uk.co.westhawk.snmp.net.*;import uk.co.westhawk.snmp.event.*;import uk.co.westhawk.snmp.util.*;/** * This class contains the abstract SNMP context that is needed by every * Pdu to send a SNMP v1, v2c or v3 request. * The context also provides functionality to receive PDUs. * * <p> * <code>destroy()</code> should be called when the context is no longer * used. This is the only way the threads will be stopped and garbage * collected. * </p> * * @see SnmpContext * @see SnmpContextv2c * @see SnmpContextv3 * * @author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a> * @version $Revision: 3.30 $ $Date: 2006/06/19 10:45:09 $ */public abstract class AbstractSnmpContext extends Object implements SnmpContextBasisFace, Runnable, RawPduListener{ private static final String version_id = "@(#)$Id: AbstractSnmpContext.java,v 3.30 2006/06/19 10:45:09 birgit Exp $ Copyright Westhawk Ltd"; private ContextSocketFace soc; private Transmitter [] transmitters; private Pdu [] pdus; private Thread me; private String basename; private boolean stopRequested; protected String typeSocket; protected String hostname; protected String bindAddr; protected int hostPort; protected int maxRecvSize; protected boolean isDestroyed; protected boolean anyPduExpectingResponse = false; protected RequestPduReceivedSupport pduSupport; protected TrapReceivedSupport trapSupport;/** * Processes an incoming response. Has to be overload by each context. * This is called in the run() method. * * @see #run */protected abstract void processIncomingResponse(ByteArrayInputStream in) throws DecodingException, IOException;/** * Encodes a PDU. This is for internal use only and should * NOT be called by the developer. * This is called by the the PDU itself and is added to the interface to * cover the different kind of Contexts. * Has to be overload by each context. * * @param msg_type The message type * @param rId The message id * @param errstat The error status * @param errind The error index * @param ve The varbind list * @param obj Additional object (only used in SNMPv3) * @return The encoded packet */public abstract byte[] encodePacket(byte msg_type, int rId, int errstat, int errind, Enumeration ve, Object obj) throws java.io.IOException, EncodingException;/** * Processes an incoming pdu (but not a response). Has to be overload by each context. * @see #rawPduReceived */public abstract Pdu processIncomingPdu(byte [] message) throws DecodingException, IOException;/** * Returns the SNMP version of this context. Has to be overload by each * context. */public abstract int getVersion();/** * Constructor. * The Standard socket type will be used. * * @param host The host to which the Pdu will be sent * @param port The port where the SNMP server will be * @see SnmpContextBasisFace#STANDARD_SOCKET */protected AbstractSnmpContext(String host, int port) throws java.io.IOException{ this(host, port, null, STANDARD_SOCKET);}/** * Constructor. * The Standard socket type will be used. * * @param host The host to which the Pdu will be sent * @param port The port where the SNMP server will be * @param typeSocketA The local address the server will bind to * * @see SnmpContextBasisFace#STANDARD_SOCKET */protected AbstractSnmpContext(String host, int port, String typeSocketA) throws java.io.IOException{ this(host, port, null, typeSocketA);}/** * Constructor. * * If bindAddress is null, then the system will pick up a valid local * address to bind the socket. * * The typeSocket will indicate which type of socket to use. This way * different handlers can be provided for Netscape or Standard JVM. * The Netscape implementation will make the necessary security calls * to access hosts that are not the applet's webserver. The KVM * version will be for small device support (e.g. Palm Pilot). * * @param host The host to which the Pdu will be sent * @param port The port where the SNMP server will be * @param bindAddress The local address the server will bind to * @param typeSocketA The type of socket to use. * * @exception java.io.IOException Thrown when the socket cannot be * created. * * @see SnmpContextBasisFace#STANDARD_SOCKET * @see SnmpContextBasisFace#TCP_SOCKET * @see SnmpContextBasisFace#NETSCAPE_SOCKET * @see SnmpContextBasisFace#KVM_SOCKET * @since 4_14 */protected AbstractSnmpContext(String host, int port, String bindAddress, String typeSocketA)throws java.io.IOException{ pdus = new Pdu[MAXPDU]; hostname = host; hostPort = port; bindAddr = bindAddress; typeSocket = typeSocketA; transmitters = new Transmitter[MAXPDU]; basename = host+"_"+ port+"_"+bindAddress; trapSupport = new TrapReceivedSupport(this); pduSupport = new RequestPduReceivedSupport(this); isDestroyed = false; stopRequested = false; maxRecvSize = MSS; soc = getSocket(typeSocketA); soc.create(host, port, bindAddr); if (AsnObject.debug > 12) { System.out.println(getClass().getName() + ": soc.getLocalSocketAddress() = " + soc.getLocalSocketAddress()); System.out.println(getClass().getName() + ": soc.getRemoteSocketAddress() = " + soc.getRemoteSocketAddress()); }}static ContextSocketFace getSocket(String type) throws IOException{ ContextSocketFace sf = null; String className = "uk.co.westhawk.snmp.net.StandardSocket"; if (type.equals(TCP_SOCKET)) { className = "uk.co.westhawk.snmp.net.TCPSocket"; } else if (type.equals(NETSCAPE_SOCKET)) { className = "uk.co.westhawk.snmp.net.NetscapeSocket"; } else if (type.equals(KVM_SOCKET)) { className = "uk.co.westhawk.snmp.net.KvmSocket"; } try { Class cl = Class.forName(className); Object obj = cl.newInstance(); sf = (ContextSocketFace) obj; } catch (ClassNotFoundException exc) { String str = "ClassNotFound problem " + exc.getMessage(); throw (new IOException(str)); } catch (InstantiationException exc) { String str = "Instantiation problem " + exc.getMessage(); throw (new IOException(str)); } catch (IllegalAccessException exc) { String str = "IllegalAccess problem " + exc.getMessage(); throw (new IOException(str)); } catch (ClassCastException exc) { String str = "ClassCast problem " + exc.getMessage(); throw (new IOException(str)); } if (sf == null) { String str = "Cannot create socket "; throw (new IOException(str)); } else { if (AsnObject.debug > 12) { System.out.println("AbstractSnmpContext.getSocket(): New socket " + sf.getClass().getName()); } } return sf;}public String getHost(){ return hostname;}/** * Returns the IP address string * aaa.bbb.ccc.ddd (IPv4) or a:b:c:d:e:f:g:h (IPv6) * of the host. * * @return The IP address of the host * @deprecated As of 4_14, use {@link #getSendToHostAddress()} */public String getHostAddress(){ return getSendToHostAddress();}public String getSendToHostAddress(){ String res = soc.getSendToHostAddress(); return res;}public String getReceivedFromHostAddress(){ String res = soc.getReceivedFromHostAddress(); return res;}public int getPort(){ return hostPort;}public String getBindAddress(){ return bindAddr;}public String getTypeSocket(){ return typeSocket;}/** * Returns the maximum number of bytes this context will read from the * socket. By default this will be set to <code>MSS</code> (i.e. 1300). * * @since 4_12 * @see SnmpContextBasisFace#MSS * @see #setMaxRecvSize(int) * @return The number */public int getMaxRecvSize(){ return maxRecvSize;}/** * Sets the maximum number of bytes this context will read from the * socket. By default this will be set to <code>MSS</code> (i.e. 1300). * The default size seems a reasonable size. The problem usually occurs * when sending Bulk requests. * * <p> * If a packet arrives that is bigger than the maximum size of received * bytes, the stack will try to decode it nevertheless. The usual * error that will occur is: * <pre> * Error message: "Incorrect packet. No of bytes received less than packet length." * </pre> * </p> * * <p> * Although UDP datagrams can be fragmented (fragmentation is part of * the network layer (IP), not the transport layer (UDP/TCP)), some * firewalls reject incoming fragments. Therefor it is best not to set * maxRecvSize higher than the largest packet size you can get through * your network topology. * </p> * * <p> * Thanks to Pete Kazmier (pete@kazmier.com) for the suggestion. * </p> * * <p><em> * <font color="red"> * Note, this property is NOT supported in any of the SNMPContextXXPool * classes. * </font> * </em></p> * * @since 4_12 * @see SnmpContextBasisFace#MSS * @see #getMaxRecvSize() * @param no The new number */public void setMaxRecvSize(int no){ maxRecvSize = no;}/** * Returns the thread usage of the AbstractSnmpContext. * It returns a String in the form of <code>=PO=QR--------------0</code>. * * <p> * The String represents the array of transmitters. * Each character represents a transmitter slot. * The transmitters form a thread pool of a maximum size, MAXPDU. * Each transmitter is used to wait for one PDU response at a given * moment in time. * When the response is received the transmitter will stop running, but * is not destroyed. It will be reused. * </p> * * <p> * Meaning of each character: * <ul> * <li><code>-</code> a transmitter slot has not yet been allocated a thread</li> * <li><code>=</code> there is a thread but it is idle</li> * <li><code>A->Z</code> the thread is transmitting a Pdu</li> * <li> * The last character represents the context's recv thread: * <ul> * <li><code>0</code> there isn't one</li> * <li><code>1</code> it exists but isn't running </li> * <li><code>2</code> it exists and is alive.</li> * </ul> * </li> * </ul> * </p> * * @since 4_12 * @return The thread usage of the AbstractSnmpContext */public String getDebugString(){ char [] cret = new char[MAXPDU+1]; for (int i=0;i<MAXPDU; i++) { if (transmitters[i] != null) { if (pdus[i] != null) { cret[i] = (char ) ('A' + (pdus[i].getReqId() % 26)); } else { cret[i] = '='; } } else { cret[i] = '-'; } } char res='0'; if (me != null) { res++; if (me.isAlive()) { res++; } } cret[MAXPDU] = res; return new String(cret);}/** * This method will stop the thread. * All transmitters, PDUs in flight and traplisteners will be removed * when run() finishes. * * <p> * It closes the socket. * The thread will actually stop/finish when the run() finishes. Since * the socket is closed, the run() will fall through almost instantly. * </p> * * <p> * Note: The thread(s) will not die immediately; this will take about * half a minute. * </p> * * @see ListeningContext#destroy() * @see ListeningContextPool#destroyPool() */public synchronized void destroy(){ if (isDestroyed == false) { stopRequested = true; if (AsnObject.debug > 12) { System.out.println(getClass().getName() + ".destroy(): Closing socket "); } soc.close(); isDestroyed = true; // If run() has been started, then it will destroy the // transmitter threads when it finishes. Otherwise they must be // destroyed here. if (me == null) { freeTransmitters(); } }}public boolean isDestroyed(){ return isDestroyed;}/** * This method will stop the thread. * All transmitters, PDUs in flight and traplisteners will be removed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -