Cleaned up git
[iotcloud.git] / version1 / src / js / iotjs / orig / slot.js
1 class Slot {
2     constructor(table, seqnum, machineid, prevhmac, hmac) {
3         this.SLOT_SIZE = 2048;
4         this.RESERVED_SPACE = 64;
5         this.HMAC_SIZE = 32;
6         if(typeof seqnum === "number"){
7                 this.seqnum = seqnum;
8         }else{
9                 throw new Error("seqnum should be a number");
10         }
11         if(typeof machineid === "number"){
12                 this.machineid = machineid;
13         }else{
14                 throw new Error("machine should be a number");
15         }
16         this.livecount = 1;
17         this.seqnumlive = true;
18         if(prevhmac && prevhmac instanceof Uint8Array){
19                 this.prevhmac = prevhmac;
20         }else{
21                 throw new Error("prevhmac input not valid");
22         }
23             if(hmac && hmac instanceof Uint8Array){
24                 this.hmac = hmac
25             }else{
26                 throw new Error("Hmac input not valid");
27             }
28         this.entries = [];
29         this.freespace = this.SLOT_SIZE - getBaseSize();   //???????
30         this.table = table;
31         }
32         getHMAC() {
33         return this.hmac;
34         }
35         getPrevHmac() {
36         return this.prevhmac;
37         }
38         addEntry(entry) {
39             if (entry && entry instanceof Entry) {
40                 var obj;
41                 this.entries.push(_.extend(obj, entry));
42                 this.livecount++;
43                 this.freespace -= entry.getSize();
44             }
45         }
46         addShallowEntry(entry){
47                 if(entry && entry instanceof Entry){
48                         this.entries.push(entry);
49                         this.livecount++;
50                 this.freespace -= entry.getSize();
51                 }
52         }
53         hasSpace(entry){
54                 var newfreespace = this.freespace - entry.getSize();
55                 return newfreespace > this.RESERVED_SPACE;
56         }
57         getEntries(){
58                 return this.entries;
59         }
60         static decode(table, array, key){
61                 var cond1 = (array && array instanceof Uint8Array);
62                 if(cond1){
63                         var mac = crypto.HmacMD5(array.slice(this.HMAC_SIZE).join([separator='']),key);
64                         
65                         var realmac = new Uint8Array(mac.length);
66                         for(var i=0; i< mac.length ; i++){
67                                 realmac[i] = mac.charCodeAt(i);
68                         }
69                         
70                         var bb = new ByteBuffer().wrap(array.join([separator=''])).flip();
71                         var hmac= new Uint8Array(this.HMAC_SIZE);
72                         var prevhmac = new Uint8Array(this.HMAC_SIZE);
73                         for(var i = 0; i<this.HMAC_SIZE; i++){
74                                 hmac[i] = bb.readByte();
75                         }
76                         for(var j = 0; j<this.HMAC_SIZE; j++){
77                                 prevhmac[j] = bb.readByte();
78                         }
79                         //shallow compare
80                         for(var k =0; k<this.HMAC_SIZE; k++){
81                                 if(!(hmac[k] === realmac[k])){
82                                         throw new Error("Server Error: Invalid HMAC!  Potential Attack!");
83                                 }
84                         }
85                         var _seqnum = bb.readLong();
86                         var _machineid = bb.readLong();
87                         var numentries = bb.readInt8();
88
89                         var _slot = new Slot(table,_seqnum,_machineid,prevhmac,hmac);
90
91                         for(var l= 0 ;l<numentries;l++){
92                                 _slot.addShallowEntry(Entry.decode(_slot,bb));
93                         }
94                         return _slot;
95                 }
96         }
97         encode(key){
98                 var array = new Uint8Array(this.SLOT_SIZE);
99                 var bb = new ByteBuffer().wrap(array.join([separator='']))
100                 //leave space for slot HMAC
101                 bb.skip(this.HMAC_SIZE);
102                 bb.writeIString(this.prevhmac.join([separator='']));
103                 bb.writeInt64(this.seqnum);
104                 bb.writeInt64(this.machineid);
105                 bb.writeByte(this.entries.length);
106                 this.entries.forEach((entry) => entry.encode(bb));
107
108                 var mac = crypto.HmacMD5(array.slice(this.HMAC_SIZE).join([separator='']),key);
109                 var realmac = new Uint8Array(mac.length);
110                 for(var i=0; i< mac.length ; i++){
111                         realmac[i] = mac.charCodeAt(i);
112                 }
113                 this.hmac = realmac;
114                 bb.reset();
115                 bb.wrap(realmac.join([separator='']));
116                 return new Uint8Array(bb.toArrayBuffer());
117         }
118         /**
119          * Returns the empty size of a Slot. Includes 2 HMACs, the machine
120          * identifier, the sequence number, and the number of entries.
121          */
122         getBaseSize(){
123                 return 2*this.HMAC_SIZE+2*8+2*4; //Problematic area
124         }
125
126         getLiveEntries(resize){
127                 var liveEntries = [];
128                 this.entries.forEach(function(entry){
129                         if(entry.isLive === true){
130                                 if(!resize || entry.getType() !== entry.TypeTableStatus){
131                                         liveEntries.push(entry);
132                                 }
133                         };
134                 });
135
136                 if(this.seqnumlive && !resize){
137                         liveEntries.push(new LastMessage(this,this.machineid,this.seqnumlive))
138                 }
139
140                 return liveEntries;
141         }
142
143         getSequenceNumber() {
144                 return this.seqnum;
145         }
146
147         getMachineID() {
148                 return this.machineid;
149         }
150         
151         setDead() {
152                 this.seqnumlive=false;
153                 this.decrementLiveCount();
154         }
155
156         decrementLiveCount() {
157                 this.livecount--;
158                 if (this.livecount === 0)
159                         this.table.decrementLiveCount();
160         }
161
162         isLive() {
163                 return this.livecount > 0;
164         }
165
166         toString() {
167                 return '<'+this.getSequenceNumber()+'>';
168         }
169
170 }
171