KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > snmp > daemon > SnmpSocket


1 /*
2  * @(#)file SnmpSocket.java
3  * @(#)author Sun Microsystems, Inc.
4  * @(#)version 1.8
5  * @(#)date 08/02/09
6  *
7  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
8  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
9  *
10  */

11
12
13 package com.sun.jmx.snmp.daemon;
14
15
16 // JAVA imports
17
//
18
import java.net.InetAddress JavaDoc;
19 import java.net.DatagramPacket JavaDoc;
20 import java.net.DatagramSocket JavaDoc;
21 import java.net.SocketException JavaDoc;
22 import java.io.IOException JavaDoc;
23
24 // SNMP Runtime imports
25
//
26
import com.sun.jmx.trace.Trace;
27
28
29 /**
30  * This class creates an SNMP Datagram Socket. This class has methods helpful
31  * to send SNMP inform request packets to an arbitrary port of a specified device.
32  * It also runs a thread that is devoted to receiving SNMP inform response on the socket.
33  * <BR>
34  * A socket imposes an upper limit on size of inform response packet. Any
35  * packet which exceeds this limit is truncated. By default, this
36  * limit is {@link SnmpAdaptorServer#bufferSize}.
37  */

38
39 final class SnmpSocket implements java.lang.Runnable JavaDoc {
40
41     
42     // VARIABLES
43
//----------
44

45     private DatagramSocket JavaDoc _socket = null;
46     private SnmpResponseHandler _dgramHdlr = null;
47     private Thread JavaDoc _sockThread = null;
48     private byte[] _buffer = null;
49     private transient boolean isClosing = false;
50
51     int _socketPort = 0;
52     int responseBufSize = 1024;
53     String JavaDoc dbgTag = "SnmpSocket";
54     
55     // CONSTRUCTORS
56
//-------------
57

58     /**
59      * Creates a new <CODE>SnmpSocket</CODE> object.
60      * @param rspHdlr A Datagram handler.
61      * @param bufferSize The SNMP adaptor buffer size.
62      * @exception SocketException A socket could not be created.
63      */

64     public SnmpSocket(SnmpResponseHandler rspHdlr, InetAddress JavaDoc addr, int bufferSize) throws SocketException JavaDoc {
65         super();
66         
67         if (isTraceOn()) {
68             trace("constructor", "Creating new SNMP datagram socket");
69         }
70     
71         // TIME BOMB HERE
72
_socket = new DatagramSocket JavaDoc(0, addr);
73         _socketPort = _socket.getLocalPort();
74         responseBufSize = bufferSize;
75         _buffer = new byte[responseBufSize];
76         _dgramHdlr = rspHdlr;
77         _sockThread = new Thread JavaDoc(this, "SnmpSocket");
78         _sockThread.start();
79     }
80
81     // PUBLIC METHODS
82
//---------------
83

84     /**
85      * Sends a datagram packet to a specified device at specified port.
86      * @param buff The packet data.
87      * @param length The packet length.
88      * @param addr The destination address.
89      * @param port The destination port number.
90      * @exception IOException Signals that an I/O exception of some sort has occurred.
91      */

92     public synchronized void sendPacket(byte[] buff, int length, InetAddress JavaDoc addr, int port) throws IOException JavaDoc {
93         DatagramPacket JavaDoc dgrmpkt;
94         dgrmpkt = new DatagramPacket JavaDoc(buff, length, addr, port);
95         sendPacket(dgrmpkt);
96     }
97     
98     /**
99      * Sends a datagram packet to a specified device at specified port.
100      * @param dgrmpkt The datagram packet.
101      * @exception IOException Signals that an I/O exception of some sort has occurred.
102      */

103     public synchronized void sendPacket(DatagramPacket JavaDoc dgrmpkt) throws IOException JavaDoc {
104     
105         try {
106             if (isValid()) {
107                 if (isTraceOn()) {
108                     trace("sendPacket", "Sending DatagramPacket. Length = " + dgrmpkt.getLength() +
109                           " through socket = " + _socket.toString());
110                 }
111                 _socket.send(dgrmpkt);
112             } else
113                 throw new IOException JavaDoc("Invalid state of SNMP datagram socket.");
114         } catch (IOException JavaDoc e) {
115             if (isDebugOn()) {
116                 debug("sendPacket", "Io error while sending");
117                 debug("sendPacket", e.getMessage());
118             }
119             throw e;
120         }
121     }
122
123     /**
124      * Checks if the socket is initialised correctly and if it is still active.
125      * @return <CODE>true</CODE> if the socket is initialised correctly and if it is still active,
126      * <CODE>false</CODE> otherwise.
127      */

128     public synchronized boolean isValid() {
129         return _socket != null && _sockThread != null && _sockThread.isAlive();
130     }
131     
132     /**
133      * Closes the socket and its associated resources.
134      */

135     public synchronized void close() {
136         
137         isClosing = true;
138
139         if (isTraceOn()) {
140             trace("close", "Closing and destroying the SNMP datagram socket -> " + toString());
141         }
142         
143         try {
144             // We send an empty datagram packet to fix bug 4293791 (it's a jdk 1.1 bug)
145
//
146
DatagramSocket JavaDoc sn = new java.net.DatagramSocket JavaDoc(0);
147             byte[] ob = new byte[1];
148             DatagramPacket JavaDoc pk = new DatagramPacket JavaDoc(ob , 1, java.net.InetAddress.getLocalHost(), _socketPort);
149             sn.send(pk);
150             sn.close();
151         } catch (Exception JavaDoc e) {}
152                 
153         // First close the datagram socket.
154
// This may generates an IO exception at the run method (_socket.receive).
155
//
156
if (_socket != null) {
157             _socket.close() ;
158             _socket = null ;
159         }
160     
161         // Then stop the thread socket.
162
//
163
if (_sockThread != null && _sockThread.isAlive()) {
164             _sockThread.interrupt();
165             try {
166                 // Wait until the thread die.
167
//
168
_sockThread.join();
169             } catch (InterruptedException JavaDoc e) {
170                 // Ignore...
171
}
172             _sockThread = null ;
173         }
174     }
175
176     /**
177      * Dispatcher method for this socket thread. This is the dispatcher method
178      * which goes in an endless-loop and waits for receiving datagram packets on the socket.
179      */

180     public void run() {
181         Thread.currentThread().setPriority(8);
182
183         while (true) {
184             try {
185                 DatagramPacket JavaDoc dgrmpkt = new DatagramPacket JavaDoc (_buffer, _buffer.length);
186
187                 if (isTraceOn()) {
188                     trace("run", "[" + Thread.currentThread().toString() + "]:" + "Blocking for receiving packet");
189                 }
190
191                 _socket.receive(dgrmpkt);
192                 
193                 // If the corresponding session is being destroyed, stop handling received responses.
194
//
195
if (isClosing)
196                     break;
197
198                 if (isTraceOn()) {
199                     trace("run", "[" + Thread.currentThread().toString() + "]:" + "Received a packet");
200                 }
201
202                 if (dgrmpkt.getLength() <= 0)
203                     continue;
204
205                 if (isTraceOn()) {
206                     trace("run", "[" + Thread.currentThread().toString() + "]:" + "Received a packet from : " +
207                           dgrmpkt.getAddress().toString() + ", Length = " + dgrmpkt.getLength());
208                 }
209
210                 handleDatagram(dgrmpkt);
211                 
212                 // We are closing the snmp socket while handling the datagram.
213
//
214
if (isClosing)
215                     break;
216             
217             } catch (IOException JavaDoc io) {
218                 // If the IO exception has been generated because of closing this SNMP socket,
219
// (call to _socket.close while _socket is blocked for receiving packet) simply terminate closing properly.
220
//
221
if (isClosing) {
222                     break;
223                 }
224                 if (isDebugOn()) {
225                     debug("run", io.getMessage());
226                     debug("run", io);
227                 }
228             } catch (Exception JavaDoc e) {
229                 // If the exception (NullPointerException) has been generated because of closing this SNMP socket,
230
// (call to _socket = null while _socket is blocked for receiving packet) simply terminate closing properly.
231
//
232
if (isClosing) {
233                     break;
234                 }
235                 if (isDebugOn()) {
236                     debug("run", "Exception in socket thread...");
237                     debug("run", e);
238                 }
239             } catch (ThreadDeath JavaDoc d) {
240                 if (isDebugOn()) {
241                     debug("run", "Socket Thread DEAD..." + toString());
242                     debug("run", d);
243                 }
244                 close();
245                 throw d; // rethrow dead thread.
246
} catch (Error JavaDoc err) {
247                 if (isDebugOn()) {
248                     debug("run", err);
249                 }
250                 handleJavaError(err);
251             }
252         }
253     }
254     
255     /**
256      * Finalizer of the <CODE>SnmpSocket</CODE> objects.
257      * This method is called by the garbage collector on an object
258      * when garbage collection determines that there are no more references to the object.
259      * <P>Closes the datagram socket and stops the socket thread associated to this SNMP socket.
260      */

261     public synchronized void finalize() {
262         close();
263     }
264     
265     // PRIVATE METHODS
266
//----------------
267

268     /*
269      * Keep this locked so that send can't happen.
270      */

271     private synchronized void handleJavaError(Throwable JavaDoc thr) {
272         if (thr instanceof OutOfMemoryError JavaDoc) {
273             if (isDebugOn()) {
274                 debug("handleJavaError", thr);
275             }
276             Thread.currentThread().yield();
277             return ;
278         }
279         if (_socket != null) {
280             _socket.close();
281             _socket = null;
282         }
283
284         if (isDebugOn()) {
285             debug("handleJavaError", "Global Internal error");
286         }
287         Thread.currentThread().yield();
288     }
289
290     private synchronized void handleDatagram(DatagramPacket JavaDoc dgrmpkt) {
291         _dgramHdlr.processDatagram(dgrmpkt);
292     }
293
294     // TRACES & DEBUG
295
//---------------
296

297     boolean isTraceOn() {
298         return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP);
299     }
300
301     void trace(String JavaDoc clz, String JavaDoc func, String JavaDoc info) {
302         Trace.send(Trace.LEVEL_TRACE, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
303     }
304
305     void trace(String JavaDoc func, String JavaDoc info) {
306         trace(dbgTag, func, info);
307     }
308     
309     boolean isDebugOn() {
310         return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP);
311     }
312
313     void debug(String JavaDoc clz, String JavaDoc func, String JavaDoc info) {
314         Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, info);
315     }
316
317     void debug(String JavaDoc clz, String JavaDoc func, Throwable JavaDoc exception) {
318         Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_ADAPTOR_SNMP, clz, func, exception);
319     }
320
321     void debug(String JavaDoc func, String JavaDoc info) {
322         debug(dbgTag, func, info);
323     }
324     
325     void debug(String JavaDoc func, Throwable JavaDoc exception) {
326         debug(dbgTag, func, exception);
327     }
328 }
329
330
Popular Tags