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