edits
[iotcloud.git] / version2 / src / C / Slot.cpp
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 MyVector<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 MyVector<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 MyVector<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 MyVector<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                 myerror("Server Error: Invalid HMAC!  Potential Attack!\n");
102         delete realmac;
103         
104         int64_t seqnum = bb->getLong();
105         int64_t machineid = bb->getLong();
106         int numentries = bb->getInt();
107         Slot *slot = new Slot(table, seqnum, machineid, prevhmac, hmac, -1);
108
109         for (int i = 0; i < numentries; i++) {
110                 slot->addShallowEntry(Entry_decode(slot, bb));
111         }
112         bb->releaseArray();
113         delete bb;
114         return slot;
115 }
116
117 char Slot::getType() {
118         return TypeSlot;
119 }
120
121 Array<char> *Slot::encode(Mac *mac) {
122         Array<char> *array = new Array<char>(SLOT_SIZE);
123         ByteBuffer *bb = ByteBuffer_wrap(array);
124         /* Leave space for the slot HMAC.  */
125         bb->position(HMAC_SIZE);
126         bb->put(prevhmac);
127         bb->putLong(seqnum);
128         bb->putLong(machineid);
129         bb->putInt(entries->size());
130         for (uint ei = 0; ei < entries->size(); ei++) {
131                 Entry *entry = entries->get(ei);
132                 entry->encode(bb);
133         }
134         /* Compute our HMAC */
135         mac->update(array, HMAC_SIZE, array->length() - HMAC_SIZE);
136         Array<char> *realmac = mac->doFinal();
137         hmac = realmac;
138         bb->position(0);
139         bb->put(realmac);
140         bb->releaseArray();
141         delete bb;
142         return array;
143 }
144
145
146 /**
147  * Returns the live set of entries for this Slot.  Generates a fake
148  * LastMessage entry to represent the information stored by the slot
149  * itself.
150  */
151
152 MyVector<Entry *> *Slot::getLiveEntries(bool resize) {
153         MyVector<Entry *> *liveEntries = new MyVector<Entry *>();
154         for (uint ei = 0; ei < entries->size(); ei++) {
155                 Entry *entry = entries->get(ei);
156                 if (entry->isLive()) {
157                         if (!resize || entry->getType() != TypeTableStatus)
158                                 liveEntries->add(entry);
159                 }
160         }
161
162         if (seqnumlive && !resize) {
163                 if (! fakeLastMessage)
164                         fakeLastMessage = new LastMessage(this, machineid, seqnum);
165                 liveEntries->add(fakeLastMessage);
166         }
167         return liveEntries;
168 }
169
170
171 /**
172  * Records that a newer slot records the fact that this slot was
173  * sent by the relevant machine.
174  */
175
176 void Slot::setDead() {
177         seqnumlive = false;
178         decrementLiveCount();
179 }
180
181 /**
182  * Update the count of live entries.
183  */
184
185 void Slot::decrementLiveCount() {
186         livecount--;
187         if (livecount == 0) {
188                 table->decrementLiveCount();
189         }
190 }
191
192 Array<char> *Slot::getSlotCryptIV() {
193         ByteBuffer *buffer = ByteBuffer_allocate(CloudComm_IV_SIZE);
194         buffer->putLong(machineid);
195         int64_t localSequenceNumberShift = localSequenceNumber << 16;
196         buffer->putLong(localSequenceNumberShift);
197         Array<char> * array = buffer->array();
198         buffer->releaseArray();
199         delete buffer;
200         return array;
201 }