2 import java.util.Vector;
3 import java.nio.ByteBuffer;
4 import javax.crypto.Mac;
5 import java.util.Arrays;
8 * Data structuring for holding Slot information.
13 class Slot implements Liveness {
14 /** Sets the slot size. */
15 static final int SLOT_SIZE = 2048;
16 /** Sets the size for the HMAC. */
17 static final int HMAC_SIZE = 32;
19 /** Sequence number of the slot. */
21 /** HMAC of previous slot. */
22 private byte[] prevhmac;
23 /** HMAC of this slot. */
25 /** Machine that sent this slot. */
26 private long machineid;
27 /** Vector of entries in this slot. */
28 private Vector<Entry> entries;
29 /** Pieces of information that are live. */
30 private int livecount;
31 /** Flag that indicates whether this slot is still live for
32 * recording the machine that sent it. */
33 private boolean seqnumlive;
34 /** Number of bytes of free space. */
35 private int freespace;
36 /** Reference to Table */
39 private long localSequenceNumber;
41 Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac, long _localSequenceNumber) {
43 machineid = _machineid;
46 entries = new Vector<Entry>();
49 freespace = SLOT_SIZE - getBaseSize();
51 localSequenceNumber = _localSequenceNumber;
54 Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac, long _localSequenceNumber) {
55 this(_table, _seqnum, _machineid, _prevhmac, null, _localSequenceNumber);
58 Slot(Table _table, long _seqnum, long _machineid, long _localSequenceNumber) {
59 this(_table, _seqnum, _machineid, new byte[HMAC_SIZE], null, _localSequenceNumber);
66 byte[] getPrevHMAC() {
70 Entry addEntry(Entry e) {
74 freespace -= e.getSize();
78 void removeEntry(Entry e) {
81 freespace += e.getSize();
84 private void addShallowEntry(Entry e) {
87 freespace -= e.getSize();
91 * Returns true if the slot has free space to hold the entry without
92 * using its reserved space. */
94 boolean hasSpace(Entry e) {
95 int newfreespace = freespace - e.getSize();
96 return newfreespace >= 0;
99 Vector<Entry> getEntries() {
103 static Slot decode(Table table, byte[] array, Mac mac) {
104 mac.update(array, HMAC_SIZE, array.length - HMAC_SIZE);
105 byte[] realmac = mac.doFinal();
107 ByteBuffer bb = ByteBuffer.wrap(array);
108 byte[] hmac = new byte[HMAC_SIZE];
109 byte[] prevhmac = new byte[HMAC_SIZE];
112 if (!Arrays.equals(realmac, hmac))
113 throw new Error("Server Error: Invalid HMAC! Potential Attack!");
115 long seqnum = bb.getLong();
116 long machineid = bb.getLong();
117 int numentries = bb.getInt();
118 Slot slot = new Slot(table, seqnum, machineid, prevhmac, hmac, -1);
120 for (int i = 0; i < numentries; i++) {
121 slot.addShallowEntry(Entry.decode(slot, bb));
127 byte[] encode(Mac mac) {
128 byte[] array = new byte[SLOT_SIZE];
129 ByteBuffer bb = ByteBuffer.wrap(array);
130 /* Leave space for the slot HMAC. */
131 bb.position(HMAC_SIZE);
134 bb.putLong(machineid);
135 bb.putInt(entries.size());
136 for (Entry entry : entries) {
139 /* Compute our HMAC */
140 mac.update(array, HMAC_SIZE, array.length - HMAC_SIZE);
141 byte[] realmac = mac.doFinal();
149 * Returns the empty size of a Slot. Includes 2 HMACs, the machine
150 * identifier, the sequence number, and the number of entries.
153 //return 2 * HMAC_SIZE + 2 * Long.BYTES + Integer.BYTES;
154 return 2 * HMAC_SIZE + 2 * Long.SIZE/8 + Integer.SIZE/8;
158 * Returns the live set of entries for this Slot. Generates a fake
159 * LastMessage entry to represent the information stored by the slot
163 Vector<Entry> getLiveEntries(boolean resize) {
164 Vector<Entry> liveEntries = new Vector<Entry>();
165 for (Entry entry : entries) {
166 if (entry.isLive()) {
167 if (!resize || entry.getType() != Entry.TypeTableStatus)
168 liveEntries.add(entry);
172 if (seqnumlive && !resize)
173 liveEntries.add(new LastMessage(this, machineid, seqnum));
179 * Returns the sequence number of the slot.
182 long getSequenceNumber() {
187 * Returns the machine that sent this slot.
190 long getMachineID() {
195 * Records that a newer slot records the fact that this slot was
196 * sent by the relevant machine.
201 decrementLiveCount();
205 * Update the count of live entries.
208 void decrementLiveCount() {
210 if (livecount == 0) {
211 table.decrementLiveCount();
216 * Returns whether the slot stores any live information.
220 return livecount > 0;
223 public byte[] getSlotCryptIV() {
224 ByteBuffer buffer = ByteBuffer.allocate(CloudComm.IV_SIZE);
225 buffer.putLong(machineid);
226 long localSequenceNumberShift = localSequenceNumber << 16;
227 buffer.putLong(localSequenceNumberShift);
228 return buffer.array();
231 public String toString() {
232 return "<" + getSequenceNumber() + ">";