/projects/jre-1.6.0/src/com/sun/jmx/snmp/daemon/SnmpSocket.java
Java | 329 lines | 182 code | 53 blank | 94 comment | 32 complexity | eef47bd17fd0e33bb178d9a73138c63e MD5 | raw file
- /*
- * %Z%file %M%
- * %Z%author Sun Microsystems, Inc.
- * %Z%version %I%
- * %Z%date %D%
- *
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- */
- package com.sun.jmx.snmp.daemon;
- // JAVA imports
- //
- import java.net.InetAddress;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.SocketException;
- import java.io.IOException;
- // SNMP Runtime imports
- //
- import com.sun.jmx.trace.Trace;
- /**
- * This class creates an SNMP Datagram Socket. This class has methods helpful
- * to send SNMP inform request packets to an arbitrary port of a specified device.
- * It also runs a thread that is devoted to receiving SNMP inform response on the socket.
- * <BR>
- * A socket imposes an upper limit on size of inform response packet. Any
- * packet which exceeds this limit is truncated. By default, this
- * limit is {@link SnmpAdaptorServer#bufferSize}.
- */
- final class SnmpSocket implements java.lang.Runnable {
-
- // VARIABLES
- //----------
-
- private DatagramSocket _socket = null;
- private SnmpResponseHandler _dgramHdlr = null;
- private Thread _sockThread = null;
- private byte[] _buffer = null;
- private transient boolean isClosing = false;
- int _socketPort = 0;
- int responseBufSize = 1024;
- String dbgTag = "SnmpSocket";
-
- // CONSTRUCTORS
- //-------------
-
- /**
- * Creates a new <CODE>SnmpSocket</CODE> object.
- * @param rspHdlr A Datagram handler.
- * @param bufferSize The SNMP adaptor buffer size.
- * @exception SocketException A socket could not be created.
- */
- public SnmpSocket(SnmpResponseHandler rspHdlr, InetAddress addr, int bufferSize) throws SocketException {
- super();
-
- if (isTraceOn()) {
- trace("constructor", "Creating new SNMP datagram socket");
- }
-
- // TIME BOMB HERE
- _socket = new DatagramSocket(0, addr);
- _socketPort = _socket.getLocalPort();
- responseBufSize = bufferSize;
- _buffer = new byte[responseBufSize];
- _dgramHdlr = rspHdlr;
- _sockThread = new Thread(this, "SnmpSocket");
- _sockThread.start();
- }
- // PUBLIC METHODS
- //---------------
-
- /**
- * Sends a datagram packet to a specified device at specified port.
- * @param buff The packet data.
- * @param length The packet length.
- * @param addr The destination address.
- * @param port The destination port number.
- * @exception IOException Signals that an I/O exception of some sort has occurred.
- */
- public synchronized void sendPacket(byte[] buff, int length, InetAddress addr, int port) throws IOException {
- DatagramPacket dgrmpkt;
- dgrmpkt = new DatagramPacket(buff, length, addr, port);
- sendPacket(dgrmpkt);
- }
-
- /**
- * Sends a datagram packet to a specified device at specified port.
- * @param dgrmpkt The datagram packet.
- * @exception IOException Signals that an I/O exception of some sort has occurred.
- */
- public synchronized void sendPacket(DatagramPacket dgrmpkt) throws IOException {
-
- try {
- if (isValid()) {
- if (isTraceOn()) {
- trace("sendPacket", "Sending DatagramPacket. Length = " + dgrmpkt.getLength() +
- " through socket = " + _socket.toString());
- }
- _socket.send(dgrmpkt);
- } else
- throw new IOException("Invalid state of SNMP datagram socket.");
- } catch (IOException e) {
- if (isDebugOn()) {
- debug("sendPacket", "Io error while sending");
- debug("sendPacket", e.getMessage());
- }
- throw e;
- }
- }
- /**
- * Checks if the socket is initialised correctly and if it is still active.
- * @return <CODE>true</CODE> if the socket is initialised correctly and if it is still active,
- * <CODE>false</CODE> otherwise.
- */
- public synchronized boolean isValid() {
- return _socket != null && _sockThread != null && _sockThread.isAlive();
- }
-
- /**
- * Closes the socket and its associated resources.
- */
- public synchronized void close() {
-
- isClosing = true;
- if (isTraceOn()) {
- trace("close", "Closing and destroying the SNMP datagram socket -> " + toString());
- }
-
- try {
- // We send an empty datagram packet to fix bug 4293791 (it's a jdk 1.1 bug)
- //
- DatagramSocket sn = new java.net.DatagramSocket(0);
- byte[] ob = new byte[1];
- DatagramPacket pk = new DatagramPacket(ob , 1, java.net.InetAddress.getLocalHost(), _socketPort);
- sn.send(pk);
- sn.close();
- } catch (Exception e) {}
-
- // First close the datagram socket.
- // This may generates an IO exception at the run method (_socket.receive).
- //
- if (_socket != null) {
- _socket.close() ;
- _socket = null ;
- }
-
- // Then stop the thread socket.
- //
- if (_sockThread != null && _sockThread.isAlive()) {
- _sockThread.interrupt();
- try {
- // Wait until the thread die.
- //
- _sockThread.join();
- } catch (InterruptedException e) {
- // Ignore...
- }
- _sockThread = null ;
- }
- }
- /**
- * Dispatcher method for this socket thread. This is the dispatcher method
- * which goes in an endless-loop and waits for receiving datagram packets on the socket.
- */
- public void run() {
- Thread.currentThread().setPriority(8);
- while (true) {
- try {
- DatagramPacket dgrmpkt = new DatagramPacket (_buffer, _buffer.length);
- if (isTraceOn()) {
- trace("run", "[" + Thread.currentThread().toString() + "]:" + "Blocking for receiving packet");
- }
- _socket.receive(dgrmpkt);
-
- // If the corresponding session is being destroyed, stop handling received responses.
- //
- if (isClosing)
- break;
- if (isTraceOn()) {
- trace("run", "[" + Thread.currentThread().toString() + "]:" + "Received a packet");
- }
- if (dgrmpkt.getLength() <= 0)
- continue;
- if (isTraceOn()) {
- trace("run", "[" + Thread.currentThread().toString() + "]:" + "Received a packet from : " +
- dgrmpkt.getAddress().toString() + ", Length = " + dgrmpkt.getLength());
- }
- handleDatagram(dgrmpkt);
-
- // We are closing the snmp socket while handling the datagram.
- //
- if (isClosing)
- break;
-
- } catch (IOException io) {
- // If the IO exception has been generated because of closing this SNMP socket,
- // (call to _socket.close while _socket is blocked for receiving packet) simply terminate closing properly.
- //
- if (isClosing) {
- break;
- }
- if (isDebugOn()) {
- debug("run", io.getMessage());
- debug("run", io);
- }
- } catch (Exception e) {
- // If the exception (NullPointerException) has been generated because of closing this SNMP socket,
- // (call to _socket = null while _socket is blocked for receiving packet) simply terminate closing properly.
- //
- if (isClosing) {
- break;
- }
- if (isDebugOn()) {
- debug("run", "Exception in socket thread...");
- debug("run", e);
- }
- } catch (ThreadDeath d) {
- if (isDebugOn()) {
- debug("run", "Socket Thread DEAD..." + toString());
- debug("run", d);
- }
- close();
- throw d; // rethrow dead thread.
- } catch (Error err) {
- if (isDebugOn()) {
- debug("run", err);
- }
- handleJavaError(err);
- }
- }
- }
-
- /**
- * Finalizer of the <CODE>SnmpSocket</CODE> objects.
- * This method is called by the garbage collector on an object
- * when garbage collection determines that there are no more references to the object.
- * <P>Closes the datagram socket and stops the socket thread associated to this SNMP socket.
- */
- public synchronized void finalize() {
- close();
- }
-
- // PRIVATE METHODS
- //----------------
-
- /*
- * Keep this locked so that send can't happen.
- */
- private synchronized void handleJavaError(Throwable thr) {
- if (thr instanceof OutOfMemoryError) {
- if (isDebugOn()) {
- debug("handleJavaError", thr);
- }
- Thread.currentThread().yield();
- return ;
- }
- if (_socket != null) {
- _socket.close();
- _socket = null;
- }
- if (isDebugOn()) {
- debug("handleJavaError", "Global Internal error");
- }
- Thread.currentThread().yield();
- }
- private synchronized void handleDatagram(DatagramPacket dgrmpkt) {
- _dgramHdlr.processDatagram(dgrmpkt);
- }
- // TRACES & DEBUG
- //---------------
-
- boolean isTraceOn() {
- return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
- }
- void trace(String clz, String func, String info) {
- Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
- }
- void trace(String func, String info) {
- trace(dbgTag, func, info);
- }
-
- boolean isDebugOn() {
- return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
- }
- void debug(String clz, String func, String info) {
- Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
- }
- void debug(String clz, String func, Throwable exception) {
- Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, exception);
- }
- void debug(String func, String info) {
- debug(dbgTag, func, info);
- }
-
- void debug(String func, Throwable exception) {
- debug(dbgTag, func, exception);
- }
- }