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