add makefile
[iotcloud.git] / src / java / iotcloud / Slot.java
index 33a8908d5b004627f07a10133024b420e0fb6b49..045259015c59d3f2a280300e81ca7031ddf7c476 100644 (file)
 package iotcloud;
 import java.util.Vector;
+import java.nio.ByteBuffer;
+import javax.crypto.Mac;
+import java.util.Arrays;
 
-class Slot {
-       long seqnum;
-       byte[] bytes;
-       Vector<Entry> entries;
+class Slot implements Liveness {
+       static final int SLOT_SIZE=2048;
+       static final int HMAC_SIZE=32;
 
-       Slot() {
-               entries=new Vector();
+       private long seqnum;
+       private byte[] prevhmac;
+       private byte[] hmac;
+       private long machineid;
+       private Vector<Entry> entries;
+       private int livecount;
+       
+       Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
+               seqnum=_seqnum;
+               machineid=_machineid;
+               prevhmac=_prevhmac;
+               hmac=_hmac;
+               entries=new Vector<Entry>();
+               livecount=1;
        }
        
        Slot(long _seqnum, byte[] _bytes) {
-               this();
                seqnum=_seqnum;
-               bytes=_bytes;
+       }
+
+       byte[] getHMAC() {
+               return hmac;
+       }
+
+       byte[] getPrevHMAC() {
+               return prevhmac;
+       }
+
+       void addEntry(Entry e) {
+               entries.add(e);
+               livecount++;
+       }
+       
+       Vector<Entry> getEntries() {
+               return entries;
+       }
+       
+       static Slot decode(byte[] array, Mac mac) {
+               mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
+               byte[] realmac=mac.doFinal();
+
+               ByteBuffer bb=ByteBuffer.wrap(array);
+               byte[] hmac=new byte[HMAC_SIZE];
+               byte[] prevhmac=new byte[HMAC_SIZE];
+               bb.get(hmac);
+               bb.get(prevhmac);
+               if (!Arrays.equals(realmac, hmac))
+                       throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
+
+               long seqnum=bb.getLong();
+               long machineid=bb.getLong();
+               int numentries=bb.getInt();
+               Slot slot=new Slot(seqnum, machineid, prevhmac, hmac);
+               
+               for(int i=0;i<numentries;i++) {
+                       slot.addEntry(Entry.decode(slot, bb));
+               }
+               
+               return slot;
+       }
+
+       byte[] encode(Mac mac) {
+               byte[] array=new byte[SLOT_SIZE];
+               ByteBuffer bb=ByteBuffer.wrap(array);
+               bb.position(HMAC_SIZE); //Leave space for the HMACs
+               bb.put(prevhmac);
+               bb.putLong(seqnum);
+               bb.putLong(machineid);
+               bb.putInt(entries.size());
+               for(Entry entry:entries) {
+                       entry.encode(bb);
+               }
+               //Compute our HMAC
+               mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
+               byte[] realmac=mac.doFinal();
+               bb.position(0);
+               bb.put(realmac);
+               return array;
        }
        
        long getSequenceNumber() {
                return seqnum;
        }
 
+       long getMachineID() {
+               return machineid;
+       }
+       
        byte[] getBytes() {
-               return bytes;
+               return null;
+       }
+
+       void decrementLiveCount() {
+               livecount--;
        }
        
+       boolean isLive() {
+               return livecount > 0;
+       }
+
        public String toString() {
                return "<"+getSequenceNumber()+", "+new String(getBytes())+">";
        }