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