edit
[iotcloud.git] / version2 / src / C / Slot.cc
1 #include "Slot.h"
2
3 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, char* _prevhmac, char* _hmac, int64_t _localSequenceNumber) {
4   seqnum = _seqnum;
5   machineid = _machineid;
6   prevhmac = _prevhmac;
7   hmac = _hmac;
8   entries = new Vector<Entry*>();
9   livecount = 1;
10   seqnumlive = true;
11   freespace = SLOT_SIZE - getBaseSize();
12   table = _table;
13   localSequenceNumber = _localSequenceNumber;
14 }
15
16 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, char* _prevhmac, int64_t _localSequenceNumber) {
17   this(_table, _seqnum, _machineid, _prevhmac, NULL, _localSequenceNumber);
18 }
19
20 Slot::Slot(Table *_table, int64_t _seqnum, int64_t _machineid, int64_t _localSequenceNumber) {
21   this(_table, _seqnum, _machineid, new char[HMAC_SIZE], NULL, _localSequenceNumber);
22 }
23
24 Entry * Slot::addEntry(Entry * e) {
25   e = e->getCopy(this);
26   entries->add(e);
27   livecount++;
28   freespace -= e->getSize();
29   return e;
30 }
31
32 void Slot::removeEntry(Entry *e) {
33   entries->remove(e);
34   livecount--;
35   freespace += e->getSize();
36 }
37
38 void Slot::addShallowEntry(Entry *e) {
39   entries->add(e);
40   livecount++;
41   freespace -= e->getSize();
42 }
43
44 /**
45  * Returns true if the slot has free space to hold the entry without
46  * using its reserved space. */
47
48 bool Slot::hasSpace(Entry *e) {
49   int newfreespace = freespace - e->getSize();
50   return newfreespace >= 0;
51 }
52
53 Vector<Entry*> * Slot::getEntries() {
54   return entries;
55 }
56
57 Slot * Slotdecode(Table * table, char* array, Mac * mac) {
58   mac->update(array, HMAC_SIZE, array.length - HMAC_SIZE);
59   char* realmac = mac->doFinal();
60   
61   ByteBuffer * bb = ByteBuffer_wrap(array);
62   char* hmac = new char[HMAC_SIZE];
63   char* prevhmac = new char[HMAC_SIZE];
64   bb->get(hmac);
65   bb->get(prevhmac);
66   if (!Arrays.equals(realmac, hmac))
67     throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
68   
69   int64_t seqnum = bb->getLong();
70   int64_t machineid = bb->getLong();
71   int numentries = bb->getInt();
72   Slot slot = new Slot(table, seqnum, machineid, prevhmac, hmac, -1);
73   
74   for (int i = 0; i < numentries; i++) {
75     slot->addShallowEntry(Entry->decode(slot, bb));
76   }
77   
78   return slot;
79 }
80
81 char* Slot::encode(Mac mac) {
82   char* array = new char[SLOT_SIZE];
83   ByteBuffer * bb = ByteBuffer_wrap(array);
84   /* Leave space for the slot HMAC.  */
85   bb->position(HMAC_SIZE);
86   bb->put(prevhmac);
87   bb->putLong(seqnum);
88   bb->putLong(machineid);
89   bb->putInt(entries->size());
90   for (Entry entry : entries) {
91     entry->encode(bb);
92   }
93   /* Compute our HMAC */
94   mac->update(array, HMAC_SIZE, array.length - HMAC_SIZE);
95   char* realmac = mac->doFinal();
96   hmac = realmac;
97   bb->position(0);
98   bb->put(realmac);
99   return array;
100 }
101
102
103 /**
104  * Returns the live set of entries for this Slot.  Generates a fake
105  * LastMessage entry to represent the information stored by the slot
106  * itself.
107  */
108
109 Vector<Entry*> *Slot::getLiveEntries(bool resize) {
110   Vector<Entry*> *liveEntries = new Vector<Entry*>();
111   for (Entry *entry : entries) {
112     if (entry->isLive()) {
113       if (!resize || entry->getType() != Entry->TypeTableStatus)
114         liveEntries->add(entry);
115     }
116   }
117   
118   if (seqnumlive && !resize)
119     liveEntries->add(new LastMessage(this, machineid, seqnum));
120   
121   return liveEntries;
122 }
123
124
125 /**
126  * Records that a newer slot records the fact that this slot was
127  * sent by the relevant machine.
128  */
129
130 void Slot::setDead() {
131   seqnumlive = false;
132   decrementLiveCount();
133 }
134
135 /**
136  * Update the count of live entries.
137  */
138
139 void Slot::decrementLiveCount() {
140   livecount--;
141   if (livecount == 0) {
142     table->decrementLiveCount();
143   }
144 }
145
146 char* Slot::getSlotCryptIV() {
147   ByteBuffer * buffer = ByteBuffer_allocate(CloudComm.IV_SIZE);
148   buffer->putLong(machineid);
149   int64_t localSequenceNumberShift = localSequenceNumber << 16;
150   buffer->putLong(localSequenceNumberShift);
151   return buffer->array();
152 }