2 #include "ByteBuffer.h"
7 #include "LastMessage.h"
10 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, Array<char> *_prevhmac, Array<char> *_hmac, int64_t _localSequenceNumber) :
14 machineid(_machineid),
15 entries(new Vector<Entry *>()),
18 freespace(SLOT_SIZE - getBaseSize()),
20 localSequenceNumber(_localSequenceNumber) {
23 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, Array<char> *_prevhmac, int64_t _localSequenceNumber) :
27 machineid(_machineid),
28 entries(new Vector<Entry *>()),
31 freespace(SLOT_SIZE - getBaseSize()),
33 localSequenceNumber(_localSequenceNumber) {
36 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, int64_t _localSequenceNumber) :
38 prevhmac(new Array<char>(HMAC_SIZE)),
40 machineid(_machineid),
41 entries(new Vector<Entry *>()),
44 freespace(SLOT_SIZE - getBaseSize()),
46 localSequenceNumber(_localSequenceNumber) {
49 Entry *Slot::addEntry(Entry *e) {
53 freespace -= e->getSize();
57 void Slot::addShallowEntry(Entry *e) {
60 freespace -= e->getSize();
64 * Returns true if the slot has free space to hold the entry without
65 * using its reserved space. */
67 bool Slot::hasSpace(Entry *e) {
68 int newfreespace = freespace - e->getSize();
69 return newfreespace >= 0;
72 Vector<Entry *> *Slot::getEntries() {
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();
80 ByteBuffer *bb = ByteBuffer_wrap(array);
81 Array<char> *hmac = new Array<char>(HMAC_SIZE);
82 Array<char> *prevhmac = new Array<char>(HMAC_SIZE);
85 if (!realmac->equals(hmac))
86 throw new Error("Server Error: Invalid HMAC! Potential Attack!");
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);
93 for (int i = 0; i < numentries; i++) {
94 slot->addShallowEntry(Entry_decode(slot, bb));
100 char Slot::getType() {
104 Array<char> *Slot::encode(Mac *mac) {
105 Array<char> *array = new Array<char>(SLOT_SIZE);
106 ByteBuffer *bb = ByteBuffer_wrap(array);
107 /* Leave space for the slot HMAC. */
108 bb->position(HMAC_SIZE);
111 bb->putLong(machineid);
112 bb->putInt(entries->size());
113 for (uint ei = 0; ei < entries->size(); ei++) {
114 Entry *entry = entries->get(ei);
117 /* Compute our HMAC */
118 mac->update(array, HMAC_SIZE, array->length() - HMAC_SIZE);
119 Array<char> *realmac = mac->doFinal();
128 * Returns the live set of entries for this Slot. Generates a fake
129 * LastMessage entry to represent the information stored by the slot
133 Vector<Entry *> *Slot::getLiveEntries(bool resize) {
134 Vector<Entry *> *liveEntries = new Vector<Entry *>();
135 for (uint ei = 0; ei < entries->size(); ei++) {
136 Entry *entry = entries->get(ei);
137 if (entry->isLive()) {
138 if (!resize || entry->getType() != TypeTableStatus)
139 liveEntries->add(entry);
143 if (seqnumlive && !resize)
144 liveEntries->add(new LastMessage(this, machineid, seqnum));
151 * Records that a newer slot records the fact that this slot was
152 * sent by the relevant machine.
155 void Slot::setDead() {
157 decrementLiveCount();
161 * Update the count of live entries.
164 void Slot::decrementLiveCount() {
166 if (livecount == 0) {
167 table->decrementLiveCount();
171 Array<char> *Slot::getSlotCryptIV() {
172 ByteBuffer *buffer = ByteBuffer_allocate(CloudComm_IV_SIZE);
173 buffer->putLong(machineid);
174 int64_t localSequenceNumberShift = localSequenceNumber << 16;
175 buffer->putLong(localSequenceNumberShift);
176 return buffer->array();