Deleted Redundent Files
[iotcloud.git] / src / 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         Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
40                 seqnum=_seqnum;
41                 machineid=_machineid;
42                 prevhmac=_prevhmac;
43                 hmac=_hmac;
44                 entries=new Vector<Entry>();
45                 livecount=1;
46                 seqnumlive=true;
47                 freespace = SLOT_SIZE - getBaseSize();
48                 table=_table;
49         }
50
51         Slot(Table _table, long _seqnum, long _machineid, byte[] _prevhmac) {
52                 this(_table, _seqnum, _machineid, _prevhmac, null);
53         }
54
55         Slot(Table _table, long _seqnum, long _machineid) {
56                 this(_table, _seqnum, _machineid, new byte[HMAC_SIZE], null);
57         }
58
59         byte[] getHMAC() {
60                 return hmac;
61         }
62
63         byte[] getPrevHMAC() {
64                 return prevhmac;
65         }
66
67         void addEntry(Entry e) {
68                 e=e.getCopy(this);
69                 entries.add(e);
70                 livecount++;
71                 freespace -= e.getSize();
72         }
73
74         private void addShallowEntry(Entry e) {
75                 entries.add(e);
76                 livecount++;
77                 freespace -= e.getSize();
78         }
79
80         /**
81          * Returns true if the slot has free space to hold the entry without
82          * using its reserved space. */
83
84         boolean hasSpace(Entry e) {
85                 int newfreespace = freespace - e.getSize();
86                 return newfreespace >= 0;
87         }
88
89         Vector<Entry> getEntries() {
90                 return entries;
91         }
92
93         static Slot decode(Table table, byte[] array, Mac mac) {
94                 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
95                 byte[] realmac=mac.doFinal();
96
97                 ByteBuffer bb=ByteBuffer.wrap(array);
98                 byte[] hmac=new byte[HMAC_SIZE];
99                 byte[] prevhmac=new byte[HMAC_SIZE];
100                 bb.get(hmac);
101                 bb.get(prevhmac);
102                 if (!Arrays.equals(realmac, hmac))
103                         throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
104
105                 long seqnum=bb.getLong();
106                 long machineid=bb.getLong();
107                 int numentries=bb.getInt();
108                 Slot slot=new Slot(table, seqnum, machineid, prevhmac, hmac);
109
110                 for(int i=0; i<numentries; i++) {
111                         slot.addShallowEntry(Entry.decode(slot, bb));
112                 }
113
114                 return slot;
115         }
116
117         byte[] encode(Mac mac) {
118                 byte[] array=new byte[SLOT_SIZE];
119                 ByteBuffer bb=ByteBuffer.wrap(array);
120                 /* Leave space for the slot HMAC.  */
121                 bb.position(HMAC_SIZE);
122                 bb.put(prevhmac);
123                 bb.putLong(seqnum);
124                 bb.putLong(machineid);
125                 bb.putInt(entries.size());
126                 for(Entry entry:entries) {
127                         entry.encode(bb);
128                 }
129                 /* Compute our HMAC */
130                 mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
131                 byte[] realmac=mac.doFinal();
132                 hmac = realmac;
133                 bb.position(0);
134                 bb.put(realmac);
135                 return array;
136         }
137
138         /**
139          * Returns the empty size of a Slot. Includes 2 HMACs, the machine
140          * identifier, the sequence number, and the number of entries.
141          */
142         int getBaseSize() {
143                 return 2*HMAC_SIZE+2*Long.BYTES+Integer.BYTES;
144         }
145
146         /**
147          * Returns the live set of entries for this Slot.  Generates a fake
148          * LastMessage entry to represent the information stored by the slot
149          * itself.
150          */
151
152         Vector<Entry> getLiveEntries(boolean resize) {
153                 Vector<Entry> liveEntries=new Vector<Entry>();
154                 for(Entry entry: entries) {
155                         if (entry.isLive()) {
156                                 if (!resize || entry.getType() != Entry.TypeTableStatus)
157                                         liveEntries.add(entry);
158                         }
159                 }
160                         
161                 if (seqnumlive && !resize)
162                         liveEntries.add(new LastMessage(this, machineid, seqnum));
163
164                 return liveEntries;
165         }
166
167         /**
168          * Returns the sequence number of the slot.
169          */
170
171         long getSequenceNumber() {
172                 return seqnum;
173         }
174
175         /**
176          * Returns the machine that sent this slot.
177          */
178
179         long getMachineID() {
180                 return machineid;
181         }
182
183         /**
184          * Records that a newer slot records the fact that this slot was
185          * sent by the relevant machine.
186          */
187
188         void setDead() {
189                 seqnumlive=false;
190                 decrementLiveCount();
191         }
192
193         /**
194          * Update the count of live entries.
195          */
196
197         void decrementLiveCount() {
198                 livecount--;
199                 if (livecount==0)
200                         table.decrementLiveCount();
201         }
202
203         /**
204          * Returns whether the slot stores any live information.
205          */
206
207         boolean isLive() {
208                 return livecount > 0;
209         }
210
211         public String toString() {
212                 return "<"+getSequenceNumber()+">";
213         }
214 }