PageRenderTime 2001ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jre-1.6.0/src/com/sun/jmx/snmp/daemon/SnmpSocket.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 329 lines | 182 code | 53 blank | 94 comment | 32 complexity | eef47bd17fd0e33bb178d9a73138c63e MD5 | raw file
  1. /*
  2. * %Z%file %M%
  3. * %Z%author Sun Microsystems, Inc.
  4. * %Z%version %I%
  5. * %Z%date %D%
  6. *
  7. * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
  8. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  9. *
  10. */
  11. package com.sun.jmx.snmp.daemon;
  12. // JAVA imports
  13. //
  14. import java.net.InetAddress;
  15. import java.net.DatagramPacket;
  16. import java.net.DatagramSocket;
  17. import java.net.SocketException;
  18. import java.io.IOException;
  19. // SNMP Runtime imports
  20. //
  21. import com.sun.jmx.trace.Trace;
  22. /**
  23. * This class creates an SNMP Datagram Socket. This class has methods helpful
  24. * to send SNMP inform request packets to an arbitrary port of a specified device.
  25. * It also runs a thread that is devoted to receiving SNMP inform response on the socket.
  26. * <BR>
  27. * A socket imposes an upper limit on size of inform response packet. Any
  28. * packet which exceeds this limit is truncated. By default, this
  29. * limit is {@link SnmpAdaptorServer#bufferSize}.
  30. */
  31. final class SnmpSocket implements java.lang.Runnable {
  32. // VARIABLES
  33. //----------
  34. private DatagramSocket _socket = null;
  35. private SnmpResponseHandler _dgramHdlr = null;
  36. private Thread _sockThread = null;
  37. private byte[] _buffer = null;
  38. private transient boolean isClosing = false;
  39. int _socketPort = 0;
  40. int responseBufSize = 1024;
  41. String dbgTag = "SnmpSocket";
  42. // CONSTRUCTORS
  43. //-------------
  44. /**
  45. * Creates a new <CODE>SnmpSocket</CODE> object.
  46. * @param rspHdlr A Datagram handler.
  47. * @param bufferSize The SNMP adaptor buffer size.
  48. * @exception SocketException A socket could not be created.
  49. */
  50. public SnmpSocket(SnmpResponseHandler rspHdlr, InetAddress addr, int bufferSize) throws SocketException {
  51. super();
  52. if (isTraceOn()) {
  53. trace("constructor", "Creating new SNMP datagram socket");
  54. }
  55. // TIME BOMB HERE
  56. _socket = new DatagramSocket(0, addr);
  57. _socketPort = _socket.getLocalPort();
  58. responseBufSize = bufferSize;
  59. _buffer = new byte[responseBufSize];
  60. _dgramHdlr = rspHdlr;
  61. _sockThread = new Thread(this, "SnmpSocket");
  62. _sockThread.start();
  63. }
  64. // PUBLIC METHODS
  65. //---------------
  66. /**
  67. * Sends a datagram packet to a specified device at specified port.
  68. * @param buff The packet data.
  69. * @param length The packet length.
  70. * @param addr The destination address.
  71. * @param port The destination port number.
  72. * @exception IOException Signals that an I/O exception of some sort has occurred.
  73. */
  74. public synchronized void sendPacket(byte[] buff, int length, InetAddress addr, int port) throws IOException {
  75. DatagramPacket dgrmpkt;
  76. dgrmpkt = new DatagramPacket(buff, length, addr, port);
  77. sendPacket(dgrmpkt);
  78. }
  79. /**
  80. * Sends a datagram packet to a specified device at specified port.
  81. * @param dgrmpkt The datagram packet.
  82. * @exception IOException Signals that an I/O exception of some sort has occurred.
  83. */
  84. public synchronized void sendPacket(DatagramPacket dgrmpkt) throws IOException {
  85. try {
  86. if (isValid()) {
  87. if (isTraceOn()) {
  88. trace("sendPacket", "Sending DatagramPacket. Length = " + dgrmpkt.getLength() +
  89. " through socket = " + _socket.toString());
  90. }
  91. _socket.send(dgrmpkt);
  92. } else
  93. throw new IOException("Invalid state of SNMP datagram socket.");
  94. } catch (IOException e) {
  95. if (isDebugOn()) {
  96. debug("sendPacket", "Io error while sending");
  97. debug("sendPacket", e.getMessage());
  98. }
  99. throw e;
  100. }
  101. }
  102. /**
  103. * Checks if the socket is initialised correctly and if it is still active.
  104. * @return <CODE>true</CODE> if the socket is initialised correctly and if it is still active,
  105. * <CODE>false</CODE> otherwise.
  106. */
  107. public synchronized boolean isValid() {
  108. return _socket != null && _sockThread != null && _sockThread.isAlive();
  109. }
  110. /**
  111. * Closes the socket and its associated resources.
  112. */
  113. public synchronized void close() {
  114. isClosing = true;
  115. if (isTraceOn()) {
  116. trace("close", "Closing and destroying the SNMP datagram socket -> " + toString());
  117. }
  118. try {
  119. // We send an empty datagram packet to fix bug 4293791 (it's a jdk 1.1 bug)
  120. //
  121. DatagramSocket sn = new java.net.DatagramSocket(0);
  122. byte[] ob = new byte[1];
  123. DatagramPacket pk = new DatagramPacket(ob , 1, java.net.InetAddress.getLocalHost(), _socketPort);
  124. sn.send(pk);
  125. sn.close();
  126. } catch (Exception e) {}
  127. // First close the datagram socket.
  128. // This may generates an IO exception at the run method (_socket.receive).
  129. //
  130. if (_socket != null) {
  131. _socket.close() ;
  132. _socket = null ;
  133. }
  134. // Then stop the thread socket.
  135. //
  136. if (_sockThread != null && _sockThread.isAlive()) {
  137. _sockThread.interrupt();
  138. try {
  139. // Wait until the thread die.
  140. //
  141. _sockThread.join();
  142. } catch (InterruptedException e) {
  143. // Ignore...
  144. }
  145. _sockThread = null ;
  146. }
  147. }
  148. /**
  149. * Dispatcher method for this socket thread. This is the dispatcher method
  150. * which goes in an endless-loop and waits for receiving datagram packets on the socket.
  151. */
  152. public void run() {
  153. Thread.currentThread().setPriority(8);
  154. while (true) {
  155. try {
  156. DatagramPacket dgrmpkt = new DatagramPacket (_buffer, _buffer.length);
  157. if (isTraceOn()) {
  158. trace("run", "[" + Thread.currentThread().toString() + "]:" + "Blocking for receiving packet");
  159. }
  160. _socket.receive(dgrmpkt);
  161. // If the corresponding session is being destroyed, stop handling received responses.
  162. //
  163. if (isClosing)
  164. break;
  165. if (isTraceOn()) {
  166. trace("run", "[" + Thread.currentThread().toString() + "]:" + "Received a packet");
  167. }
  168. if (dgrmpkt.getLength() <= 0)
  169. continue;
  170. if (isTraceOn()) {
  171. trace("run", "[" + Thread.currentThread().toString() + "]:" + "Received a packet from : " +
  172. dgrmpkt.getAddress().toString() + ", Length = " + dgrmpkt.getLength());
  173. }
  174. handleDatagram(dgrmpkt);
  175. // We are closing the snmp socket while handling the datagram.
  176. //
  177. if (isClosing)
  178. break;
  179. } catch (IOException io) {
  180. // If the IO exception has been generated because of closing this SNMP socket,
  181. // (call to _socket.close while _socket is blocked for receiving packet) simply terminate closing properly.
  182. //
  183. if (isClosing) {
  184. break;
  185. }
  186. if (isDebugOn()) {
  187. debug("run", io.getMessage());
  188. debug("run", io);
  189. }
  190. } catch (Exception e) {
  191. // If the exception (NullPointerException) has been generated because of closing this SNMP socket,
  192. // (call to _socket = null while _socket is blocked for receiving packet) simply terminate closing properly.
  193. //
  194. if (isClosing) {
  195. break;
  196. }
  197. if (isDebugOn()) {
  198. debug("run", "Exception in socket thread...");
  199. debug("run", e);
  200. }
  201. } catch (ThreadDeath d) {
  202. if (isDebugOn()) {
  203. debug("run", "Socket Thread DEAD..." + toString());
  204. debug("run", d);
  205. }
  206. close();
  207. throw d; // rethrow dead thread.
  208. } catch (Error err) {
  209. if (isDebugOn()) {
  210. debug("run", err);
  211. }
  212. handleJavaError(err);
  213. }
  214. }
  215. }
  216. /**
  217. * Finalizer of the <CODE>SnmpSocket</CODE> objects.
  218. * This method is called by the garbage collector on an object
  219. * when garbage collection determines that there are no more references to the object.
  220. * <P>Closes the datagram socket and stops the socket thread associated to this SNMP socket.
  221. */
  222. public synchronized void finalize() {
  223. close();
  224. }
  225. // PRIVATE METHODS
  226. //----------------
  227. /*
  228. * Keep this locked so that send can't happen.
  229. */
  230. private synchronized void handleJavaError(Throwable thr) {
  231. if (thr instanceof OutOfMemoryError) {
  232. if (isDebugOn()) {
  233. debug("handleJavaError", thr);
  234. }
  235. Thread.currentThread().yield();
  236. return ;
  237. }
  238. if (_socket != null) {
  239. _socket.close();
  240. _socket = null;
  241. }
  242. if (isDebugOn()) {
  243. debug("handleJavaError", "Global Internal error");
  244. }
  245. Thread.currentThread().yield();
  246. }
  247. private synchronized void handleDatagram(DatagramPacket dgrmpkt) {
  248. _dgramHdlr.processDatagram(dgrmpkt);
  249. }
  250. // TRACES & DEBUG
  251. //---------------
  252. boolean isTraceOn() {
  253. return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
  254. }
  255. void trace(String clz, String func, String info) {
  256. Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
  257. }
  258. void trace(String func, String info) {
  259. trace(dbgTag, func, info);
  260. }
  261. boolean isDebugOn() {
  262. return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
  263. }
  264. void debug(String clz, String func, String info) {
  265. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
  266. }
  267. void debug(String clz, String func, Throwable exception) {
  268. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, exception);
  269. }
  270. void debug(String func, String info) {
  271. debug(dbgTag, func, info);
  272. }
  273. void debug(String func, Throwable exception) {
  274. debug(dbgTag, func, exception);
  275. }
  276. }