Author: cyberdo
Date: 2006-01-31 21:11:38 +0000 (Tue, 31 Jan 2006)
New Revision: 7974

Added:
   trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java
   trunk/freenet/src/snmplib/
   trunk/freenet/src/snmplib/BERDecoder.java
   trunk/freenet/src/snmplib/BEREncoder.java
   trunk/freenet/src/snmplib/BadFormatException.java
   trunk/freenet/src/snmplib/DataConstantInt.java
   trunk/freenet/src/snmplib/DataConstantString.java
   trunk/freenet/src/snmplib/DataFetcher.java
   trunk/freenet/src/snmplib/DataStatisticsInfo.java
   trunk/freenet/src/snmplib/SNMPAgent.java
   trunk/freenet/src/snmplib/SNMPStarter.java
Modified:
   trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
   trunk/freenet/src/freenet/node/Node.java
Log:
Basic, undocumented, SNMP-support. Most useful OIDs:
.1.3.1.1.0.0 Total outgoing bytes
.1.3.1.1.0.1 Total incoming bytes


Added: trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java 2006-01-31 
18:30:45 UTC (rev 7973)
+++ trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java 2006-01-31 
21:11:38 UTC (rev 7974)
@@ -0,0 +1,226 @@
+package freenet.io.comm;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import snmplib.SNMPStarter;
+
+public class IOStatisticCollector {
+       public static final int STATISTICS_ENTRIES = 10;
+       public static final int STATISTICS_DURATION_S = 30;
+       public static final int STATISTICS_DURATION = 
1000*STATISTICS_DURATION_S;
+       private long lastrotate=0;
+       
+       private static IOStatisticCollector _currentSC = null;
+       private long totalbytesin = 0;
+       private long totalbytesout = 0;
+       private HashMap targets = null;
+       
+       private IOStatisticCollector() {
+               // Only I should be able to create myself
+               _currentSC = this;
+               targets = new HashMap();
+               // TODO: only for testing!!!!
+               // This should only happen once
+               //SNMPAgent.create();
+               SNMPStarter.initialize();
+       }
+       
+       private static IOStatisticCollector getSC() {
+               if (_currentSC == null) {
+                       _currentSC = new IOStatisticCollector();
+               }
+               return _currentSC;
+       }
+       
+       public static void addInfo(String key, int inbytes, int outbytes) {
+               try {
+                       IOStatisticCollector sc = getSC();
+                       synchronized (sc) {
+                               sc._addInfo(key, inbytes, outbytes);
+                       }
+               } catch (Throwable t) {
+                       t.printStackTrace();
+               }
+       }
+       
+       private void _addInfo(String key, int inbytes, int outbytes) {
+               rotate();
+               StatisticEntry entry = (StatisticEntry)targets.get(key);
+               if (entry == null) {
+                       entry = new StatisticEntry();
+                       targets.put(key, entry);
+               }
+               entry.addData(inbytes, outbytes);
+               totalbytesout += outbytes;
+               totalbytesin += outbytes;
+       }
+       
+       public static void dumpInfo() {
+               IOStatisticCollector sc = getSC();
+               synchronized (sc) {
+                       sc._dumpInfo();
+               }
+       }
+
+       public static long[] getTotalIO() {
+               IOStatisticCollector sc = getSC();
+               synchronized (sc) {
+                       return sc._getTotalIO();
+               }
+       }
+       
+       private long[] _getTotalIO() {
+               long ret[] = new long[2]; 
+               ret[0] = totalbytesout;
+               ret[1] = totalbytesin;
+               return ret;
+       }
+       
+       public static int[][] getTotalStatistics() {
+               IOStatisticCollector sc = getSC();
+               synchronized (sc) {
+                       return sc._getTotalStatistics();
+               }
+       }
+
+       private int[][] _getTotalStatistics() {
+               //String[] keys = (String[])targets.keySet().toArray();
+               int ret[][] = new int[STATISTICS_ENTRIES][2];
+               for (int i = 0 ; i < STATISTICS_ENTRIES ; i++) {
+                       ret[i][0] = ret[i][1] = 0;
+               }
+               
+               Iterator it = targets.keySet().iterator();
+               while (it.hasNext()) {
+                       String key = (String)it.next();
+                       int inres[] = 
((StatisticEntry)targets.get(key)).getRecieved();
+                       int outres[] = 
((StatisticEntry)targets.get(key)).getSent();
+                       for (int i = 0 ; i < STATISTICS_ENTRIES ; i++) {
+                               ret[i][1] += inres[i];
+                               ret[i][0] += outres[i];
+                       }
+               }
+               
+               return ret;
+       }
+       
+       private void _dumpInfo() {
+               rotate();
+               //DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, 
Locale.FRANCE);
+               //System.err.println(DateFormat.getDateInstance().format(new 
Date()));
+               System.err.println(new Date());
+               Iterator it = targets.keySet().iterator();
+               final double divby = STATISTICS_DURATION_S*1024; 
+               while (it.hasNext()) {
+                       String key = (String)it.next();
+                       int inres[] = 
((StatisticEntry)targets.get(key)).getRecieved();
+                       int outres[] = 
((StatisticEntry)targets.get(key)).getSent();
+                       System.err.print((key + "          ").substring(0,22) + 
": ");
+                       int tin = 0;
+                       int tout = 0;
+                       
+                       for (int i = 0 ; i < inres.length ; i++) {
+                               // in/out in 102.4 bytes (hecto-bytes)
+                               tin += inres[i];
+                               tout += outres[i];
+                               
+                               int in = (int) (((double)tin*10.0) / 
(divby*(double)(i+1)));
+                               int out =(int) (((double)tout*10.0) 
/(divby*(double)(i+1)));
+                               
+                               System.err.print("i:" + (in/10) + "." + 
(in%10));
+                               System.err.print(" o:" + (out/10) + "." + 
(out%10));
+                               System.err.print(" \t");
+                       }
+                       System.err.println();
+               }
+               System.err.println();
+       }
+       
+       private void rotate() {
+               long now = System.currentTimeMillis();
+               if ((now - lastrotate) >= STATISTICS_DURATION) {
+                       Object[] keys = targets.keySet().toArray();
+                       for(int i = 0 ; i < keys.length ; i++) {
+                               Object key = keys[i];
+                               if 
(((StatisticEntry)(targets.get(key))).rotate() == false)
+                                       targets.remove(key);
+                       }
+                       lastrotate = now;
+                       // FIXME: debugging
+                       //_dumpInfo();
+               }
+       }
+
+       
+/*     
+ * to thead each update.... heavy stuff
+       private class StatisticUpdater implements Runnable {
+               private IOStatisticCollector sc;
+               private String key;
+               private int inbytes;
+               private int outbytes;
+               
+               public StatisticUpdater(IOStatisticCollector sc, String key,
+                               int inbytes, int outbytes) {
+                       this.sc = sc;
+                       this.key = key;
+                       this.inbytes = inbytes;
+                       this.outbytes = outbytes;
+                       new Thread(this).run();
+               }
+               
+               public void run() {
+                       
+               }
+       }
+       */
+       
+       
+       
+       private class StatisticEntry {
+               private int recieved[];
+               private int sent[];
+               
+               public StatisticEntry() {
+                       // Create a new array and clear it
+                       recieved = new 
int[IOStatisticCollector.STATISTICS_ENTRIES+1];
+                       sent     = new 
int[IOStatisticCollector.STATISTICS_ENTRIES+1];
+                       for (int i = 0 ; i < recieved.length ; i++) {
+                               recieved[i] = sent[i] = 0;
+                       }
+               }
+               
+               public void addData(int inbytes, int outbytes) {
+                       recieved[0] += inbytes;
+                       sent[0]     += outbytes;
+               }
+               
+               public boolean rotate() {
+                       boolean hasdata = false;
+                       for (int i = recieved.length - 1 ; i > 0 ; i--) {
+                               recieved[i] = recieved[i-1];
+                               sent[i]     = sent[i-1];
+                               hasdata |= (recieved[i] > 0) || (sent[i] > 0);
+                       }
+                       recieved[0] = sent[0] = 0;
+                       return hasdata;
+               }
+               
+               public int[] getRecieved() {
+                       int retint[] = new 
int[IOStatisticCollector.STATISTICS_ENTRIES];
+                       for(int i = 1 ; i < 
IOStatisticCollector.STATISTICS_ENTRIES + 1 ; i++)
+                               retint[i-1] = recieved[i];
+                       return retint;
+               }
+               
+               public int[] getSent() {
+                       int retint[] = new 
int[IOStatisticCollector.STATISTICS_ENTRIES];
+                       for(int i = 1 ; i < 
IOStatisticCollector.STATISTICS_ENTRIES + 1; i++)
+                               retint[i-1] = sent[i];
+                       return retint;
+               }
+               
+       }
+}

Modified: trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketManager.java     2006-01-31 
18:30:45 UTC (rev 7973)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketManager.java     2006-01-31 
21:11:38 UTC (rev 7974)
@@ -208,6 +208,9 @@
                DatagramPacket packet = new DatagramPacket(new byte[1500], 
1500);
                try {
                        _sock.receive(packet);
+                       // TODO: keep?
+                       IOStatisticCollector.addInfo(packet.getAddress() + ":" 
+ packet.getPort(),
+                                       packet.getLength(), 0);
                } catch (SocketTimeoutException e1) {
                        packet = null;
                } catch (IOException e2) {
@@ -470,6 +473,10 @@
                DatagramPacket packet = new DatagramPacket(blockToSend, 
blockToSend.length);
                packet.setAddress(destination.getAddress());
                packet.setPort(destination.getPort());
+               
+               // TODO: keep?
+               IOStatisticCollector.addInfo(packet.getAddress() + ":" + 
packet.getPort(),
+                               0, packet.getLength());
                try {
                        _sock.send(packet);
                } catch (IOException e) {

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-01-31 18:30:45 UTC (rev 
7973)
+++ trunk/freenet/src/freenet/node/Node.java    2006-01-31 21:11:38 UTC (rev 
7974)
@@ -24,6 +24,9 @@
 import java.util.HashSet;
 import java.util.Iterator;

+import snmplib.SNMPAgent;
+import snmplib.SNMPStarter;
+
 import freenet.client.ArchiveManager;
 import freenet.client.HighLevelSimpleClient;
 import freenet.client.HighLevelSimpleClientImpl;
@@ -342,6 +345,9 @@
         System.out.println("Starting fproxy on port "+(port+2000));
         new FCPServer(port+3000, n);
         System.out.println("Starting FCP server on port "+(port+3000));
+        SNMPAgent.setSNMPPort(port+4000);
+        System.out.println("Starting SNMP server on port "+(port+4000));
+        SNMPStarter.initialize();
         //server.register(fproxy, "/SSK@", false);
         //server.register(fproxy, "/KSK@", false);
     }

Added: trunk/freenet/src/snmplib/BERDecoder.java
===================================================================
--- trunk/freenet/src/snmplib/BERDecoder.java   2006-01-31 18:30:45 UTC (rev 
7973)
+++ trunk/freenet/src/snmplib/BERDecoder.java   2006-01-31 21:11:38 UTC (rev 
7974)
@@ -0,0 +1,120 @@
+package snmplib;
+
+import java.util.Stack;
+
+public class BERDecoder {
+       private byte[] buf;
+       private int ptr = 0;
+       private Stack seqStack;
+       
+       public BERDecoder(byte[] buf) {
+               this.buf = buf;
+               seqStack = new Stack();
+       }
+       
+       public void startSequence() throws BadFormatException {
+               startSequence((byte)0x30);
+       }
+       
+       public void startSequence(byte id) throws BadFormatException {
+               if (buf[ptr] != id)
+                       throw new BadFormatException("Unknown Sequence");
+               ptr++;
+               int len = readBERInt();
+               seqStack.push(new Integer(ptr + len));
+               seqStack.push(new Integer(len));
+       }
+       
+       public void endSequence() throws BadFormatException {
+               int length = ((Integer)seqStack.pop()).intValue();
+               int pos = ((Integer)seqStack.pop()).intValue();
+               if (pos != ptr)
+                       throw new BadFormatException("Wrong length of field " + 
+                                       length + ":" + pos + ":" + ptr);
+       }
+       
+       public byte peekRaw() {
+               return buf[ptr];
+       }
+       
+       public long[] fetchOID() throws BadFormatException {
+               startSequence((byte)0x06);
+               long[] ret = readOID();
+               endSequence();
+               return ret;
+       }
+       
+       private long[] readOID() throws BadFormatException {
+               if (buf[ptr] != 0x2b)
+                       throw new BadFormatException("Bad start of OID");
+               int inptr = ptr;
+               ptr++;
+               int length = ((Integer)seqStack.peek()).intValue();
+               if (length < 2)
+                       return new long[0];
+               long ret[] = new long[length]; // it won't getlonger then this
+               int i;
+               for(i = 0; i < length ; i++) {
+                       ret[i] = readBERInt();
+                       if ((ptr - inptr) >= length)
+                               break;
+               }
+               
+               if (i < length) { // Bring out the scissors
+                       long ret2[] = (long[])ret.clone();
+                       ret = new long[i + 1];
+                       for ( ; i >= 0 ; i--)
+                               ret[i] = ret2[i];
+               }
+               return ret;
+       }
+       
+       
+       public byte[] fetchOctetString() throws BadFormatException {
+               startSequence((byte)0x04);
+               byte[] ret = readOctetString();
+               endSequence();
+               return ret;
+       }
+       
+       private byte[] readOctetString() {
+               int length = ((Integer)seqStack.peek()).intValue();
+               byte ret[] = new byte[length];
+               for(int i = 0; i < length ; i++) {
+                       ret[i] = buf[ptr++];
+               }
+               return ret;
+       }
+
+       
+       public int fetchInt() throws BadFormatException {
+               startSequence((byte)0x02);
+               int ret = readInt();
+               endSequence();
+               return ret;
+       }
+       
+       private int readInt() {
+               int length = ((Integer)seqStack.peek()).intValue();
+               int ret = 0;
+               for ( ; length > 0 ; length--) {
+                       ret = ret * 256;
+                       ret = ret + ((((int)buf[ptr])+256)%256);
+                       ptr++;
+               }
+               return ret;
+       }
+       
+       
+       
+       private int readBERInt() {
+               int ret = 0;
+               do {
+                       ret = ret * 128;
+                       ret = ret + ((((int)buf[ptr])+128)%128);
+                       ptr++;
+               } while (buf[ptr-1] < 0);
+               return ret;
+       }
+
+}

Added: trunk/freenet/src/snmplib/BEREncoder.java
===================================================================
--- trunk/freenet/src/snmplib/BEREncoder.java   2006-01-31 18:30:45 UTC (rev 
7973)
+++ trunk/freenet/src/snmplib/BEREncoder.java   2006-01-31 21:11:38 UTC (rev 
7974)
@@ -0,0 +1,171 @@
+package snmplib;
+
+import java.util.Stack;
+import java.util.Vector;
+
+public class BEREncoder {
+       private IDVector fields;
+       private Stack fstack;
+       
+       public BEREncoder() {
+               this((byte)0x30);
+       }
+       
+       public BEREncoder(byte id) {
+               fields = new IDVector(id);
+               fstack = new Stack();
+               fstack.add(fields);
+       }
+       
+       
+       public int toBytes(byte[] buf) {
+               while (fields.size() > 1)
+                       endSequence();
+               
+               int len = vecToBytes(fields, buf, 0);
+               byte tmpbt;
+               // Remember.. this function writes backwards first!
+               for (int i = 0 ; i < len/2 ; i++) {
+                       tmpbt = buf[i];
+                       buf[i] = buf[len - 1 - i];
+                       buf[len - 1 - i] = tmpbt;
+               }
+                       
+               return len;
+       }
+       
+       private int vecToBytes(IDVector v, byte[] buf, int offset) {
+               int inoffset = offset;
+               for (int i = v.size() - 1 ; i >= 0 ; i--) {
+                       Object o = v.get(i); 
+                       if (o instanceof Integer) {
+                               int dlen = intToBytes(((Integer)o).intValue(), 
buf, offset);
+                               offset += dlen;
+                               offset += intToBERBytes(dlen, buf, offset);
+                               buf[offset++] = 0x02;
+                       } else if (o instanceof IDVector) {
+                               int dlen = vecToBytes((IDVector)o, buf, offset);
+                               offset += dlen;
+                               offset += intToBERBytes(dlen, buf, offset);
+                               buf[offset++] = ((IDVector)o).getVid();
+                       } else if (o instanceof ByteArrWrapper) {
+                               byte[] barr = ((ByteArrWrapper)o).arr;
+                               for (int j = 0 ; j < barr.length ; j++)
+                                       buf[offset + j] = barr[barr.length - 1 
- j];
+                               offset += barr.length;
+                               offset += intToBERBytes(barr.length, buf, 
offset);
+                               buf[offset++] = ((ByteArrWrapper)o).id;
+                       }
+//                             myoffset += intToBytes(v.get(i), buf, myoffset);
+
+               }
+               
+               return (offset - inoffset);
+       }
+       
+       
+       private int intToBytes(int i, byte[] buf, int offset) {
+               int inoffset = offset;
+               if (i == 0) {
+                       buf[offset++] = 0;
+               } else {
+                       for (; i > 0 ; i = i / 256) {
+                               buf[offset] = (byte)(i % 256);
+                               offset++;
+                       }
+               }
+               return (offset - inoffset);
+       }
+       
+       private int intToBERBytes(long i, byte[] buf, int offset) {
+               String bs = Long.toBinaryString(i);
+               int len = (bs.length()%7);
+               bs = ("0000000" + bs).substring(len);
+               char bits[] = bs.toCharArray();
+               int eatenbits = 0;
+               buf[offset] = 0;
+               int inoffset = offset; 
+               //for (int j = bits.length - 1 ; j >= 0 ; j--) {
+               for (int j = 0 ; j < bits.length ; j++) {
+                       if (eatenbits == 7) {
+                               buf[offset] += 128;
+                               offset++;
+                               eatenbits = 0;
+                               buf[offset] = 0;
+                       }
+                       
+                       buf[offset] |= (bits[j]=='1'?1:0) << (6 - eatenbits);
+                       eatenbits++;
+               }
+               offset++;
+               return (offset - inoffset);
+       }
+       
+       
+       
+       public void putInteger(int i) {
+               addToTop(new Integer(i));
+       }
+       
+       public void putOctetString(byte buf[]) {
+               addToTop(new ByteArrWrapper((byte[])buf.clone(), (byte)0x04));
+       }
+
+       public void putOID(long buf[]) {
+               byte bufa[] = new byte[10*buf.length];
+               int offset = 1;
+               bufa[0] = 0x2b;
+               for (int i = 0 ; i < buf.length ; i++) {
+                       offset += intToBERBytes(buf[i], bufa, offset);
+               }
+               byte bufb[] = new byte[offset];
+               for (int i = 0 ; i < bufb.length ; i++)
+                       bufb[i] = bufa[i];
+               
+               addToTop(new ByteArrWrapper(bufb, (byte)0x06));
+       }
+
+       public void startSequence() {
+               startSequence((byte)0x30);
+       }
+       
+       public void startSequence(byte id) {
+               IDVector v = new IDVector(id);
+               addToTop(v);
+               fstack.add(v);
+       }
+       
+       public void endSequence() {
+               fstack.pop();
+       }
+       
+       private void addToTop(Object o) {
+               ((IDVector)fstack.peek()).addElement(o);
+       }
+       
+       private class ByteArrWrapper {
+               public byte arr[];
+               public byte id;
+               
+               public ByteArrWrapper(byte arr[], byte id) {
+                       this.arr = arr;
+                       this.id = id;
+               }
+       }
+       
+       // unpublic
+       private class IDVector extends Vector {
+               private static final long serialVersionUID = 
2689317091785298027L;
+               byte vid = (byte)0x30;
+               
+               public IDVector(byte id) {
+                       super();
+                       vid = id;
+               }
+               
+               public byte getVid() {
+                       return vid;
+               }
+
+       }
+}

Added: trunk/freenet/src/snmplib/BadFormatException.java
===================================================================
--- trunk/freenet/src/snmplib/BadFormatException.java   2006-01-31 18:30:45 UTC 
(rev 7973)
+++ trunk/freenet/src/snmplib/BadFormatException.java   2006-01-31 21:11:38 UTC 
(rev 7974)
@@ -0,0 +1,7 @@
+package snmplib;
+
+public class BadFormatException extends Exception {
+       public BadFormatException(String s) {
+               super(s);
+       }
+}

Added: trunk/freenet/src/snmplib/DataConstantInt.java
===================================================================
--- trunk/freenet/src/snmplib/DataConstantInt.java      2006-01-31 18:30:45 UTC 
(rev 7973)
+++ trunk/freenet/src/snmplib/DataConstantInt.java      2006-01-31 21:11:38 UTC 
(rev 7974)
@@ -0,0 +1,19 @@
+package snmplib;
+
+public class DataConstantInt implements DataFetcher {
+       private String OID;
+       private int value;
+       
+       public DataConstantInt(String oID, int value) {
+               this.OID = oID;
+               this.value = value;
+       }
+       
+       public String getSNMPOID() {
+               return OID;
+       }
+
+       public Object getSNMPData() {
+               return new Integer(value);
+       }
+}

Added: trunk/freenet/src/snmplib/DataConstantString.java
===================================================================
--- trunk/freenet/src/snmplib/DataConstantString.java   2006-01-31 18:30:45 UTC 
(rev 7973)
+++ trunk/freenet/src/snmplib/DataConstantString.java   2006-01-31 21:11:38 UTC 
(rev 7974)
@@ -0,0 +1,19 @@
+package snmplib;
+
+public class DataConstantString implements DataFetcher {
+       private String OID;
+       private String value;
+       
+       public DataConstantString(String oID, String value) {
+               this.OID = oID;
+               this.value = value;
+       }
+       
+       public String getSNMPOID() {
+               return OID;
+       }
+
+       public Object getSNMPData() {
+               return value;
+       }
+}

Added: trunk/freenet/src/snmplib/DataFetcher.java
===================================================================
--- trunk/freenet/src/snmplib/DataFetcher.java  2006-01-31 18:30:45 UTC (rev 
7973)
+++ trunk/freenet/src/snmplib/DataFetcher.java  2006-01-31 21:11:38 UTC (rev 
7974)
@@ -0,0 +1,10 @@
+package snmplib;
+
+public interface DataFetcher {
+       
+       public String getSNMPOID();
+       
+       /* Must return an Integer or a String */
+       public Object getSNMPData();
+
+}

Added: trunk/freenet/src/snmplib/DataStatisticsInfo.java
===================================================================
--- trunk/freenet/src/snmplib/DataStatisticsInfo.java   2006-01-31 18:30:45 UTC 
(rev 7973)
+++ trunk/freenet/src/snmplib/DataStatisticsInfo.java   2006-01-31 21:11:38 UTC 
(rev 7974)
@@ -0,0 +1,35 @@
+package snmplib;
+
+import freenet.io.comm.IOStatisticCollector;
+
+public class DataStatisticsInfo implements DataFetcher {
+       private String OID;
+       int blocks;
+       boolean in;
+       
+       public DataStatisticsInfo(int blocks, boolean in) {
+               this.OID = "1.1." + blocks + "." + (in?"1":"0");
+               //System.err.println("adding: " + this.OID);
+               this.in = in;
+               this.blocks = blocks;
+       }
+       
+       public String getSNMPOID() {
+               //System.err.println("        " + this.OID);
+               return OID;
+       }
+
+       public Object getSNMPData() {
+               if (blocks == 0) {
+                       long io[] = IOStatisticCollector.getTotalIO();
+                       return new Integer((int)io[in?1:0]);
+               }
+               // else sum all fields up to <blocks>
+               int res = 0;
+               int stats[][] = IOStatisticCollector.getTotalStatistics();
+               for (int i = 0 ; i < blocks ; i++)
+                       res += stats[i][in?1:0];
+               
+               return new Integer(res);
+       }
+}

Added: trunk/freenet/src/snmplib/SNMPAgent.java
===================================================================
--- trunk/freenet/src/snmplib/SNMPAgent.java    2006-01-31 18:30:45 UTC (rev 
7973)
+++ trunk/freenet/src/snmplib/SNMPAgent.java    2006-01-31 21:11:38 UTC (rev 
7974)
@@ -0,0 +1,266 @@
+package snmplib;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.util.Iterator;
+import java.util.TreeMap;
+
+public class SNMPAgent implements Runnable {
+       private int port = 4445;
+
+       /**
+        * @param args
+        */
+       public static void main(String[] args) throws IOException {
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.1", 10));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.2", 20));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.3", 30));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.4", 40));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantInt("1.1.5", 50));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantString("1.1.0", "Step by 10"));
+               SNMPAgent.getSNMPAgent().addFetcher(new 
DataConstantString("1.2", "Nothing here"));
+       }
+       
+    protected DatagramSocket socket = null;
+    protected BufferedReader in = null;
+    protected boolean moreQuotes = true;
+    private TreeMap alldata;
+    private static SNMPAgent _SNMPAgent = null;
+
+    public static void setSNMPPort(int port) {
+       ensureCreated();
+       _SNMPAgent.port = port;
+       restartSNMPAgent();
+    }
+    
+    public static void restartSNMPAgent() {
+       ensureCreated();
+       _SNMPAgent.stopRunning();
+       new Thread(_SNMPAgent).start();
+    }
+    
+    public static SNMPAgent getSNMPAgent() {
+       ensureCreated();
+       return _SNMPAgent;
+    }
+    
+    private static void ensureCreated() {
+       if (_SNMPAgent == null)
+               _SNMPAgent = new SNMPAgent();
+    }
+    
+    private SNMPAgent() {
+       alldata = new TreeMap();
+    }
+    
+    public void addFetcher(DataFetcher df) {
+       DataHandler dh = new DataHandler(df);
+       alldata.put(dh.getStringOID(), dh);
+    }
+
+    public void removeFetcher(String OID) {
+       alldata.remove(((OID.startsWith("\\."))?"":".") + OID);
+    }
+    
+    public void stopRunning() {
+       try {
+               socket.close();
+       } catch (Throwable e) {
+               // prpbably since not running...
+       }
+    }
+
+    public void run() {
+       try {
+               socket = new DatagramSocket(port, 
InetAddress.getByName("localhost"));
+       } catch (IOException e) {
+               e.printStackTrace();
+               return ;
+       }
+       // make smaller.... 0484 enough?
+        byte[] buf = new byte[65535];
+        DatagramPacket packet = new DatagramPacket(buf, buf.length);
+
+        while (socket.isBound()) {
+            try {
+                socket.receive(packet);
+
+                RequestContainer rc = new RequestContainer();
+                
+                parseRequest(buf, rc);
+                
+                int replylength = 0;
+                boolean keyfound = false;
+                DataHandler dh = null;
+                
+                Iterator it = alldata.keySet().iterator();
+                String key = "";
+                if (rc.OID.length() == 0)
+                       rc.OID = ".";
+                
+                while (it.hasNext() && !keyfound) {
+                       key = (String)it.next();
+                       if (key.startsWith(rc.OID))
+                               keyfound = true;
+                }
+
+                // keyfound /\ (equal -> hasnext)
+                if (keyfound && (!key.equals(rc.OID) || it.hasNext())) {
+                       key = key.equals(rc.OID)?(String)it.next():key;
+                       
+                       dh = (DataHandler)alldata.get(key);
+                       rc.lOID = (long[])dh.lOID.clone();
+
+                       replylength = makeIntReply(buf, rc, dh.getData());
+                } else {
+                       rc.lOID[0] = 100;
+                       replylength = makeIntReply(buf, rc, new Integer(1));
+                }
+                
+                // send the response to the client at "address" and "port"
+                InetAddress address = packet.getAddress();
+                int port = packet.getPort();
+                packet = new DatagramPacket(buf, replylength, address, port);
+                socket.send(packet);
+                
+            } catch (IOException e) {
+                e.printStackTrace();
+                break;
+            } catch (BadFormatException e) {
+               System.err.println(e.toString());
+            } catch (ArrayIndexOutOfBoundsException e) {
+               e.printStackTrace();
+               // not much to do.. ignore the request and it'll time out
+            }
+        }
+        socket.close();
+    }
+    
+    private int makeIntReply(byte buf[], RequestContainer rc, Object data) /* 
throws SnmpTooBigException */ {
+       int replyLength = 0;
+       BEREncoder be = new BEREncoder();
+       be.startSequence(); // whole pkg
+       be.putInteger(0); // version
+       be.putOctetString(rc.community); // community
+       be.startSequence((byte)0xa2); // Response
+       be.putInteger(rc.requestID); // RID
+       be.putInteger(0); // err
+       be.putInteger(0); // err
+       be.startSequence(); // value
+       be.startSequence(); // value
+       be.putOID(rc.lOID); // oid
+       
+       if (data instanceof Integer)
+               be.putInteger(((Integer)data).intValue());
+       else if (data instanceof String) {
+               char[] charr = ((String)data).toCharArray();
+               byte[] byarr = new byte[charr.length];
+               for (int i = 0 ; i < charr.length ; i++)
+                       byarr[i] = (byte)charr[i];
+               be.putOctetString(byarr);
+       }
+       
+       replyLength = be.toBytes(buf);
+       
+       return replyLength;
+    }
+    
+    // http://www.rane.com/note161.html
+    private void parseRequest(byte buf[], RequestContainer rc) throws 
BadFormatException {
+       int tmpint;
+       
+       BERDecoder bd = new BERDecoder(buf);
+       bd.startSequence();
+       if ((tmpint = bd.fetchInt()) != 0)
+               throw new BadFormatException("Wrong version, expected 0, got "
+                               + tmpint);
+       
+       rc.community = bd.fetchOctetString();
+       if (! rc.setPDU(bd.peekRaw()))
+               throw new BadFormatException("Unknown PDU");
+       bd.startSequence(bd.peekRaw());
+       rc.requestID = bd.fetchInt();
+       
+       // TODO: care about errors eventually?
+       bd.fetchInt();
+       bd.fetchInt();
+       
+       bd.startSequence();
+       bd.startSequence();
+       rc.lOID = bd.fetchOID();
+       rc.OID = (rc.lOID.length == 0)?".":"";
+       for (int i = 0; i < rc.lOID.length ; i++)
+               rc.OID += "." + rc.lOID[i];
+       
+    }
+
+   
+    private class DataHandler {
+       //public Integer data;
+       public long lOID[] = null;
+       DataFetcher df;
+       
+       public DataHandler(DataFetcher df) {
+               lOID = splitToLong(df.getSNMPOID());
+               this.df = df;
+       }
+       
+        private long[] splitToLong(String list) {
+               String nums[] = list.split("\\.");
+               long ret[] = new long[nums.length];
+               for(int i = 0; i < ret.length ; i++)
+                       ret[i] = Long.parseLong(nums[i]);
+               return ret;
+        }
+
+        public Object getData() {
+               return df.getSNMPData(); 
+        }
+       
+       public String getStringOID() {
+               String ret = "";
+                       for (int i = 0; i < lOID.length ; i++)
+                               ret += "." + lOID[i];
+               return ret;
+       }
+    }
+    
+    
+    
+    
+
+    private class RequestContainer {
+       public long lOID[] = null;
+       public byte community[] = null;
+       public int pdutype = 0;
+       public static final int PDU_GET_NEXT = 2;
+       public static final int PDU_GET_THIS = 1;
+       public int requestID = 0;
+       public String OID = null;
+       
+       public boolean setPDU(byte id) {
+               switch(id) {
+               case (byte)0xA0:
+                       pdutype = PDU_GET_THIS;
+               break;
+               
+               case (byte)0xA1:
+                       pdutype = PDU_GET_NEXT;
+               break;
+               
+               default:
+                       //System.err.println("Unknown PDU: 0x" + 
Integer.toHexString((id + 256)%256));
+                       return false;
+               }
+               return true;
+       }
+       
+       public String toString() {
+               return ("Community: " + new String(community) +
+                               ", PDU: " + pdutype + ", OID: " + OID);
+       }
+    }
+}

Added: trunk/freenet/src/snmplib/SNMPStarter.java
===================================================================
--- trunk/freenet/src/snmplib/SNMPStarter.java  2006-01-31 18:30:45 UTC (rev 
7973)
+++ trunk/freenet/src/snmplib/SNMPStarter.java  2006-01-31 21:11:38 UTC (rev 
7974)
@@ -0,0 +1,26 @@
+package snmplib;
+
+import snmplib.DataStatisticsInfo;
+import freenet.io.comm.IOStatisticCollector;
+
+/**
+ * @author cyberdo
+ *
+ * Creates the SNMP-agent
+ */
+public class SNMPStarter {
+
+       private static boolean has_been_runned = false;
+
+       public static void initialize() {
+               //SNMPAgent.setSNMPPort(port);
+               if (has_been_runned) return;
+               // 0 is toatl I/O
+               for (int i = 0 ; i < IOStatisticCollector.STATISTICS_ENTRIES ; 
i++) {
+                       SNMPAgent.getSNMPAgent().addFetcher(new 
DataStatisticsInfo(i, true));
+                       SNMPAgent.getSNMPAgent().addFetcher(new 
DataStatisticsInfo(i, false));
+               }
+               
+               has_been_runned = true;
+       }
+}


Reply via email to