2 import java.util.Vector;
3 import java.nio.ByteBuffer;
4 import javax.crypto.Mac;
5 import java.util.Arrays;
7 class Slot implements Liveness {
8 static final int SLOT_SIZE=2048;
9 static final int RESERVED_SPACE=64;
10 static final int HMAC_SIZE=32;
13 private byte[] prevhmac;
15 private long machineid;
16 private Vector<Entry> entries;
17 private int livecount;
18 private boolean seqnumlive;
19 private int freespace;
21 Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
26 entries=new Vector<Entry>();
29 freespace = SLOT_SIZE - getBaseSize();
32 Slot(long _seqnum, long _machineid, byte[] _prevhmac) {
33 this(_seqnum, _machineid, _prevhmac, new byte[HMAC_SIZE]);
36 Slot(long _seqnum, long _machineid) {
37 this(_seqnum, _machineid, new byte[HMAC_SIZE], new byte[HMAC_SIZE]);
44 byte[] getPrevHMAC() {
48 void addEntry(Entry e) {
51 freespace -= e.getSize();
54 boolean hasSpace(Entry e) {
55 int newfreespace = freespace - e.getSize();
56 return newfreespace > RESERVED_SPACE;
59 boolean canFit(Entry e) {
60 int newfreespace = freespace - e.getSize();
61 return newfreespace >= 0;
64 Vector<Entry> getEntries() {
68 static Slot decode(byte[] array, Mac mac) {
69 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
70 byte[] realmac=mac.doFinal();
72 ByteBuffer bb=ByteBuffer.wrap(array);
73 byte[] hmac=new byte[HMAC_SIZE];
74 byte[] prevhmac=new byte[HMAC_SIZE];
77 if (!Arrays.equals(realmac, hmac))
78 throw new Error("Server Error: Invalid HMAC! Potential Attack!");
80 long seqnum=bb.getLong();
81 long machineid=bb.getLong();
82 int numentries=bb.getInt();
83 Slot slot=new Slot(seqnum, machineid, prevhmac, hmac);
85 for(int i=0; i<numentries; i++) {
86 slot.addEntry(Entry.decode(slot, bb));
92 byte[] encode(Mac mac) {
93 byte[] array=new byte[SLOT_SIZE];
94 ByteBuffer bb=ByteBuffer.wrap(array);
95 bb.position(HMAC_SIZE); //Leave space for the HMACs
98 bb.putLong(machineid);
99 bb.putInt(entries.size());
100 for(Entry entry:entries) {
104 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
105 byte[] realmac=mac.doFinal();
112 return 2*HMAC_SIZE+2*Long.BYTES+Integer.BYTES;
115 Vector<Entry> getLiveEntries() {
116 Vector<Entry> liveEntries=new Vector<Entry>();
117 for(Entry entry: entries)
119 liveEntries.add(entry);
122 liveEntries.add(new LastMessage(this, machineid, seqnum));
127 long getSequenceNumber() {
131 long getMachineID() {
140 decrementLiveCount();
144 void decrementLiveCount() {
149 return livecount > 0;
152 public String toString() {
153 return "<"+getSequenceNumber()+", "+new String(getBytes())+">";