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));
101 char Slot::getType() {
105 Array<char> *Slot::encode(Mac *mac) {
106 Array<char> *array = new Array<char>(SLOT_SIZE);
107 ByteBuffer *bb = ByteBuffer_wrap(array);
108 /* Leave space for the slot HMAC. */
109 bb->position(HMAC_SIZE);
112 bb->putLong(machineid);
113 bb->putInt(entries->size());
114 for (uint ei = 0; ei < entries->size(); ei++) {
115 Entry *entry = entries->get(ei);
118 /* Compute our HMAC */
119 mac->update(array, HMAC_SIZE, array->length() - HMAC_SIZE);
120 Array<char> *realmac = mac->doFinal();
131 * Returns the live set of entries for this Slot. Generates a fake
132 * LastMessage entry to represent the information stored by the slot
136 Vector<Entry *> *Slot::getLiveEntries(bool resize) {
137 Vector<Entry *> *liveEntries = new Vector<Entry *>();
138 for (uint ei = 0; ei < entries->size(); ei++) {
139 Entry *entry = entries->get(ei);
140 if (entry->isLive()) {
141 if (!resize || entry->getType() != TypeTableStatus)
142 liveEntries->add(entry);
146 if (seqnumlive && !resize)
147 liveEntries->add(new LastMessage(this, machineid, seqnum));
154 * Records that a newer slot records the fact that this slot was
155 * sent by the relevant machine.
158 void Slot::setDead() {
160 decrementLiveCount();
164 * Update the count of live entries.
167 void Slot::decrementLiveCount() {
169 if (livecount == 0) {
170 table->decrementLiveCount();
174 Array<char> *Slot::getSlotCryptIV() {
175 ByteBuffer *buffer = ByteBuffer_allocate(CloudComm_IV_SIZE);
176 buffer->putLong(machineid);
177 int64_t localSequenceNumberShift = localSequenceNumber << 16;
178 buffer->putLong(localSequenceNumberShift);
179 return buffer->array();