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 #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         bb->releaseArray();
97         delete bb;
98         return slot;
99 }
100
101 char Slot::getType() {
102         return TypeSlot;
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 (uint ei = 0; ei < entries->size(); ei++) {
115                 Entry *entry = entries->get(ei);
116                 entry->encode(bb);
117         }
118         /* Compute our HMAC */
119         mac->update(array, HMAC_SIZE, array->length() - HMAC_SIZE);
120         Array<char> *realmac = mac->doFinal();
121         hmac = realmac;
122         bb->position(0);
123         bb->put(realmac);
124         bb->releaseArray();
125         delete bb;
126         return array;
127 }
128
129
130 /**
131  * Returns the live set of entries for this Slot.  Generates a fake
132  * LastMessage entry to represent the information stored by the slot
133  * itself.
134  */
135
136 Vector<Entry *> *Slot::getLiveEntries(bool resize) {
137         Vector<Entry *> *liveEntries = new Vector<Entry *>();
138         for (uint ei = 0; ei < entries->size(); ei++) {
139                 Entry *entry = entries->get(ei);
140                 if (entry->isLive()) {
141                         if (!resize || entry->getType() != TypeTableStatus)
142                                 liveEntries->add(entry);
143                 }
144         }
145
146         if (seqnumlive && !resize)
147                 liveEntries->add(new LastMessage(this, machineid, seqnum));
148
149         return liveEntries;
150 }
151
152
153 /**
154  * Records that a newer slot records the fact that this slot was
155  * sent by the relevant machine.
156  */
157
158 void Slot::setDead() {
159         seqnumlive = false;
160         decrementLiveCount();
161 }
162
163 /**
164  * Update the count of live entries.
165  */
166
167 void Slot::decrementLiveCount() {
168         livecount--;
169         if (livecount == 0) {
170                 table->decrementLiveCount();
171         }
172 }
173
174 Array<char> *Slot::getSlotCryptIV() {
175         ByteBuffer *buffer = ByteBuffer_allocate(CloudComm_IV_SIZE);
176         buffer->putLong(machineid);
177         int64_t localSequenceNumberShift = localSequenceNumber << 16;
178         buffer->putLong(localSequenceNumberShift);
179         return buffer->array();
180 }