Another file
[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::removeEntry(Entry *e) {
58         entries->remove(e);
59         livecount--;
60         freespace += e->getSize();
61 }
62
63 void Slot::addShallowEntry(Entry *e) {
64         entries->add(e);
65         livecount++;
66         freespace -= e->getSize();
67 }
68
69 /**
70  * Returns true if the slot has free space to hold the entry without
71  * using its reserved space. */
72
73 bool Slot::hasSpace(Entry *e) {
74         int newfreespace = freespace - e->getSize();
75         return newfreespace >= 0;
76 }
77
78 Vector<Entry *> *Slot::getEntries() {
79         return entries;
80 }
81
82 Slot *Slot_decode(Table *table, Array<char> *array, Mac *mac) {
83         mac->update(array, HMAC_SIZE, array->length() - HMAC_SIZE);
84         Array<char> *realmac = mac->doFinal();
85
86         ByteBuffer *bb = ByteBuffer_wrap(array);
87         Array<char> *hmac = new Array<char>(HMAC_SIZE);
88         Array<char> *prevhmac = new Array<char>(HMAC_SIZE);
89         bb->get(hmac);
90         bb->get(prevhmac);
91         if (!realmac->equals(hmac))
92                 throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
93
94         int64_t seqnum = bb->getLong();
95         int64_t machineid = bb->getLong();
96         int numentries = bb->getInt();
97         Slot *slot = new Slot(table, seqnum, machineid, prevhmac, hmac, -1);
98
99         for (int i = 0; i < numentries; i++) {
100                 slot->addShallowEntry(Entry_decode(slot, bb));
101         }
102
103         return slot;
104 }
105
106 Array<char> *Slot::encode(Mac *mac) {
107         Array<char> *array = new Array<char>(SLOT_SIZE);
108         ByteBuffer *bb = ByteBuffer_wrap(array);
109         /* Leave space for the slot HMAC.  */
110         bb->position(HMAC_SIZE);
111         bb->put(prevhmac);
112         bb->putLong(seqnum);
113         bb->putLong(machineid);
114         bb->putInt(entries->size());
115         for (uint ei = 0; ei < entries->size(); ei++) {
116                 Entry *entry = entries->get(ei);
117                 entry->encode(bb);
118         }
119         /* Compute our HMAC */
120         mac->update(array, HMAC_SIZE, array->length() - HMAC_SIZE);
121         Array<char> *realmac = mac->doFinal();
122         hmac = realmac;
123         bb->position(0);
124         bb->put(realmac);
125         return array;
126 }
127
128
129 /**
130  * Returns the live set of entries for this Slot.  Generates a fake
131  * LastMessage entry to represent the information stored by the slot
132  * itself.
133  */
134
135 Vector<Entry *> *Slot::getLiveEntries(bool resize) {
136         Vector<Entry *> *liveEntries = new Vector<Entry *>();
137         for (uint ei = 0; ei < entries->size(); ei++) {
138                 Entry *entry = entries->get(ei);
139                 if (entry->isLive()) {
140                         if (!resize || entry->getType() != TypeTableStatus)
141                                 liveEntries->add(entry);
142                 }
143         }
144
145         if (seqnumlive && !resize)
146                 liveEntries->add(new LastMessage(this, machineid, seqnum));
147
148         return liveEntries;
149 }
150
151
152 /**
153  * Records that a newer slot records the fact that this slot was
154  * sent by the relevant machine.
155  */
156
157 void Slot::setDead() {
158         seqnumlive = false;
159         decrementLiveCount();
160 }
161
162 /**
163  * Update the count of live entries.
164  */
165
166 void Slot::decrementLiveCount() {
167         livecount--;
168         if (livecount == 0) {
169                 table->decrementLiveCount();
170         }
171 }
172
173 Array<char> *Slot::getSlotCryptIV() {
174         ByteBuffer *buffer = ByteBuffer_allocate(CloudComm_IV_SIZE);
175         buffer->putLong(machineid);
176         int64_t localSequenceNumberShift = localSequenceNumber << 16;
177         buffer->putLong(localSequenceNumberShift);
178         return buffer->array();
179 }