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