edits
[iotcloud.git] / version2 / src / C / Slot.cc
1 #include "Slot.h"
2
3 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, char *_prevhmac, char *_hmac, int64_t _localSequenceNumber) {
4         seqnum = _seqnum;
5         machineid = _machineid;
6         prevhmac = _prevhmac;
7         hmac = _hmac;
8         entries = new Vector<Entry *>();
9         livecount = 1;
10         seqnumlive = true;
11         freespace = SLOT_SIZE - getBaseSize();
12         table = _table;
13         localSequenceNumber = _localSequenceNumber;
14 }
15
16 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, char *_prevhmac, int64_t _localSequenceNumber) {
17         this(_table, _seqnum, _machineid, _prevhmac, NULL, _localSequenceNumber);
18 }
19
20 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, int64_t _localSequenceNumber) {
21         this(_table, _seqnum, _machineid, new char[HMAC_SIZE], NULL, _localSequenceNumber);
22 }
23
24 Entry *Slot::addEntry(Entry *e) {
25         e = e->getCopy(this);
26         entries->add(e);
27         livecount++;
28         freespace -= e->getSize();
29         return e;
30 }
31
32 void Slot::removeEntry(Entry *e) {
33         entries->remove(e);
34         livecount--;
35         freespace += e->getSize();
36 }
37
38 void Slot::addShallowEntry(Entry *e) {
39         entries->add(e);
40         livecount++;
41         freespace -= e->getSize();
42 }
43
44 /**
45  * Returns true if the slot has free space to hold the entry without
46  * using its reserved space. */
47
48 bool Slot::hasSpace(Entry *e) {
49         int newfreespace = freespace - e->getSize();
50         return newfreespace >= 0;
51 }
52
53 Vector<Entry *> *Slot::getEntries() {
54         return entries;
55 }
56
57 Slot *Slotdecode(Table *table, char *array, Mac *mac) {
58         mac->update(array, HMAC_SIZE, array.length - HMAC_SIZE);
59         char *realmac = mac->doFinal();
60
61         ByteBuffer *bb = ByteBuffer_wrap(array);
62         char *hmac = new char[HMAC_SIZE];
63         char *prevhmac = new char[HMAC_SIZE];
64         bb->get(hmac);
65         bb->get(prevhmac);
66         if (!Arrays.equals(realmac, hmac))
67                 throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
68
69         int64_t seqnum = bb->getLong();
70         int64_t machineid = bb->getLong();
71         int numentries = bb->getInt();
72         Slot slot = new Slot(table, seqnum, machineid, prevhmac, hmac, -1);
73
74         for (int i = 0; i < numentries; i++) {
75                 slot->addShallowEntry(Entry->decode(slot, bb));
76         }
77
78         return slot;
79 }
80
81 char *Slot::encode(Mac * mac) {
82         char *array = new char[SLOT_SIZE];
83         ByteBuffer *bb = ByteBuffer_wrap(array);
84         /* Leave space for the slot HMAC.  */
85         bb->position(HMAC_SIZE);
86         bb->put(prevhmac);
87         bb->putLong(seqnum);
88         bb->putLong(machineid);
89         bb->putInt(entries->size());
90         for (Entry entry : entries) {
91                 entry->encode(bb);
92         }
93         /* Compute our HMAC */
94         mac->update(array, HMAC_SIZE, array.length - HMAC_SIZE);
95         char *realmac = mac->doFinal();
96         hmac = realmac;
97         bb->position(0);
98         bb->put(realmac);
99         return array;
100 }
101
102
103 /**
104  * Returns the live set of entries for this Slot.  Generates a fake
105  * LastMessage entry to represent the information stored by the slot
106  * itself.
107  */
108
109 Vector<Entry *> *Slot::getLiveEntries(bool resize) {
110         Vector<Entry *> *liveEntries = new Vector<Entry *>();
111         for (Entry *entry : entries) {
112                 if (entry->isLive()) {
113                         if (!resize || entry->getType() != Entry->TypeTableStatus)
114                                 liveEntries->add(entry);
115                 }
116         }
117
118         if (seqnumlive && !resize)
119                 liveEntries->add(new LastMessage(this, machineid, seqnum));
120
121         return liveEntries;
122 }
123
124
125 /**
126  * Records that a newer slot records the fact that this slot was
127  * sent by the relevant machine.
128  */
129
130 void Slot::setDead() {
131         seqnumlive = false;
132         decrementLiveCount();
133 }
134
135 /**
136  * Update the count of live entries.
137  */
138
139 void Slot::decrementLiveCount() {
140         livecount--;
141         if (livecount == 0) {
142                 table->decrementLiveCount();
143         }
144 }
145
146 char *Slot::getSlotCryptIV() {
147         ByteBuffer *buffer = ByteBuffer_allocate(CloudComm.IV_SIZE);
148         buffer->putLong(machineid);
149         int64_t localSequenceNumberShift = localSequenceNumber << 16;
150         buffer->putLong(localSequenceNumberShift);
151         return buffer->array();
152 }