Adding config file for sharing.
[iot2.git] / benchmarks / other / PhoneInterface / Control / app / src / main / java / iotcloud / Slot.java
1 package iotcloud;
2 import java.util.Vector;
3 import java.nio.ByteBuffer;
4 import javax.crypto.Mac;
5 import java.util.Arrays;
6
7 /**
8  * Data structuring for holding Slot information.
9  * @author Brian Demsky
10  * @version 1.0
11  */
12
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;
18
19         /** Sequence number of the slot. */
20         private long seqnum;
21         /** HMAC of previous slot. */
22         private byte[] prevhmac;
23         /** HMAC of this slot. */
24         private byte[] hmac;
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 */
37         private Table table;
38
39         private long localSequenceNumber;
40
41         Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac, long _localSequenceNumber) {
42                 seqnum = _seqnum;
43                 machineid = _machineid;
44                 prevhmac = _prevhmac;
45                 hmac = _hmac;
46                 entries = new Vector<Entry>();
47                 livecount = 1;
48                 seqnumlive = true;
49                 freespace = SLOT_SIZE - getBaseSize();
50                 table = _table;
51                 localSequenceNumber = _localSequenceNumber;
52         }
53
54         Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac, long _localSequenceNumber) {
55                 this(_table, _seqnum, _machineid, _prevhmac, null, _localSequenceNumber);
56         }
57
58         Slot(Table _table, long _seqnum, long _machineid, long _localSequenceNumber) {
59                 this(_table, _seqnum, _machineid, new byte[HMAC_SIZE], null, _localSequenceNumber);
60         }
61
62         byte[] getHMAC() {
63                 return hmac;
64         }
65
66         byte[] getPrevHMAC() {
67                 return prevhmac;
68         }
69
70         Entry addEntry(Entry e) {
71                 e = e.getCopy(this);
72                 entries.add(e);
73                 livecount++;
74                 freespace -= e.getSize();
75                 return e;
76         }
77
78         void removeEntry(Entry e) {
79                 entries.remove(e);
80                 livecount--;
81                 freespace += e.getSize();
82         }
83
84         private void addShallowEntry(Entry e) {
85                 entries.add(e);
86                 livecount++;
87                 freespace -= e.getSize();
88         }
89
90         /**
91          * Returns true if the slot has free space to hold the entry without
92          * using its reserved space. */
93
94         boolean hasSpace(Entry e) {
95                 int newfreespace = freespace - e.getSize();
96                 return newfreespace >= 0;
97         }
98
99         Vector<Entry> getEntries() {
100                 return entries;
101         }
102
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();
106
107                 ByteBuffer bb = ByteBuffer.wrap(array);
108                 byte[] hmac = new byte[HMAC_SIZE];
109                 byte[] prevhmac = new byte[HMAC_SIZE];
110                 bb.get(hmac);
111                 bb.get(prevhmac);
112                 if (!Arrays.equals(realmac, hmac))
113                         throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
114
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);
119
120                 for (int i = 0; i < numentries; i++) {
121                         slot.addShallowEntry(Entry.decode(slot, bb));
122                 }
123
124                 return slot;
125         }
126
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);
132                 bb.put(prevhmac);
133                 bb.putLong(seqnum);
134                 bb.putLong(machineid);
135                 bb.putInt(entries.size());
136                 for (Entry entry : entries) {
137                         entry.encode(bb);
138                 }
139                 /* Compute our HMAC */
140                 mac.update(array, HMAC_SIZE, array.length - HMAC_SIZE);
141                 byte[] realmac = mac.doFinal();
142                 hmac = realmac;
143                 bb.position(0);
144                 bb.put(realmac);
145                 return array;
146         }
147
148         /**
149          * Returns the empty size of a Slot. Includes 2 HMACs, the machine
150          * identifier, the sequence number, and the number of entries.
151          */
152         int getBaseSize() {
153                 //return 2 * HMAC_SIZE + 2 * Long.BYTES + Integer.BYTES;
154                 return 2 * HMAC_SIZE + 2 * Long.SIZE/8 + Integer.SIZE/8;
155         }
156
157         /**
158          * Returns the live set of entries for this Slot.  Generates a fake
159          * LastMessage entry to represent the information stored by the slot
160          * itself.
161          */
162
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);
169                         }
170                 }
171
172                 if (seqnumlive && !resize)
173                         liveEntries.add(new LastMessage(this, machineid, seqnum));
174
175                 return liveEntries;
176         }
177
178         /**
179          * Returns the sequence number of the slot.
180          */
181
182         long getSequenceNumber() {
183                 return seqnum;
184         }
185
186         /**
187          * Returns the machine that sent this slot.
188          */
189
190         long getMachineID() {
191                 return machineid;
192         }
193
194         /**
195          * Records that a newer slot records the fact that this slot was
196          * sent by the relevant machine.
197          */
198
199         void setDead() {
200                 seqnumlive = false;
201                 decrementLiveCount();
202         }
203
204         /**
205          * Update the count of live entries.
206          */
207
208         void decrementLiveCount() {
209                 livecount--;
210                 if (livecount == 0) {
211                         table.decrementLiveCount();
212                 }
213         }
214
215         /**
216          * Returns whether the slot stores any live information.
217          */
218
219         boolean isLive() {
220                 return livecount > 0;
221         }
222
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();
229         }
230
231         public String toString() {
232                 return "<" + getSequenceNumber() + ">";
233         }
234 }