Author: infinity0
Date: 2009-03-31 13:09:45 +0000 (Tue, 31 Mar 2009)
New Revision: 26281

Added:
   trunk/contrib/fec/lib/fec.properties
   trunk/contrib/fec/src/com/
   trunk/contrib/fec/src/com/onionnetworks/
   trunk/contrib/fec/src/com/onionnetworks/fec/
   trunk/contrib/fec/src/com/onionnetworks/fec/DefaultFECCodeFactory.java
   trunk/contrib/fec/src/com/onionnetworks/fec/FECCode.java
   trunk/contrib/fec/src/com/onionnetworks/fec/FECCodeFactory.java
   trunk/contrib/fec/src/com/onionnetworks/fec/FECMath.java
   trunk/contrib/fec/src/com/onionnetworks/fec/Native16Code.java
   trunk/contrib/fec/src/com/onionnetworks/fec/Native8Code.java
   trunk/contrib/fec/src/com/onionnetworks/fec/Pure16Code.java
   trunk/contrib/fec/src/com/onionnetworks/fec/PureCode.java
Removed:
   trunk/contrib/fec/fec_src/
Modified:
   trunk/contrib/freenet_ext/build.xml
Log:
Cleaner directory structure (git commit summary follows:)

 On branch master
 Changes to be committed:
   (use "git reset HEAD <file>..." to unstage)

        renamed:    contrib/fec/fec_src/lib/fec.properties -> 
contrib/fec/lib/fec.properties
        renamed:    
contrib/fec/fec_src/com/onionnetworks/fec/DefaultFECCodeFactory.java -> 
contrib/fec/src/com/onionnetworks/fec/DefaultFECCodeFactory.java
        renamed:    contrib/fec/fec_src/com/onionnetworks/fec/FECCode.java -> 
contrib/fec/src/com/onionnetworks/fec/FECCode.java
        renamed:    
contrib/fec/fec_src/com/onionnetworks/fec/FECCodeFactory.java -> 
contrib/fec/src/com/onionnetworks/fec/FECCodeFactory.java
        renamed:    contrib/fec/fec_src/com/onionnetworks/fec/FECMath.java -> 
contrib/fec/src/com/onionnetworks/fec/FECMath.java
        renamed:    contrib/fec/fec_src/com/onionnetworks/fec/Native16Code.java 
-> contrib/fec/src/com/onionnetworks/fec/Native16Code.java
        renamed:    contrib/fec/fec_src/com/onionnetworks/fec/Native8Code.java 
-> contrib/fec/src/com/onionnetworks/fec/Native8Code.java
        renamed:    contrib/fec/fec_src/com/onionnetworks/fec/Pure16Code.java 
-> contrib/fec/src/com/onionnetworks/fec/Pure16Code.java
        renamed:    contrib/fec/fec_src/com/onionnetworks/fec/PureCode.java -> 
contrib/fec/src/com/onionnetworks/fec/PureCode.java
        modified:   contrib/freenet_ext/build.xml

Copied: trunk/contrib/fec/lib/fec.properties (from rev 26280, 
trunk/contrib/fec/fec_src/lib/fec.properties)
===================================================================
--- trunk/contrib/fec/lib/fec.properties                                (rev 0)
+++ trunk/contrib/fec/lib/fec.properties        2009-03-31 13:09:45 UTC (rev 
26281)
@@ -0,0 +1,17 @@
+# Order is very important because it defines the preffered order to try 
+# the various codes.  So faster performing codes should be at the front of the
+# list.
+
+com.onionnetworks.fec.keys=native8,pure8,native16,pure16
+
+com.onionnetworks.fec.native8.class=com.onionnetworks.fec.Native8Code
+com.onionnetworks.fec.native8.bits=8
+
+com.onionnetworks.fec.pure8.class=com.onionnetworks.fec.PureCode
+com.onionnetworks.fec.pure8.bits=8
+
+com.onionnetworks.fec.native16.class=com.onionnetworks.fec.Native16Code
+com.onionnetworks.fec.native16.bits=16
+
+com.onionnetworks.fec.pure16.class=com.onionnetworks.fec.Pure16Code
+com.onionnetworks.fec.pure16.bits=16

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/DefaultFECCodeFactory.java 
(from rev 26280, 
trunk/contrib/fec/fec_src/com/onionnetworks/fec/DefaultFECCodeFactory.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/DefaultFECCodeFactory.java      
                        (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/DefaultFECCodeFactory.java      
2009-03-31 13:09:45 UTC (rev 26281)
@@ -0,0 +1,139 @@
+package com.onionnetworks.fec;
+
+import java.util.*;
+import java.io.IOException;
+import java.lang.reflect.*;
+import com.onionnetworks.util.Tuple;
+import com.onionnetworks.util.TimedSoftHashMap;
+
+/**
+ * This is the default FECCodeFactory that wraps all of the FECCode 
+ * implementations.  It provides a way to customize the codes through
+ * a properties file specified by the property 
+ * "com.onionnetworks.fec.defaultfeccodefactorypropertiesfile".  By default
+ * it will use the "lib/fec.properties" file distributed with the JAR.
+ * Please consult this file for an example of how this should be done.
+ *
+ * The properties in this file can also be passed manually to the 
+ * System properties.  Again, consult the provided properties file for an
+ * example.  This given, if you are adding new codes to this stuff please
+ * let me know because I worked my ass of to provide this for you, so do me
+ * a favor and at least let me know what you're using this for.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public class DefaultFECCodeFactory extends FECCodeFactory {
+
+    public static final int DEFAULT_CACHE_TIME = 2*60*1000;
+
+    //protected TimedSoftHashMap codeCache = new HashMap();
+    protected ArrayList eightBitCodes = new ArrayList();
+    protected ArrayList sixteenBitCodes = new ArrayList();
+    protected Properties fecProperties;
+
+    public DefaultFECCodeFactory() {
+        // Load in the properties file.
+        try {
+            fecProperties = new Properties();
+            fecProperties.load
+                (ClassLoader.getSystemClassLoader().
+                 getResourceAsStream
+                 (System.getProperty
+                  ("com.onionnetworks.fec.defaultfeccodefactorypropertiesfile",
+                   "lib/fec.properties")));
+
+//              fecProperties.load
+//                  (DefaultFECCodeFactory.class.getClassLoader().
+//                   getResourceAsStream
+//                   (System.getProperty
+//                    
("com.onionnetworks.fec.defaultfeccodefactorypropertiesfile",
+//                     "lib/fec.properties")));
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new IllegalStateException
+                ("Unable to load /lib/fec.properties");
+        }
+
+        // Parse the keys
+        StringTokenizer st = new StringTokenizer
+            (getProperty("com.onionnetworks.fec.keys"),",");
+
+        // Load the codes into the HashMaps.
+        while (st.hasMoreTokens()) {
+            String key = st.nextToken();
+            try {
+                Constructor con = Class.forName
+                    (getProperty("com.onionnetworks.fec."+key+".class")).
+                    getConstructor(new Class[] {int.class, int.class});
+                String numBits = 
getProperty("com.onionnetworks.fec."+key+".bits");
+                if ("8".equals(numBits)) {
+                    eightBitCodes.add(con);
+                } else if ("16".equals(numBits)) {
+                    sixteenBitCodes.add(con);
+                } else {
+                    throw new IllegalArgumentException
+                        ("Only 8 and 16 bit codes are currently supported");
+                }
+            } catch (Throwable t) {
+                System.out.println(t.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Get a value, trying the System properties first and then checking
+     * the fecProperties.
+     */
+    protected synchronized String getProperty(String key) {
+        String result = System.getProperty(key);
+        if (result == null) {
+            result = fecProperties.getProperty(key);
+        }
+        return result;
+    }
+
+    /**
+     * If you're only asking for an 8 bit code we will NOT give you a 16 bit
+     * one.
+     */
+    public synchronized FECCode createFECCode(int k, int n) {
+        Integer K = new Integer(k);
+        Integer N = new Integer(n);
+        Tuple t = new Tuple(K,N);
+
+        // See if there is a cached code.
+        FECCode result = null; //(FECCode) codeCache.get(t);
+        if (result == null) {
+            if (k < 1 || k > 65536 || n < k || n > 65536) {
+                throw new IllegalArgumentException
+                    ("k and n must be between 1 and 65536 and n must not be "+
+                     "smaller than k: k="+k+",n="+n);
+            }
+
+            Iterator it;
+            if (n <= 256 && !eightBitCodes.isEmpty()) {
+                it = eightBitCodes.iterator();
+            } else {
+                it = sixteenBitCodes.iterator();
+            }
+            while (it.hasNext()) {
+                try {
+                    result = (FECCode) ((Constructor) it.next()).newInstance
+                        (new Object[] {K, N});
+                    break;
+                } catch (Throwable doh) {
+                    //doh.printStackTrace();
+                }
+            }
+                        
+            //if (result != null) {
+            //    codeCache.put(t,result,DEFAULT_CACHE_TIME);
+            // }
+        } 
+        return result;
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/FECCode.java (from rev 
26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/FECCode.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/FECCode.java                    
        (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/FECCode.java    2009-03-31 
13:09:45 UTC (rev 26281)
@@ -0,0 +1,275 @@
+package com.onionnetworks.fec;
+
+import com.onionnetworks.util.Util;
+import com.onionnetworks.util.Buffer;
+
+/**
+ *
+ * This class provides the main API/SPI for the FEC library.  You cannot
+ * construct an FECCode directly, rather you must use an FECCodeFactory.
+ *
+ * For example:
+ * <code>
+ *   int k = 32;
+ *   int n = 256;
+ *   FECCode code = FECCodeFactory.getDefault().createFECCode(k,n);
+ * </code>
+ *
+ * All FEC
+ * implementations will sublcass FECCode and implement the encode/decode
+ * methods.  All codes implemented by this interface are assumed to be
+ * systematic codes which means that the first k repair packets will be
+ * the same as the original source packets.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public abstract class FECCode {
+
+    protected int k,n;
+    
+    /**
+     * Construct a new FECCode given <code>k</code> and <code>n</code>
+     *
+     * @param k The number of source packets to be encoded/decoded.
+     * @param n The number of packets that the source packets will be encoded
+     * to.
+     */
+    protected FECCode(int k, int n) {
+        this.k = k;
+        this.n = n;
+    }
+
+    /**
+     * This method takes an array of source packets and generates a number
+     * of repair packets from them.  This method could have taken in only
+     * one repair packet to be generated, but in many cases it is more
+     * efficient (and convenient) to encode multiple packets at once.  This
+     * is especially true of the NativeCode implementation where data must
+     * be copied and the Java->Native->Java transition is expensive.
+     *
+     * @param src An array of <code>k</code> byte[]'s that contain the source
+     * packets to be encoded.  Often these byte[]'s are actually references
+     * to a single byte[] that contains the entire source block, then you must
+     * simply vary the srcOff's to pass it in in this fashion.  src[0] will
+     * point to the 1st packet, src[1] to the second, etc.
+     *
+     * @param srcOff An array of integers which specifies the offset of each
+     * each packet within its associated byte[].
+     * 
+     * @param repair Much like src, variable points to a number of buffers
+     * to which the encoded repair packets will be written.  This array should
+     * be the same length as repairOff and index.
+     * 
+     * @param repairOff This is the repair analog to srcOff.
+     *
+     * @param index This int[] specifies the indexes of the packets to be
+     * encoded and written to <code>repair</code>.  These indexes must be
+     * between 0..n (should probably be k..n, because encoding < k is a NOP)
+     * 
+     * @param packetLength the packetLength in bytes.  All of the buffers
+     * in src and repair are assumed to be this long.
+     */
+    protected abstract void encode(byte[][] src, int[] srcOff, byte[][] repair,
+                                   int[] repairOff, int[] index, 
+                                   int packetLength);
+
+    /**
+     * This method takes an array of encoded packets and decodes them.  Before
+     * the packets are decoded, they are shuffled so that packets that are
+     * original source packets (index < k) are positioned so that their
+     * index within the byte[][] is the same as their packet index.  If the
+     * <code>shuffled</code> flag is set to true then it is assumed that
+     * the packets are already in the proper order.  If not then they will 
+     * have the references of the byte[]'s shuffled within the byte[][].  No
+     * data will be copied, only references swapped.  This means that if the
+     * byte[][] is wrapping an underlying byte[] then the shuffling proceedure
+     * may bring the byte[][] out of sync with the underlying data structure.
+     * From an SPI perspective this means that the implementation is expected
+     * to follow the exact same behavior as the shuffle() method in this class
+     * which means that you should simply call shuffle() if the flag is false.
+     *
+     * @param pkts An array of <code>k</code> byte[]'s that contain the repair
+     * packets to be decoded.  The decoding proceedure will copy the decoded
+     * data into the byte[]'s that are provided and will place them in order
+     * within the byte[][].  If the byte[][] is already properly shuffled
+     * then the byte[]'s will not be moved around in the byte[][].
+     *
+     * @param pktsOff An array of integers which specifies the offset of each
+     * each packet within its associated byte[].
+     * 
+     * @param index This int[] specifies the indexes of the packets to be
+     * decoded.  These indexes must be between 0..n
+     * 
+     * @param packetLength the packetLength in bytes.  All of the buffers
+     * in pkts are assumed to be this long.
+     */
+    protected abstract void decode(byte[][] pkts, int[] pktsOff,
+                                   int[] index, int packetLength, 
+                                   boolean shuffled);
+
+    /**
+     * This method takes an array of source packets and generates a number
+     * of repair packets from them.  This method could have taken in only
+     * one repair packet to be generated, but in many cases it is more
+     * efficient (and convenient) to encode multiple packets at once.  This
+     * is especially true of the NativeCode implementation where data must
+     * be copied and the Java->Native->Java transition is expensive.
+     *
+     * @param src An array of <code>k</code> Buffers that contain the source
+     * packets to be encoded.  Often these Buffers are actually references
+     * to a single byte[] that contains the entire source block.
+     *
+     * @param repair Much like src, variable points to a number of Buffers
+     * to which the encoded repair packets will be written.  This array should
+     * be the same length as index.
+     * 
+     * @param index This int[] specifies the indexes of the packets to be
+     * encoded and written to <code>repair</code>.  These indexes must be
+     * between 0..n (should probably be k..n, because encoding < k is a NOP)
+     * 
+     */
+    public void encode(Buffer[] src, Buffer[] repair, int[] index) {
+        byte[][] srcBufs = new byte[src.length][];
+        int[] srcOffs = new int[src.length];
+        byte[][] repairBufs = new byte[repair.length][];
+        int[] repairOffs = new int[repair.length];
+        for (int i=0;i<srcBufs.length;i++) {
+            srcBufs[i] = src[i].b;
+            srcOffs[i] = src[i].off;
+        }
+        for (int i=0;i<repairBufs.length;i++) {
+            repairBufs[i] = repair[i].b;
+            repairOffs[i] = repair[i].off;
+        }
+
+        encode(srcBufs,srcOffs,repairBufs,repairOffs,index,src[0].len);
+    }
+
+    /*
+    protected void checkArguments() {
+        if (index < 0 || index >= n) {
+            throw new IllegalArgumentException("Invalid index "+index+
+                                              " (max "+(n-1)+")");
+       }
+        if (buf.len != repair.len) {
+            throw new IllegalArgumentException
+                ("Source buffer and output buffer not same length");
+        }
+
+        if (pkts.length != k || index.length != k) {
+            throw new IllegalArgumentException("Must be exactly k packets "+
+                                               "and index entries.");
+        }
+        }*/
+
+    /**
+     * This method takes an array of encoded packets and decodes them.  Before
+     * the packets are decoded, they are shuffled so that packets that are
+     * original source packets (index < k) are positioned so that their
+     * index within the byte[][] is the same as their packet index. 
+     *
+     * We shuffle the packets using the copy mechanism to allow API users to 
+     * be guarenteed that the Buffer[] references will not be shuffled around.
+     * This allows the Buffer[] to wrap an underlying byte[], and once 
+     * decoding is complete the entire block will be in the proper order 
+     * in the underlying byte[].  If the packets are already in the proper
+     * position then no copying will take place.
+     *
+     * @param pkts An array of <code>k</code> Buffers that contain the repair
+     * packets to be decoded.  The decoding proceedure will copy the decoded
+     * data into the Buffers that are provided and will place them in order
+     * within the Buffer[].  If the Buffers are already properly shuffled
+     * then no data will be copied around during the shuffle proceedure.
+     *
+     * @param index This int[] specifies the indexes of the packets to be
+     * decoded.  These indexes must be between 0..n
+     * 
+     */
+    public void decode(Buffer[] pkts, int[] index) {
+        // Must pre-shuffle so that no future shuffles bring the byte[]'s
+        // out of sync with the Buffer[]'s.  We use copyShuffle so that 
+        // the Buffer[]'s don't have their references shuffled around and
+        // therefore we can have the Buffer[]'s wrapping one large byte[]
+        // that will be decoded with all of the data in order in that block.
+        copyShuffle(pkts,index,k);
+
+        byte[][] bufs = new byte[pkts.length][];
+        int[] offs = new int[pkts.length];
+        for (int i=0;i<bufs.length;i++) {
+            bufs[i] = pkts[i].b;
+            offs[i] = pkts[i].off;
+        }
+        decode(bufs,offs,index,pkts[0].len,true);
+    }
+
+    /**
+     * Move packets with index < k into their position.  This method
+     * copies the data using System.arraycopy rather than modifying the
+     * Buffer[].
+     */
+    protected static final void copyShuffle(Buffer[] pkts, int index[], int k){
+        byte[] b = null;
+        for (int i = 0;i < k ;) {
+            if (index[i] >= k || index[i] == i) {
+                i++;
+            } else {
+                // put pkts in the right position (first check for conflicts).
+                int c = index[i];
+                
+                if (index[c] == c) {
+                    throw new IllegalArgumentException
+                        ("Shuffle Error: Duplicate indexes at "+i);
+                }
+                // swap(index[c],index[i])
+                int tmp = index[i];
+                index[i] = index[c];
+                index[c] = tmp;
+
+                // swap(pkts[c],pkts[i])
+                if (b == null) {
+                    b = new byte[pkts[0].len];
+                }
+                System.arraycopy(pkts[i].b,pkts[i].off,b,0,b.length);
+                System.arraycopy(pkts[c].b,pkts[c].off,pkts[i].b,pkts[i].off,
+                                 b.length);
+                System.arraycopy(b,0,pkts[c].b,pkts[c].off,b.length);
+            }
+        }
+    }
+
+    /**
+     * shuffle move src packets in their position
+     */
+    protected static final void shuffle(byte[][] pkts, int[] pktsOff, 
+                                        int[] index, int k) {
+        for (int i=0; i<k;) {
+            if (index[i] >= k || index[i] == i) {
+                i++;
+            } else {
+                // put pkts in the right position (first check for conflicts).
+                int c = index[i] ;
+                
+                if (index[c] == c) {
+                    throw new IllegalArgumentException("Shuffle error at "+i);
+                }
+                // swap(pkts[c],pkts[i])
+                byte[] tmp = pkts[i];
+                pkts[i] = pkts[c];
+                pkts[c] = tmp;
+
+                // swap(pktsOff[c],pktsOff[i])
+                int tmp2 = pktsOff[i];
+                pktsOff[i] = pktsOff[c];
+                pktsOff[c] = tmp2;
+
+                // swap(index[c],index[i])
+                tmp2 = index[i];
+                index[i] = index[c];
+                index[c] = tmp2;
+            }
+        }
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/FECCodeFactory.java (from 
rev 26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/FECCodeFactory.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/FECCodeFactory.java             
                (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/FECCodeFactory.java     
2009-03-31 13:09:45 UTC (rev 26281)
@@ -0,0 +1,51 @@
+package com.onionnetworks.fec;
+
+/**
+ * This is the abstract class is subclassed in order to plug in new FEC 
+ * implementations.  If you wish to use the default implementation defined by 
+ * the property "com.onionnetworks.fec.defaultcodefactoryclass" you should 
+ * simply call:
+ *
+ * <code>
+ *   FECCodeFactory factory = FECCodeFactory.getDefault();
+ * </code>
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public abstract class FECCodeFactory {
+
+    protected static FECCodeFactory def;
+
+    protected FECCodeFactory() {}
+
+    /**
+     * @return An FECCode for the appropriate <code>k</code> and <code>n</code>
+     * values.
+     */
+    public abstract FECCode createFECCode(int k, int n);
+
+    /**
+     * @return The default FECCodeFactory which is defined by the property
+     * "com.onionnetworks.fec.defaultcodefactoryclass".  If this property is
+     * not defined then DefaultFECCodeFactory will be used by default.
+     */
+    public synchronized static FECCodeFactory getDefault() {
+        if (def == null) {
+            try {
+                Class clazz = Class.forName
+                    (System.getProperty
+                     ("com.onionnetworks.fec.defaultcodefactoryclass",
+                      "com.onionnetworks.fec.DefaultFECCodeFactory"));
+                def = (FECCodeFactory) clazz.newInstance();
+            } catch (Exception e) {
+                // krunky structure, but the easiest way to deal with the 
+                // exception.
+                def = new DefaultFECCodeFactory();
+            }
+        }
+        return def;
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/FECMath.java (from rev 
26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/FECMath.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/FECMath.java                    
        (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/FECMath.java    2009-03-31 
13:09:45 UTC (rev 26281)
@@ -0,0 +1,665 @@
+package com.onionnetworks.fec;
+
+import com.onionnetworks.util.Util;
+
+/**
+ * This class provides the majority of the logic for the pure Java 
+ * implementation of the vandermonde FEC codes.  This code is heavily derived
+ * from Luigi Rizzo's original C implementation.  Copyright information can
+ * be found in the 'LICENSE' file that comes with this distribution.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public class FECMath {
+    
+    /**
+     * The following parameter defines how many bits are used for
+     * field elements.  This probably only supports 8 and 16 bit codes
+     * at this time because Java lacks a typedef construct.  This code
+     * should perhaps be redone with some sort of template language/
+     * precompiler for Java.
+     */
+    
+    // code over GF(2**gfBits) - change to suit
+    public int gfBits;  
+    
+    /*
+     * You should not need to change anything beyond this point.
+     * The first part of the file implements linear algebra in GF.
+     *
+     * gf is the type used to store an element of the Galois Field.
+     * Must constain at least gfBits bits.
+     */
+    // 2^n-1 = the number of elements in this extension field
+    public int gfSize; // powers of alpha
+    
+    /**
+     * Primitive polynomials - see Lin & Costello, Appendix A,
+     * and  Lee & Messerschmitt, p. 453.
+     */
+    public static final String[] prim_polys = {    
+                                // gfBits      polynomial
+        null,                          //  0            no code
+        null,                   //  1            no code
+        "111",                         //  2            1+x+x^2
+        "1101",                        //  3            1+x+x^3
+        "11001",                       //  4            1+x+x^4
+        "101001",                      //  5            1+x^2+x^5
+        "1100001",                     //  6            1+x+x^6
+        "10010001",                    //  7            1 + x^3 + x^7
+        "101110001",            //  8            1+x^2+x^3+x^4+x^8
+        "1000100001",           //  9            1+x^4+x^9
+        "10010000001",          // 10            1+x^3+x^10
+        "101000000001",         // 11            1+x^2+x^11
+        "1100101000001",        // 12            1+x+x^4+x^6+x^12
+        "11011000000001",       // 13            1+x+x^3+x^4+x^13
+        "110000100010001",      // 14            1+x+x^6+x^10+x^14
+        "1100000000000001",     // 15            1+x+x^15
+        "11010000000010001"     // 16            1+x+x^3+x^12+x^16
+    };
+
+    
+    /**
+     * To speed up computations, we have tables for logarithm, exponent
+     * and inverse of a number. If gfBits <= 8, we use a table for
+     * multiplication as well (it takes 64K, no big deal even on a PDA,
+     * especially because it can be pre-initialized an put into a ROM!),
+     * otherwhise we use a table of logarithms.
+     */
+    
+    // index->poly form conversion table
+    public char[] gf_exp;
+    // Poly->index form conversion table
+    public int[] gf_log;
+    // inverse of field elem.
+    public char[] inverse;
+
+    // inv[\alpha**i]=\alpha**(gfSize-i-1)
+
+    /**
+     * gf_mul(x,y) multiplies two numbers. If gfBits<=8, it is much
+     * faster to use a multiplication table.
+     *
+     * USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying
+     * many numbers by the same constant. In this case the first
+     * call sets the constant, and others perform the multiplications.
+     * A value related to the multiplication is held in a local variable
+     * declared with USE_GF_MULC . See usage in addMul1().
+     */
+    public char[][] gf_mul_table;
+
+    public FECMath() {
+        this(8);
+    }
+
+    public FECMath(int gfBits) {
+        this.gfBits = gfBits;
+        this.gfSize = ((1 << gfBits) - 1);
+        
+        gf_exp = new char[2*gfSize];
+        gf_log = new int[gfSize+1];
+        inverse = new char[gfSize+1];
+
+        if (gfBits < 2 || gfBits > 16) {
+            throw new IllegalArgumentException("gfBits must be 2 .. 16");
+        }
+        generateGF();
+        if (gfBits <= 8) {
+            initMulTable();
+        }
+    }
+
+    public final void generateGF() {
+        int i;
+
+        String primPoly = prim_polys[gfBits];
+        
+        char mask = 1; // x ** 0 = 1
+        gf_exp[gfBits] = 0; // will be updated at the end of the 1st loop
+        /*
+         * first, generate the (polynomial representation of) powers of \alpha,
+         * which are stored in gf_exp[i] = \alpha ** i .
+         * At the same time build gf_log[gf_exp[i]] = i .
+         * The first gfBits powers are simply bits shifted to the left.
+         */
+        for (i = 0; i < gfBits; i++, mask <<= 1 ) {
+            gf_exp[i] = mask;
+            gf_log[gf_exp[i]] = i;
+            /*
+             * If primPoly[i] == 1 then \alpha ** i occurs in poly-repr
+             * gf_exp[gfBits] = \alpha ** gfBits
+             */
+            if (primPoly.charAt(i) == '1') {
+                gf_exp[gfBits] ^= mask;
+            }
+        }
+        /*
+         * now gf_exp[gfBits] = \alpha ** gfBits is complete, so can als
+         * compute its inverse.
+         */
+        gf_log[gf_exp[gfBits]] = gfBits;
+        /*
+         * Poly-repr of \alpha ** (i+1) is given by poly-repr of
+         * \alpha ** i shifted left one-bit and accounting for any
+         * \alpha ** gfBits term that may occur when poly-repr of
+         * \alpha ** i is shifted.
+         */
+        mask = (char) (1 << (gfBits - 1)) ;
+        for (i = gfBits + 1; i < gfSize; i++) {
+            if (gf_exp[i-1] >= mask) {
+                gf_exp[i] = (char) (gf_exp[gfBits] ^ 
+                                    ((gf_exp[i-1] ^ mask) << 1));
+            } else {
+                gf_exp[i] = (char) (gf_exp[i-1] << 1);
+            }
+            gf_log[gf_exp[i]] = i;
+        }
+        /*
+         * log(0) is not defined, so use a special value
+         */
+        gf_log[0] = gfSize;
+        // set the extended gf_exp values for fast multiply
+        for (i = 0 ; i < gfSize ; i++) {
+            gf_exp[i + gfSize] = gf_exp[i];
+        }
+        
+        /*
+         * again special cases. 0 has no inverse. This used to
+         * be initialized to gfSize, but it should make no difference
+         * since noone is supposed to read from here.
+         */
+        inverse[0] = 0 ;
+        inverse[1] = 1;
+        for (i=2; i<=gfSize; i++) {
+            inverse[i] = gf_exp[gfSize-gf_log[i]];
+        }
+    }
+    
+    public final void initMulTable() {
+        if (gfBits <= 8) {
+            gf_mul_table = new char[gfSize + 1][gfSize + 1];
+
+            int i, j;
+            for (i=0; i< gfSize+1; i++) {
+                for (j=0; j< gfSize+1; j++) {
+                    gf_mul_table[i][j] = gf_exp[modnn(gf_log[i] + gf_log[j])];
+                }
+            }
+            for (j=0; j< gfSize+1; j++) {
+                gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
+            }
+        }
+    }
+
+    /**
+     * modnn(x) computes x % gfSize, where gfSize is 2**gfBits - 1,
+     * without a slow divide.
+     */
+    public final char modnn(int x) {
+        while (x >= gfSize) {
+            x -= gfSize;
+            x = (x >> gfBits) + (x & gfSize);
+        }
+        return (char) x;
+    }
+
+    public final char mul(char x, char y) {
+        if (gfBits <= 8) {
+            return gf_mul_table[x][y];
+        } else {
+            if (x == 0 || y == 0) { 
+                return 0;
+            }
+     
+            return gf_exp[gf_log[x] + gf_log[y]] ;
+        }
+    }
+
+    /**
+     * Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
+     * Lookup tables:
+     *     index->polynomial form              gf_exp[] contains j= \alpha^i;
+     *     polynomial form -> index form       gf_log[ j = \alpha^i ] = i
+     * \alpha=x is the primitive element of GF(2^m)
+     *
+     * For efficiency, gf_exp[] has size 2*gfSize, so that a simple
+     * multiplication of two numbers can be resolved without calling modnn
+     */
+    public static final char[] createGFMatrix(int rows, int cols) {
+        return new char[rows * cols];
+    }
+    
+    /*
+     * addMul() computes dst[] = dst[] + c * src[]
+     * This is used often, so better optimize it! Currently the loop is
+     * unrolled 16 times, a good value for 486 and pentium-class machines.
+     * The case c=0 is also optimized, whereas c=1 is not. These
+     * calls are unfrequent in my typical apps so I did not bother.
+     * 
+     */
+    public final void addMul(char[] dst, int dstPos, char[] src, 
+                             int srcPos, char c, int len) {
+        // nop, optimize
+        if (c == 0) {
+            return;
+        }
+
+        int unroll = 16; // unroll the loop 16 times.
+        int i = dstPos;
+        int j = srcPos;
+        int lim = dstPos + len;
+
+        if (gfBits <= 8) { // use our multiplication table.
+            // Instead of doing gf_mul_table[c,x] for multiply, we'll save
+            // the gf_mul_table[c] to a local variable since it is going to
+            // be used many times.
+            char[] gf_mulc = gf_mul_table[c];
+            
+            // Not sure if loop unrolling has any real benefit in Java, but 
+            // what the hey.
+            for (;i < lim && (lim-i) > unroll; i += unroll, j += unroll) {
+                // dst ^= gf_mulc[x] is equal to mult then add (xor == add)
+                
+                dst[i] ^= gf_mulc[src[j]];
+                dst[i+1] ^= gf_mulc[src[j+1]];
+                dst[i+2] ^= gf_mulc[src[j+2]];
+                dst[i+3] ^= gf_mulc[src[j+3]];
+                dst[i+4] ^= gf_mulc[src[j+4]];
+                dst[i+5] ^= gf_mulc[src[j+5]];
+                dst[i+6] ^= gf_mulc[src[j+6]];
+                dst[i+7] ^= gf_mulc[src[j+7]];
+                dst[i+8] ^= gf_mulc[src[j+8]];
+                dst[i+9] ^= gf_mulc[src[j+9]];
+                dst[i+10] ^= gf_mulc[src[j+10]];
+                dst[i+11] ^= gf_mulc[src[j+11]];
+                dst[i+12] ^= gf_mulc[src[j+12]];
+                dst[i+13] ^= gf_mulc[src[j+13]];
+                dst[i+14] ^= gf_mulc[src[j+14]];
+                dst[i+15] ^= gf_mulc[src[j+15]];
+            }
+            
+            // final components
+            for (;i < lim; i++, j++) {
+                dst[i] ^= gf_mulc[src[j]];
+            }
+
+        } else { // gfBits > 8, no multiplication table
+            int mulcPos = gf_log[c];
+
+            // unroll your own damn loop.
+            int y;
+            for (;i < lim;i++,j++) {
+                if ((y=src[j]) != 0) {
+                    dst[i] ^= gf_exp[mulcPos+gf_log[y]];
+                }
+            }
+        }
+    }
+
+    /*
+     * addMul() computes dst[] = dst[] + c * src[]
+     * This is used often, so better optimize it! Currently the loop is
+     * unrolled 16 times, a good value for 486 and pentium-class machines.
+     * The case c=0 is also optimized, whereas c=1 is not. These
+     * calls are unfrequent in my typical apps so I did not bother.
+     * 
+     */
+    public final void addMul(byte[] dst, int dstPos, byte[] src, 
+                             int srcPos, byte c, int len) {
+        // nop, optimize
+        if (c == 0) {
+            return;
+        }
+
+        int unroll = 16; // unroll the loop 16 times.
+        int i = dstPos;
+        int j = srcPos;
+        int lim = dstPos + len;
+
+        // use our multiplication table.
+        // Instead of doing gf_mul_table[c,x] for multiply, we'll save
+        // the gf_mul_table[c] to a local variable since it is going to
+        // be used many times.
+        char[] gf_mulc = gf_mul_table[c & 0xff];
+        
+        // Not sure if loop unrolling has any real benefit in Java, but 
+        // what the hey.
+        for (;i < lim && (lim-i) > unroll; i += unroll, j += unroll) {
+            // dst ^= gf_mulc[x] is equal to mult then add (xor == add)
+            
+            dst[i] ^= gf_mulc[src[j] & 0xff];
+            dst[i+1] ^= gf_mulc[src[j+1] & 0xff];
+            dst[i+2] ^= gf_mulc[src[j+2] & 0xff];
+            dst[i+3] ^= gf_mulc[src[j+3] & 0xff];
+            dst[i+4] ^= gf_mulc[src[j+4] & 0xff];
+            dst[i+5] ^= gf_mulc[src[j+5] & 0xff];
+            dst[i+6] ^= gf_mulc[src[j+6] & 0xff];
+            dst[i+7] ^= gf_mulc[src[j+7] & 0xff];
+            dst[i+8] ^= gf_mulc[src[j+8] & 0xff];
+            dst[i+9] ^= gf_mulc[src[j+9] & 0xff];
+            dst[i+10] ^= gf_mulc[src[j+10] & 0xff];
+            dst[i+11] ^= gf_mulc[src[j+11] & 0xff];
+            dst[i+12] ^= gf_mulc[src[j+12] & 0xff];
+            dst[i+13] ^= gf_mulc[src[j+13] & 0xff];
+            dst[i+14] ^= gf_mulc[src[j+14] & 0xff];
+            dst[i+15] ^= gf_mulc[src[j+15] & 0xff];
+        }
+        
+        // final components
+        for (;i < lim; i++, j++) {
+            dst[i] ^= gf_mulc[src[j] & 0xff];
+        }
+    }
+
+    /*
+     * computes C = AB where A is n*k, B is k*m, C is n*m
+     */
+    public final void matMul(char[] a, char[] b, char[] c, 
+                             int n, int k, int m) {
+       matMul(a,0,b,0,c,0,n,k,m);
+    }
+
+    /*
+     * computes C = AB where A is n*k, B is k*m, C is n*m
+     */
+    public final void matMul(char[] a, int aStart, char[] b, int bStart,
+                                   char[] c, int cStart, int n, int k, int m){
+
+        for (int row = 0; row < n ; row++) {
+            for (int col = 0; col < m ; col++) {
+                int posA = row * k;
+                int posB = col;
+                char acc = 0 ;
+                for (int i = 0; i < k ; i++, posA++, posB += m) {
+                    acc ^= mul(a[aStart+posA],b[bStart+posB]);
+                }
+                c[cStart+(row * m + col)] = acc ;
+            }
+        }
+    }
+    
+    /*
+     * Checks to see if the square matrix is identiy
+     * @return whether it is an identity matrix or not
+     */
+    public static final boolean isIdentity(char[] m, int k) {
+        int pos = 0;
+        for (int row=0; row<k; row++) {
+            for (int col=0; col<k; col++) {
+                if ((row==col && m[pos] != 1) || 
+                    (row!=col && m[pos] != 0)) {
+                    return false;
+                } else {
+                    pos++ ;
+                }
+            }
+        }
+        return true;
+    }
+    
+    
+    /*
+     * invertMatrix() takes a matrix and produces its inverse
+     * k is the size of the matrix.
+     * (Gauss-Jordan, adapted from Numerical Recipes in C)
+     * Return non-zero if singular.
+     */
+    public final void invertMatrix(char[] src, int k) 
+        throws IllegalArgumentException {
+        
+        int[] indxc = new int[k];
+        int[] indxr = new int[k];
+
+        // ipiv marks elements already used as pivots.
+        int[] ipiv = new int[k];
+
+        char[] id_row = createGFMatrix(1, k);
+        char[] temp_row = createGFMatrix(1, k);
+        
+        for (int col = 0; col < k ; col++) {
+            /*
+             * Zeroing column 'col', look for a non-zero element.
+             * First try on the diagonal, if it fails, look elsewhere.
+             */
+            int irow = -1;
+            int icol = -1;
+            boolean foundPiv = false;
+
+            if (ipiv[col] != 1 && src[col*k + col] != 0) {
+                irow = col ;
+                icol = col ;
+                foundPiv = true;
+            }
+            if (!foundPiv) {
+            loop1: for (int row = 0 ; row < k ; row++) {
+                if (ipiv[row] != 1) {
+                    for (int ix = 0 ; ix < k ; ix++) {
+                        if (ipiv[ix] == 0) {
+                            if (src[row*k + ix] != 0) {
+                                irow = row ;
+                                icol = ix ;
+                                foundPiv = true;
+                                break loop1;
+                            }
+                        } else if (ipiv[ix] > 1) {
+                            throw new IllegalArgumentException
+                                ("singular matrix");
+                        }
+                    }
+                }
+            }
+            }
+
+            // redundant??? I'm too lazy to figure it out -Justin
+            if (!foundPiv && icol == -1) { 
+                throw new IllegalArgumentException("XXX pivot not found!");
+            }
+
+            // Ok, we've found a pivot by this point, so we can set the 
+            // foundPiv variable back to false.  The reason that this is
+            // so shittily laid out is that the original code had goto's :(
+            foundPiv = false;
+
+            ipiv[icol] = ipiv[icol] + 1;
+            /*
+             * swap rows irow and icol, so afterwards the diagonal
+             * element will be correct. Rarely done, not worth
+             * optimizing.
+             */
+            if (irow != icol) {
+                for (int ix = 0 ; ix < k ; ix++ ) {
+                    // swap 'em
+                    char tmp = src[irow*k + ix];
+                    src[irow*k + ix] = src[icol*k + ix];
+                    src[icol*k + ix] = tmp;
+                }
+            }
+            indxr[col] = irow;
+            indxc[col] = icol;
+
+            int pivotRowPos = icol*k;
+            char c = src[pivotRowPos + icol];
+            if (c == 0) {
+                throw new IllegalArgumentException("singular matrix 2");
+            }
+            if (c != 1) { /* otherwhise this is a NOP */
+                /*
+                 * this is done often , but optimizing is not so
+                 * fruitful, at least in the obvious ways (unrolling)
+                 */
+                c = inverse[c];
+                src[pivotRowPos+icol] = 1;
+                for (int ix = 0 ; ix < k ; ix++ ) {
+                    src[pivotRowPos+ix] = mul(c, src[pivotRowPos+ix]);
+                }
+            }
+            /*
+             * from all rows, remove multiples of the selected row
+             * to zero the relevant entry (in fact, the entry is not zero
+             * because we know it must be zero).
+             * (Here, if we know that the pivotRowPos is the identity,
+             * we can optimize the addMul).
+             */
+            id_row[icol] = 1;
+            if (!Util.arraysEqual(src,pivotRowPos,id_row,0,k)) {
+                for (int p = 0, ix = 0 ; ix < k ; ix++, p += k) {
+                    if (ix != icol) {
+                        c = src[p+icol];
+                        src[p+icol] = 0;
+                        addMul(src,p,src,pivotRowPos, c, k);
+                    }
+                }
+            }
+            id_row[icol] = 0;
+        } // done all columns
+        
+        for (int col = k-1 ; col >= 0 ; col--) {
+            if (indxr[col] <0 || indxr[col] >= k) {
+                System.err.println("AARGH, indxr[col] "+indxr[col]);
+            } else if (indxc[col] <0 || indxc[col] >= k) {
+                System.err.println("AARGH, indxc[col] "+indxc[col]);
+            } else {
+                if (indxr[col] != indxc[col] ) {
+                    for (int row = 0 ; row < k ; row++ ) {
+                        // swap 'em
+                        char tmp = src[row*k + indxc[col]];
+                        src[row*k + indxc[col]] = src[row*k + indxr[col]];
+                        src[row*k + indxr[col]] = tmp;
+                    }
+                }
+            }
+        }
+    }
+    
+    /*
+     * fast code for inverting a vandermonde matrix.
+     * XXX NOTE: It assumes that the matrix
+     * is not singular and _IS_ a vandermonde matrix. Only uses
+     * the second column of the matrix, containing the p_i's.
+     *
+     * Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but
+     * largely revised for my purposes.
+     * p = coefficients of the matrix (p_i)
+     * q = values of the polynomial (known)
+     */
+    
+    public final void invertVandermonde(char[] src, int k) {
+
+        if (k == 1) {  // degenerate case, matrix must be p^0 = 1
+            return;
+        }
+        
+        /*
+         * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1
+         * b holds the coefficient for the matrix inversion
+         */
+        char[] c = createGFMatrix(1, k);
+        char[] b = createGFMatrix(1, k);
+        char[] p = createGFMatrix(1, k);
+        
+        for (int j=1,i=0; i < k ; i++, j+=k) {
+            c[i] = 0;
+            p[i] = src[j];    /* p[i] */
+        }
+        /*
+         * construct coeffs. recursively. We know c[k] = 1 (implicit)
+         * and start P_0 = x - p_0, then at each stage multiply by
+         * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1}
+         * After k steps we are done.
+         */
+        c[k-1] = p[0]; /* really -p(0), but x = -x in GF(2^m) */
+        for (int i = 1 ; i < k ; i++) {
+            char p_i = p[i]; /* see above comment */
+            for (int j = k-1  - ( i - 1 ) ; j < k-1 ; j++ ) {
+                c[j] ^= mul( p_i, c[j+1] );
+            }
+            c[k-1] ^= p_i;
+        }
+        
+        for (int row = 0 ; row < k ; row++ ) {
+            /*
+             * synthetic division etc.
+             */
+            char xx = p[row] ;
+            char t = 1 ;
+            b[k-1] = 1 ; /* this is in fact c[k] */
+            for (int i = k-2 ; i >= 0 ; i-- ) {
+                b[i] = (char) (c[i+1] ^ mul(xx, b[i+1])) ;
+                t = (char) (mul(xx, t) ^ b[i]) ;
+            }
+            for (int col = 0 ; col < k ; col++ ) {
+                src[col*k + row] = mul(inverse[t], b[col]);
+            }
+        }
+    }
+
+    public final char[] createEncodeMatrix(int k, int n) {
+        if (k > gfSize + 1 || n > gfSize + 1 || 
+           k > n ) {
+            throw new IllegalArgumentException
+               ("Invalid parameters n="+n+",k="+k+",gfSize="+
+                gfSize);
+        }
+
+
+        char[] encMatrix = createGFMatrix(n,k);
+       
+       /*
+        * The encoding matrix is computed starting with a Vandermonde matrix,
+        * and then transforming it into a systematic matrix.
+        *
+         * fill the matrix with powers of field elements, starting from 0.
+         * The first row is special, cannot be computed with exp. table.
+         */
+        char[] tmpMatrix = createGFMatrix(n, k);
+
+        tmpMatrix[0] = 1;
+       // first row should be 0's, fill in the rest.
+       for (int pos = k, row = 0; row < n-1 ; row++, pos += k) {
+            for (int col = 0 ; col < k ; col ++ ) {
+                tmpMatrix[pos+col] = gf_exp[modnn
+                                           (row*col)];
+           }
+        }
+        
+        /*
+         * quick code to build systematic matrix: invert the top
+         * k*k vandermonde matrix, multiply right the bottom n-k rows
+         * by the inverse, and construct the identity matrix at the top.
+         */
+        // much faster than invertMatrix 
+        invertVandermonde(tmpMatrix, k); 
+        matMul(tmpMatrix,k*k, tmpMatrix,0,encMatrix,k*k, n - k, 
+                           k, k);
+
+        /*
+         * the upper matrix is I so do not bother with a slow multiply
+         */
+        Util.bzero(encMatrix, 0, k*k);
+        for (int i = 0, col = 0; col < k ; col++, i += k+1 ) {
+            encMatrix[i] = 1;
+       }
+        
+        return encMatrix;
+    }
+
+    /**
+     * createDecodeMatrix constructs the encoding matrix given the
+     * indexes.
+     */
+    protected final char[] createDecodeMatrix(char[] encMatrix, int[] index,
+                                              int k, int n) {
+        
+        char[] matrix = createGFMatrix(k, k);
+        for (int i = 0, pos = 0; i < k ; i++, pos += k) {
+            System.arraycopy(encMatrix,index[i]*k,matrix,pos,k);
+        }
+        
+        invertMatrix(matrix, k);
+        
+        return matrix;
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/Native16Code.java (from rev 
26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/Native16Code.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/Native16Code.java               
                (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/Native16Code.java       
2009-03-31 13:09:45 UTC (rev 26281)
@@ -0,0 +1,79 @@
+package com.onionnetworks.fec;
+
+//import java.security.AccessController;
+//import sun.security.action.*;
+import com.onionnetworks.util.*;
+
+/**
+ * This class is the frontend for the JNI wrapper for the C implementation of
+ * the FEC Codes.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public class Native16Code extends FECCode {
+    
+    // One must be very very careful not to let code escape, it stores the
+    // memory address of a fec_parms struct and if modified could give an
+    // attacker the ability to point to anything in memory.
+    private final long code;
+    
+    static {
+        String path = NativeDeployer.getLibraryPath
+            (Native8Code.class.getClassLoader(),"fec16");
+        if (path != null) {
+            System.load(path);
+        } else {
+            System.out.println("Unable to find native library for fec16 for 
platform "+NativeDeployer.OS_ARCH);
+            System.out.println(path);
+        }
+    }
+    
+    public Native16Code(int k, int n) {
+        super(k,n);
+        code = nativeNewFEC(k,n);
+    }
+
+    protected void encode(byte[][] src, int[] srcOff, byte[][] repair, 
+                          int[] repairOff, int[] index, int packetLength) {
+        
+        if (packetLength % 2 != 0) {
+            throw new IllegalArgumentException("For 16 bit codes, buffers "+
+                                               "must be 16 bit aligned.");
+        }
+        nativeEncode(code,src,srcOff,index,repair,repairOff,k,packetLength);
+    }
+
+    protected void decode(byte[][] pkts, int[] pktsOff,
+                          int[] index, int packetLength, boolean inOrder) {
+        if (packetLength % 2 != 0) {
+            throw new IllegalArgumentException("For 16 bit codes, buffers "+
+                                               "must be 16 bit aligned.");
+        }
+        if (!inOrder) {
+            shuffle(pkts,pktsOff,index,k);
+        }
+        nativeDecode(code,pkts,pktsOff,index,k,packetLength);
+    }
+
+    protected native void nativeEncode
+        (long code, byte[][] src, int[] srcOff, int[] index, byte[][] repair, 
+         int[] repairOff, int k, int packetLength);
+
+    protected native void nativeDecode(long code, byte[][] pkts, int[] pktsOff,
+                                       int[] index, int k, int packetLength);
+
+    protected synchronized native long nativeNewFEC(int k, int n);
+
+    protected synchronized native void nativeFreeFEC(long code);
+
+    protected void finalize() throws Throwable {
+        nativeFreeFEC(code);
+    }
+
+    public String toString() {
+        return new String("Native16Code[k="+k+",n="+n+"]");
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/Native8Code.java (from rev 
26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/Native8Code.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/Native8Code.java                
                (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/Native8Code.java        
2009-03-31 13:09:45 UTC (rev 26281)
@@ -0,0 +1,73 @@
+package com.onionnetworks.fec;
+
+//import java.security.AccessController;
+//import sun.security.action.*;
+import com.onionnetworks.util.*;
+
+/**
+ * This class is the frontend for the JNI wrapper for the C implementation of
+ * the FEC Codes.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public class Native8Code extends FECCode {
+    
+    // One must be very very careful not to let code escape, it stores the
+    // memory address of a fec_parms struct and if modified could give an
+    // attacker the ability to point to anything in memory.
+    private final long code;
+    
+    static {
+        String path = NativeDeployer.getLibraryPath
+            (Native8Code.class.getClassLoader(),"fec8");
+        if (path != null) {
+            System.load(path);
+        } else {
+            System.out.println("Unable to find native library for fec8 for 
platform "+NativeDeployer.OS_ARCH);
+           System.out.println(path);
+        }
+    }
+    
+    public Native8Code(int k, int n) {
+        super(k,n);
+        code = nativeNewFEC(k,n);
+    }
+
+    protected void encode(byte[][] src, int[] srcOff, byte[][] repair, 
+                          int[] repairOff, int[] index, int packetLength) {
+        
+        nativeEncode(code,src,srcOff,index,repair,repairOff,k,packetLength);
+    }
+
+    protected void decode(byte[][] pkts, int[] pktsOff,
+                          int[] index, int packetLength, boolean inOrder) {
+        // We need to shuffle at this point so that the Java byte[][] stays
+        // in sync with what happens in native land.
+        if (!inOrder) {
+            shuffle(pkts,pktsOff,index,k);
+        }
+        nativeDecode(code,pkts,pktsOff,index,k,packetLength);
+    }
+
+    protected native void nativeEncode
+        (long code, byte[][] src, int[] srcOff, int[] index, byte[][] repair, 
+         int[] repairOff, int k, int packetLength);
+
+    protected native void nativeDecode(long code, byte[][] pkts, int[] pktsOff,
+                                       int[] index, int k, int packetLength);
+
+    protected synchronized native long nativeNewFEC(int k, int n);
+
+    protected synchronized native void nativeFreeFEC(long code);
+
+    protected void finalize() throws Throwable {
+        nativeFreeFEC(code);
+    }
+
+    public String toString() {
+        return new String("Native8Code[k="+k+",n="+n+"]");
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/Pure16Code.java (from rev 
26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/Pure16Code.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/Pure16Code.java                 
        (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/Pure16Code.java 2009-03-31 
13:09:45 UTC (rev 26281)
@@ -0,0 +1,134 @@
+package com.onionnetworks.fec;
+
+import com.onionnetworks.util.Util;
+import com.onionnetworks.util.Buffer;
+/**
+ * This class, along with FECMath, provides the implementation of the pure
+ * Java 16 bit FEC codes.  This is heavily dervied from Luigi Rizzos original
+ * C implementation.  See the file "LICENSE" along with this distribution for
+ * additional copyright information.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public class Pure16Code extends PureCode {
+
+    protected static final FECMath fecMath = new FECMath(16);
+
+
+    /** Notes about large N support:
+        you can just generate the top k*k vandermonde matrix, call it V,
+        then invert it, then when you have k blocks generate a matrix M
+        with the k rows you need <r_i> and E = M* V^{-1} is the encoding matrix
+        for the systematic code which you then need to invert to perform
+        the decoding. Probably there is a fast way to invert E given that M
+        is also a vandermonde matrix so it is "easy" to compute M^{-1}
+    */
+
+    public Pure16Code(int k, int n) {
+        super(k,n,fecMath.createEncodeMatrix(k,n));
+    }
+
+    /**
+     * encode accepts as input pointers to n data packets of size sz,
+     * and produces as output a packet pointed to by fec, computed
+     * with index "index".
+     */
+    protected void encode(byte[][] src, int[] srcOff, byte[][] repair, 
+                          int[] repairOff, int[] index, int packetLength) {
+        if (packetLength % 2 != 0) {
+            throw new IllegalArgumentException("For 16 bit codes, buffers "+
+                                               "must be 16 bit aligned.");
+        }
+        char[][] srcChars = new char[src.length][];
+        int[] srcCharsOff = new int[src.length];
+        int numChars = packetLength/2;
+        char[] repairChars = new char[numChars];
+        for (int i=0;i<srcChars.length;i++) {
+            srcChars[i] = new char[numChars];
+            Util.arraycopy(src[i], srcOff[i], srcChars[i], 0, packetLength);
+            srcCharsOff[i] = 0;
+        }
+
+        for (int i=0;i<repair.length;i++) {
+            if (index[i] < k) { // < k, systematic so direct copy.
+                System.arraycopy(src[index[i]],srcOff[index[i]],repair[i],
+                                 repairOff[i], packetLength);
+            } else {
+                encode(srcChars,srcCharsOff,repairChars,0,index[i],numChars);
+                Util.arraycopy(repairChars,0,repair[i],repairOff[i],
+                               packetLength);
+            }
+        }
+    }
+
+    /**
+     * ASSERT: index >= k && index < n
+     */
+    protected void encode(char[][] src, int[] srcOff, char[] repair, 
+                          int repairOff, int index, int numChars) {
+        int pos = index*k;
+        Util.bzero(repair,repairOff,numChars);
+        for (int i=0; i<k ; i++) {
+            fecMath.addMul(repair,repairOff,src[i],srcOff[i],
+                           encMatrix[pos+i],numChars);
+        }
+    }
+    
+    protected void decode(byte[][] pkts, int[] pktsOff, int[] index, 
+                          int packetLength, boolean inOrder) {          
+        if (packetLength % 2 != 0) {
+            throw new IllegalArgumentException("For 16 bit codes, buffers "+
+                                               "must be 16 bit aligned.");
+        }
+
+        if (!inOrder) {
+            shuffle(pkts, pktsOff, index, k);
+        }
+
+        char[][] pktsChars = new char[pkts.length][];
+        int[] pktsCharsOff = new int[pkts.length];
+        int numChars = packetLength/2;
+        for (int i=0;i<pktsChars.length;i++) {
+            pktsChars[i] = new char[numChars];
+            Util.arraycopy(pkts[i], pktsOff[i], pktsChars[i], 0, packetLength);
+            pktsCharsOff[i] = 0;
+        }
+
+        char[][] result = decode(pktsChars, pktsCharsOff, index, numChars);
+
+        for (int i=0;i<result.length;i++) {
+            if (result[i] != null) {
+                Util.arraycopy(result[i], 0, pkts[i], pktsOff[i], 
+                               packetLength);
+                index[i] = i;
+            }
+        }
+    }
+
+    protected char[][] decode(char[][] pkts, int[] pktsOff, int[] index, 
+                          int numChars) {
+
+        char[] decMatrix = fecMath.createDecodeMatrix(encMatrix,index,k,n);
+        
+        // do the actual decoding
+        char[][] tmpPkts = new char[k][];
+        for (int row=0; row<k; row++) {
+            if (index[row] >= k) {
+                tmpPkts[row] = new char[numChars];
+                for (int col=0 ; col<k ; col++) {
+                    fecMath.addMul(tmpPkts[row],0,pkts[col],pktsOff[col], 
+                                   decMatrix[row*k + col], numChars);
+                }
+            }
+        }
+
+        return tmpPkts;
+    }
+    
+    public String toString() {
+        return new String("Pure16Code[k="+k+",n="+n+"]");
+    }
+}

Copied: trunk/contrib/fec/src/com/onionnetworks/fec/PureCode.java (from rev 
26280, trunk/contrib/fec/fec_src/com/onionnetworks/fec/PureCode.java)
===================================================================
--- trunk/contrib/fec/src/com/onionnetworks/fec/PureCode.java                   
        (rev 0)
+++ trunk/contrib/fec/src/com/onionnetworks/fec/PureCode.java   2009-03-31 
13:09:45 UTC (rev 26281)
@@ -0,0 +1,99 @@
+package com.onionnetworks.fec;
+
+import com.onionnetworks.util.Util;
+import com.onionnetworks.util.Buffer;
+/**
+ * This class, along with FECMath, provides the implementation of the pure
+ * Java 8 bit FEC codes.  This is heavily dervied from Luigi Rizzos original
+ * C implementation.  See the file "LICENSE" along with this distribution for
+ * additional copyright information.
+ *
+ * (c) Copyright 2001 Onion Networks
+ * (c) Copyright 2000 OpenCola
+ *
+ * @author Justin F. Chapweske (justin at chapweske.com)
+ */
+public class PureCode extends FECCode {
+
+    // Keeping this around because it amuses me.
+    public static final int FEC_MAGIC = 0xFECC0DEC;
+    protected static final FECMath fecMath = new FECMath(8);
+    protected char[] encMatrix;
+    
+    //create a new encoder. This contains n,k and the encoding matrix.
+    public PureCode(int k, int n) {
+        this(k,n,fecMath.createEncodeMatrix(k,n));
+    }
+
+    public PureCode(int k, int n, char[] encMatrix) {
+        super(k,n);
+        this.encMatrix = encMatrix;
+    }
+
+    /**
+     * encode accepts as input pointers to n data packets of size sz,
+     * and produces as output a packet pointed to by fec, computed
+     * with index "index".
+     */
+    protected void encode(byte[][] src, int[] srcOff, byte[][] repair, 
+                          int[] repairOff, int[] index, int packetLength) {
+        for (int i=0;i<repair.length;i++) {
+            encode(src,srcOff,repair[i],repairOff[i],index[i],packetLength);
+        }
+    }
+
+    protected void encode(byte[][] src, int[] srcOff, byte[] repair, 
+                          int repairOff, int index, int packetLength) {
+        // *remember* indices start at 0, k starts at 1.
+        if (index < k) { // < k, systematic so direct copy.
+            System.arraycopy(src[index],srcOff[index],repair,repairOff,
+                             packetLength);
+        } else { // index >= k && index < n
+            int pos = index*k;
+            Util.bzero(repair,repairOff,packetLength);
+            for (int i=0; i<k ; i++) {
+                fecMath.addMul(repair,repairOff,src[i],srcOff[i],
+                                   (byte) encMatrix[pos+i],packetLength);
+            }
+        } 
+    }
+    
+    protected void decode(byte[][] pkts, int[] pktsOff, int[] index, 
+                          int packetLength, boolean shuffled) {                
+        // This may be the second time shuffle has been called, if so
+        // this is ok because it will quickly determine that things are in
+        // order.  The previous shuffles may have been necessary to keep
+        // another data structure in sync with the byte[]'s
+        if (!shuffled) {
+            shuffle(pkts, pktsOff, index, k);
+        }
+
+        char[] decMatrix = fecMath.createDecodeMatrix(encMatrix,index,k,n);
+        
+        // do the actual decoding..
+        byte[][] tmpPkts = new byte[k][];
+        for (int row=0; row<k; row++) {
+            if (index[row] >= k) {
+                tmpPkts[row] = new byte[packetLength];
+                for (int col=0 ; col<k ; col++) {
+                    fecMath.addMul(tmpPkts[row],0,pkts[col],pktsOff[col], 
+                                   (byte) decMatrix[row*k + col],
+                                   packetLength);
+                }
+            }
+        }
+
+        // move pkts to their final destination
+        for (int row=0;row < k;row++) {
+            if (index[row] >= k) { // only copy those actually decoded.
+                System.arraycopy(tmpPkts[row],0, pkts[row],pktsOff[row],
+                                 packetLength);
+                index[row] = row;
+            }
+        }
+    }
+    
+    public String toString() {
+        return new String("PureCode[k="+k+",n="+n+"]");
+    }
+}

Modified: trunk/contrib/freenet_ext/build.xml
===================================================================
--- trunk/contrib/freenet_ext/build.xml 2009-03-31 12:36:13 UTC (rev 26280)
+++ trunk/contrib/freenet_ext/build.xml 2009-03-31 13:09:45 UTC (rev 26281)
@@ -27,15 +27,13 @@

        <target name="fec" depends="fec-common" description="build the 
fecencoder/decoder plugins for fproxy.">
                <javac destdir="${build}" optimize="on" 
source="${javac.target.version}">
-                       <src path="../fec/fec_src"/>
+                       <src path="../fec/src"/>
                        <classpath path="../fec/common/lib/onion-common.jar"/>
+                       <exclude name="csrc/*.java"/>
                </javac>

                <copy file="../fec/onion_LICENSE" todir="${build}"/>
                <copy todir="${build}">
-                       <fileset dir="../fec/fec_src">
-                               <include name="**/*.properties"/>
-                       </fileset>
                        <fileset dir="../fec/">
                                <include name="lib/"/>
                        </fileset>


Reply via email to