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