edits
[iotcloud.git] / version2 / src / C / CloudComm.cpp
1 #include "CloudComm.h"
2 #include "TimingSingleton.h"
3 #include "SecureRandom.h"
4 #include "IoTString.h"
5 #include "Error.h"
6 #include "URL.h"
7 #include "Mac.h"
8 #include "Table.h"
9 #include "Slot.h"
10 #include "Crypto.h"
11 #include "ByteBuffer.h"
12 #include "aes.h"
13 #include <sys/types.h>
14 //#include <sys/socket.h>
15 //#include <arpa/inet.h>
16 //#include <netinet/tcp.h>
17 #include <unistd.h>
18 //#include <netdb.h>
19
20 /**
21  * Empty Constructor needed for child class.
22  */
23 CloudComm::CloudComm() :
24         baseurl(NULL),
25         key(NULL),
26         mac(NULL),
27         password(NULL),
28         random(NULL),
29         salt(NULL),
30         table(NULL),
31         listeningPort(-1),
32         doEnd(false),
33         timer(TimingSingleton_getInstance()),
34         getslot(new Array<char>("getslot", 7)),
35         putslot(new Array<char>("putslot", 7))
36 {
37 }
38
39 void *threadWrapper(void *cloud) {
40         CloudComm *c = (CloudComm *) cloud;
41         c->localServerWorkerFunction();
42         return NULL;
43 }
44
45 /**
46  * Constructor for actual use. Takes in the url and password.
47  */
48 CloudComm::CloudComm(Table *_table,  IoTString *_baseurl, IoTString *_password, int _listeningPort) :
49         baseurl(new IoTString(_baseurl)),
50         key(NULL),
51         mac(NULL),
52         password(new IoTString(_password)),
53         random(new SecureRandom()),
54         salt(NULL),
55         table(_table),
56         listeningPort(_listeningPort),
57         doEnd(false),
58         timer(TimingSingleton_getInstance()),
59         getslot(new Array<char>("getslot", 7)),
60         putslot(new Array<char>("putslot", 7)) {
61         /*      if (listeningPort > 0) {
62                 pthread_create(&localServerThread, NULL, threadWrapper, this);
63                 }*/
64 }
65
66 CloudComm::~CloudComm() {
67         delete getslot;
68         delete putslot;
69         if (salt)
70                 delete salt;
71         if (password)
72                 delete password;
73         if (random)
74                 delete random;
75         if (baseurl)
76                 delete baseurl;
77         if (mac)
78                 delete mac;
79         if (key)
80                 delete key;
81 }
82
83 /**
84  * Generates Key from password.
85  */
86 AESKey *CloudComm::initKey() {
87         AESKey *key = new AESKey(password->internalBytes(),
88                                                                                                          salt,
89                                                                                                          65536,
90                                                                                                          128);
91         return key;
92 }
93
94 /**
95  * Inits all the security stuff
96  */
97
98 void CloudComm::initSecurity() {
99         // try to get the salt and if one does not exist set one
100         if (!getSalt()) {
101                 //Set the salt
102                 setSalt();
103         }
104
105         initCrypt();
106 }
107
108 /**
109  * Inits the HMAC generator.
110  */
111 void CloudComm::initCrypt() {
112         if (password == NULL) {
113                 return;
114         }
115         key = initKey();
116         delete password;
117         password = NULL;// drop password
118         mac = new Mac();
119         mac->init(key);
120 }
121
122 /*
123  * Builds the URL for the given request.
124  */
125 IoTString *CloudComm::buildRequest(bool isput, int64_t sequencenumber, int64_t maxentries) {
126         const char *reqstring = isput ? "req=putslot" : "req=getslot";
127         char *buffer = (char *) malloc(baseurl->length() + 200);
128         memcpy(buffer, baseurl->internalBytes()->internalArray(), baseurl->length());
129         int offset = baseurl->length();
130         offset += sprintf(&buffer[offset], "?%s&seq=%" PRId64, reqstring, sequencenumber);
131         if (maxentries != 0)
132                 sprintf(&buffer[offset], "&max=%" PRId64, maxentries);
133         IoTString *urlstr = new IoTString(buffer);
134         free(buffer);
135         return urlstr;
136 }
137
138 void loopWrite(TCPClient * client, char *array, int bytestowrite) {
139         int byteswritten = 0;
140         while (bytestowrite) {
141                 int bytes = client->write((const unsigned char *) &array[byteswritten], bytestowrite);
142                 if (bytes >= 0) {
143                         byteswritten += bytes;
144                         bytestowrite -= bytes;
145                 } else {
146                         printf("Error in write\n");
147                         exit(-1);
148                 }
149         }
150 }
151
152 void loopRead(TCPClient * client, char *array, int bytestoread) {
153         int bytesread = 0;
154         while (bytestoread) {
155                 int bytes = client->read((unsigned char *) &array[bytesread], bytestoread);
156                 if (bytes >= 0) {
157                         bytesread += bytes;
158                         bytestoread -= bytes;
159                 } else {
160                         printf("Error in read\n");
161                         exit(-1);
162                 }
163         }
164 }
165
166 WebConnection openURL(IoTString *url) {
167         if (url->length() < 7 || memcmp(url->internalBytes()->internalArray(), "http://", 7)) {
168                 printf("BOGUS URL\n");
169                 exit(-1);
170         }
171         int i = 7;
172         for (; i < url->length(); i++)
173                 if (url->get(i) == '/')
174                         break;
175
176         if ( i == url->length()) {
177                 printf("ERROR in openURL\n");
178                 exit(-1);
179         }
180
181         char *host = (char *) malloc(i - 6);
182         memcpy(host, &url->internalBytes()->internalArray()[7], i - 7);
183         host[i - 7] = 0;
184         printf("%s\n", host);
185
186         char *message = (char *)malloc(sizeof("POST  HTTP/1.1\r\n") + sizeof("Host: \r\n") + 2 * url->length());
187
188         /* fill in the parameters */
189         int post = sprintf(message,"POST ");
190         /* copy data */
191         memcpy(&message[post], &url->internalBytes()->internalArray()[i], url->length() - i);
192         int endpost = sprintf(&message[post + url->length() - i], " HTTP/1.1\r\n");
193
194         int hostlen = sprintf(&message[endpost + post + url->length() - i], "Host: ");
195         memcpy(&message[endpost + post + url->length() + hostlen - i], host, i - 7);
196         sprintf(&message[endpost + post + url->length() + hostlen - 7], "\r\n");
197
198
199         WebConnection wc;
200         wc.numBytes = -1;
201
202         if (!wc.client.connect(host, 80)) {
203                 myerror("ERROR connecting\n");
204         }
205         free(host);
206         
207         /* send the request */
208         int total = strlen(message);
209         loopWrite(&wc.client, message, total);
210         free(message);
211         return wc;
212 }
213
214 TCPClient createSocket(IoTString *name, int port) {
215         char *host = (char *) malloc(name->length() + 1);
216         memcpy(host, name->internalBytes()->internalArray(), name->length());
217         host[name->length()] = 0;
218         printf("%s\n", host);
219         /* How big is the message? */
220
221         /* create the socket */
222         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
223         if (sockfd < 0) {printf("ERROR opening socket\n"); exit(-1);}
224
225         /* lookup the ip address */
226         TCPClient client;
227         if (!client.connect(host, port)) {
228                 myerror("ERROR connecting\n");
229         }
230
231         free(host);
232         return client;
233 }
234
235 TCPServer createSocket(int port) {
236         int fd;
237         TCPServer server = TCPServer(port);
238         server.begin();
239
240         return server;
241 }
242
243
244 void writeSocketData(TCPClient * fd, Array<char> *data) {
245         loopWrite(fd, data->internalArray(), data->length());
246 }
247
248 void writeSocketInt(TCPClient * fd, int32_t value) {
249         char array[4];
250         array[0] = value >> 24;
251         array[1] = (value >> 16) & 0xff;
252         array[2] = (value >> 8) & 0xff;
253         array[3] = value & 0xff;
254         loopWrite(fd, array, 4);
255 }
256
257 int readSocketInt(TCPClient * fd) {
258         char array[4];
259         loopRead(fd, array, 4);
260         return (((int32_t)(unsigned char) array[0]) << 24) |
261                                  (((int32_t)(unsigned char) array[1]) << 16) |
262                                  (((int32_t)(unsigned char) array[2]) << 8) |
263                                  ((int32_t)(unsigned char) array[3]);
264 }
265
266 void readSocketData(TCPClient * fd, Array<char> *data) {
267         loopRead(fd, data->internalArray(), data->length());
268 }
269
270 void writeURLDataAndClose(WebConnection *wc, Array<char> *data) {
271         char buffer[300];
272         sprintf(buffer, "Content-Length: %d\r\n\r\n", data->length());
273         wc->client.print(buffer);
274         loopWrite(&wc->client, data->internalArray(), data->length());
275 }
276
277 void closeURLReq(WebConnection *wc) {
278         wc->client.println("");
279 }
280
281 void readURLData(WebConnection *wc, Array<char> *output) {
282         loopRead(&wc->client, output->internalArray(), output->length());
283 }
284
285 int readURLInt(WebConnection *wc) {
286         char array[4];
287         loopRead(&wc->client, array, 4);
288         return (((int32_t)(unsigned char) array[0]) << 24) |
289                                  (((int32_t)(unsigned char) array[1]) << 16) |
290                                  (((int32_t)(unsigned char) array[2]) << 8) |
291                                  ((int32_t)(unsigned char) array[3]);
292 }
293
294 void readLine(WebConnection *wc, char *response, int numBytes) {
295         int offset = 0;
296         char newchar;
297         while (true) {
298                 int bytes = wc->client.read((unsigned char *) &newchar, 1);
299                 if (bytes <= 0)
300                         break;
301                 if (offset == (numBytes - 1)) {
302                         printf("Response too long");
303                         exit(-1);
304                 }
305                 response[offset++] = newchar;
306                 if (newchar == '\n')
307                         break;
308         }
309         response[offset] = 0;
310 }
311
312 int getResponseCode(WebConnection *wc) {
313         char response[600];
314         readLine(wc, response, sizeof(response));
315         int ver1 = 0, ver2 = 0, respcode = 0;
316         sscanf(response, "HTTP/%d.%d %d", &ver1, &ver2, &respcode);
317         printf("Response code %d\n", respcode);
318         return respcode;
319 }
320
321 void readHeaders(WebConnection *wc) {
322         char response[600];
323         int numBytes;
324
325         while (true) {
326                 readLine(wc, response, sizeof(response));
327                 if (response[0] == '\r')
328                         return;
329                 else if (memcmp(response, "Content-Length:", sizeof("Content-Length:") - 1) == 0) {
330                         sscanf(response, "Content-Length: %d", &numBytes);
331                         wc->numBytes = numBytes;
332                 }
333         }
334 }
335
336 void CloudComm::setSalt() {
337         if (salt != NULL) {
338                 // Salt already sent to server so don't set it again
339                 return;
340         }
341
342         WebConnection wc = {-1, -1};
343         //      try {
344                 Array<char> *saltTmp = new Array<char>(CloudComm_SALT_SIZE);
345                 random->nextBytes(saltTmp);
346
347                 char *buffer = (char *) malloc(baseurl->length() + 100);
348                 memcpy(buffer, baseurl->internalBytes()->internalArray(), baseurl->length());
349                 int offset = baseurl->length();
350                 offset += sprintf(&buffer[offset], "?req=setsalt");
351                 IoTString *urlstr = new IoTString(buffer);
352                 free(buffer);
353
354                 timer->startTime();
355                 wc = openURL(urlstr);
356                 delete urlstr;
357                 writeURLDataAndClose(&wc, saltTmp);
358
359                 int responsecode = getResponseCode(&wc);
360                 if (responsecode != HttpURLConnection_HTTP_OK) {
361                         //throw new Error("Invalid response");
362                         myerror("Invalid response\n");
363                 }
364                 wc.client.stop();
365
366                 timer->endTime();
367                 salt = saltTmp;
368                 /*      } catch (Exception *e) {
369                 timer->endTime();
370                 throw new ServerException("Failed setting salt", ServerException_TypeConnectTimeout);
371                 }*/
372 }
373
374 bool CloudComm::getSalt() {
375         WebConnection wc;
376         wc.numBytes = -1;
377         IoTString *urlstr = NULL;
378
379         //      try {
380                 char *buffer = (char *) malloc(baseurl->length() + 100);
381                 memcpy(buffer, baseurl->internalBytes()->internalArray(), baseurl->length());
382                 int offset = baseurl->length();
383                 offset += sprintf(&buffer[offset], "?req=getsalt");
384                 urlstr = new IoTString(buffer);
385                 free(buffer);
386                 /*      } catch (Exception *e) {
387                 throw new Error("getSlot failed");
388                 }*/
389                 //      try {
390                 timer->startTime();
391                 wc = openURL(urlstr);
392                 delete urlstr;
393                 urlstr = NULL;
394                 closeURLReq(&wc);
395                 timer->endTime();
396                 /*      } catch (SocketTimeoutException *e) {
397                 if (urlstr)
398                         delete urlstr;
399                 timer->endTime();
400                 throw new ServerException("getSalt failed", ServerException_TypeConnectTimeout);
401         } catch (Exception *e) {
402                 if (urlstr)
403                         delete urlstr;
404                 throw new Error("getSlot failed");
405                 }*/
406
407                 //      try {
408                 timer->startTime();
409                 int responsecode = getResponseCode(&wc);
410                 readHeaders(&wc);
411                 if (responsecode != HttpURLConnection_HTTP_OK) {
412                         //throw new Error("Invalid response");
413                         myerror("Invalid response\n");
414                 }
415                 if (wc.numBytes == 0) {
416                         timer->endTime();
417                         wc.client.stop();
418                         return false;
419                 }
420
421
422                 int salt_length = readURLInt(&wc);
423                 Array<char> *tmp = new Array<char>(salt_length);
424                 readURLData(&wc, tmp);
425                 wc.client.stop();
426
427                 salt = tmp;
428                 timer->endTime();
429                 return true;
430                 /*      } catch (SocketTimeoutException *e) {
431                 timer->endTime();
432                 throw new ServerException("getSalt failed", ServerException_TypeInputTimeout);
433         } catch (Exception *e) {
434                 throw new Error("getSlot failed");
435                 }*/
436 }
437
438 Array<char> *CloudComm::createIV(int64_t machineId, int64_t localSequenceNumber) {
439         ByteBuffer *buffer = ByteBuffer_allocate(CloudComm_IV_SIZE);
440         buffer->putLong(machineId);
441         int64_t localSequenceNumberShifted = localSequenceNumber << 16;
442         buffer->putLong(localSequenceNumberShifted);
443         return buffer->array();
444 }
445
446 Array<char> *AESEncrypt(Array<char> *ivBytes, AESKey *key, Array<char> *data) {
447         Array<char> *output = new Array<char>(data->length());
448         aes_encrypt_ctr((BYTE *)data->internalArray(), data->length(), (BYTE *) output->internalArray(), (WORD *)key->getKeySchedule(), key->getKey()->length() * 8, (BYTE *)ivBytes->internalArray());
449         return output;
450 }
451
452 Array<char> *AESDecrypt(Array<char> *ivBytes, AESKey *key, Array<char> *data) {
453         Array<char> *output = new Array<char>(data->length());
454         aes_decrypt_ctr((BYTE *)data->internalArray(), data->length(), (BYTE *)output->internalArray(), (WORD *)key->getKeySchedule(), key->getKey()->length() * 8, (BYTE *)ivBytes->internalArray());
455         return output;
456 }
457
458 Array<char> *CloudComm::encryptSlotAndPrependIV(Array<char> *rawData, Array<char> *ivBytes) {
459         //      try {
460                 Array<char> *encryptedBytes = AESEncrypt(ivBytes, key, rawData);
461                 Array<char> *chars = new Array<char>(encryptedBytes->length() + CloudComm_IV_SIZE);
462                 System_arraycopy(ivBytes, 0, chars, 0, ivBytes->length());
463                 System_arraycopy(encryptedBytes, 0, chars, CloudComm_IV_SIZE, encryptedBytes->length());
464                 delete encryptedBytes;
465                 return chars;
466                 /*      } catch (Exception *e) {
467                 throw new Error("Failed To Encrypt");
468                 }*/
469 }
470
471 Array<char> *CloudComm::stripIVAndDecryptSlot(Array<char> *rawData) {
472         //      try {
473                 Array<char> *ivBytes = new Array<char>(CloudComm_IV_SIZE);
474                 Array<char> *encryptedBytes = new Array<char>(rawData->length() - CloudComm_IV_SIZE);
475                 System_arraycopy(rawData, 0, ivBytes, 0, CloudComm_IV_SIZE);
476                 System_arraycopy(rawData, CloudComm_IV_SIZE, encryptedBytes, 0, encryptedBytes->length());
477                 Array<char> * data = AESDecrypt(ivBytes, key, encryptedBytes);
478                 delete encryptedBytes;
479                 delete ivBytes;
480                 return data;
481                 /*      } catch (Exception *e) {
482                 throw new Error("Failed To Decrypt");
483                 }*/
484 }
485
486 /*
487  * API for putting a slot into the queue.  Returns NULL on success.
488  * On failure, the server will send slots with newer sequence
489  * numbers.
490  */
491 Array<Slot *> *CloudComm::putSlot(Slot *slot, int max) {
492         WebConnection wc = {-1, -1};
493         //      try {
494                 if (salt == NULL) {
495                         if (!getSalt()) {
496                                 //                              throw new ServerException("putSlot failed", ServerException_TypeSalt);
497                                 myerror("putSlot failed\n");
498                         }
499                         initCrypt();
500                 }
501
502                 int64_t sequencenumber = slot->getSequenceNumber();
503                 Array<char> *slotBytes = slot->encode(mac);
504                 Array<char> * ivBytes = slot->getSlotCryptIV();
505                 Array<char> *chars = encryptSlotAndPrependIV(slotBytes, ivBytes);
506                 delete ivBytes;
507                 delete slotBytes;
508                 IoTString *url = buildRequest(true, sequencenumber, max);
509                 timer->startTime();
510                 wc = openURL(url);
511                 delete url;
512                 writeURLDataAndClose(&wc, chars);
513                 delete chars;
514                 timer->endTime();
515                 /*      } catch (ServerException *e) {
516                 timer->endTime();
517                 throw e;
518         } catch (SocketTimeoutException *e) {
519                 timer->endTime();
520                 throw new ServerException("putSlot failed", ServerException_TypeConnectTimeout);
521         } catch (Exception *e) {
522                 throw new Error("putSlot failed");
523                 }*/
524
525         Array<char> *resptype = NULL;
526         //      try {
527                 int respcode = getResponseCode(&wc);
528                 readHeaders(&wc);
529                 timer->startTime();
530                 resptype = new Array<char>(7);
531                 readURLData(&wc, resptype);
532                 timer->endTime();
533
534                 if (resptype->equals(getslot)) {
535                         delete resptype;
536                         Array<Slot *> *tmp = processSlots(&wc);
537                         wc.client.stop();
538                         return tmp;
539                 } else if (resptype->equals(putslot)) {
540                         delete resptype;
541                         wc.client.stop();
542                         return NULL;
543                 } else {
544                         delete resptype;
545                         wc.client.stop();
546                         //throw new Error("Bad response to putslot");
547                         myerror("Bad response to putslot\n");
548                 }
549                 /*      } catch (SocketTimeoutException *e) {
550                 if (resptype != NULL)
551                         delete resptype;
552                 timer->endTime();
553                 close(wc.fd);
554                 throw new ServerException("putSlot failed", ServerException_TypeInputTimeout);
555         } catch (Exception *e) {
556                 if (resptype != NULL)
557                         delete resptype;
558                 throw new Error("putSlot failed");
559                 }*/
560 }
561
562 /**
563  * Request the server to send all slots with the given
564  * sequencenumber or newer->
565  */
566 Array<Slot *> *CloudComm::getSlots(int64_t sequencenumber) {
567         WebConnection wc = {-1, -1};
568         //      try {
569                 if (salt == NULL) {
570                         if (!getSalt()) {
571                                 //throw new ServerException("getSlots failed", ServerException_TypeSalt);
572                                 myerror("getSlots failed\n");
573                         }
574                         initCrypt();
575                 }
576
577                 IoTString *url = buildRequest(false, sequencenumber, 0);
578                 timer->startTime();
579                 wc = openURL(url);
580                 delete url;
581                 closeURLReq(&wc);
582                 timer->endTime();
583                 /*      } catch (SocketTimeoutException *e) {
584                 timer->endTime();
585                 throw new ServerException("getSlots failed", ServerException_TypeConnectTimeout);
586         } catch (ServerException *e) {
587                 timer->endTime();
588
589                 throw e;
590         } catch (Exception *e) {
591                 throw new Error("getSlots failed");
592                 }*/
593
594                 //      try {
595                 timer->startTime();
596                 int responsecode = getResponseCode(&wc);
597                 readHeaders(&wc);
598                 Array<char> *resptype = new Array<char>(7);
599                 readURLData(&wc, resptype);
600                 timer->endTime();
601                 if (!resptype->equals(getslot))
602                         //                      throw new Error("Bad Response: ");
603                         myerror("Bad Response: \n");
604
605                 delete resptype;
606                 Array<Slot *> *tmp = processSlots(&wc);
607                 wc.client.stop();
608                 return tmp;
609                 /*      } catch (SocketTimeoutException *e) {
610                 timer->endTime();
611                 close(wc.fd);
612                 throw new ServerException("getSlots failed", ServerException_TypeInputTimeout);
613         } catch (Exception *e) {
614                 throw new Error("getSlots failed");
615                 }*/
616 }
617
618 /**
619  * Method that actually handles building Slot objects from the
620  * server response.  Shared by both putSlot and getSlots.
621  */
622 Array<Slot *> *CloudComm::processSlots(WebConnection *wc) {
623         int numberofslots = readURLInt(wc);
624         Array<int> *sizesofslots = new Array<int>(numberofslots);
625         Array<Slot *> *slots = new Array<Slot *>(numberofslots);
626
627         for (int i = 0; i < numberofslots; i++)
628                 sizesofslots->set(i, readURLInt(wc));
629         for (int i = 0; i < numberofslots; i++) {
630                 Array<char> *rawData = new Array<char>(sizesofslots->get(i));
631                 readURLData(wc, rawData);
632                 Array<char> *data = stripIVAndDecryptSlot(rawData);
633                 delete rawData;
634                 slots->set(i, Slot_decode(table, data, mac));
635                 delete data;
636         }
637         delete sizesofslots;
638         return slots;
639 }
640
641 Array<char> *CloudComm::sendLocalData(Array<char> *sendData, int64_t localSequenceNumber, IoTString *host, int port) {
642         if (salt == NULL)
643                 return NULL;
644         //      try {
645                 printf("Passing Locally\n");
646                 mac->update(sendData, 0, sendData->length());
647                 Array<char> *genmac = mac->doFinal();
648                 Array<char> *totalData = new Array<char>(sendData->length() + genmac->length());
649                 System_arraycopy(sendData, 0, totalData, 0, sendData->length());
650                 System_arraycopy(genmac, 0, totalData, sendData->length(), genmac->length());
651
652                 // Encrypt the data for sending
653                 Array<char> *iv = createIV(table->getMachineId(), table->getLocalSequenceNumber());
654                 Array<char> *encryptedData = encryptSlotAndPrependIV(totalData, iv);
655
656                 // Open a TCP socket connection to a local device
657                 TCPClient socket = createSocket(host, port);
658
659                 timer->startTime();
660                 // Send data to output (length of data, the data)
661                 writeSocketInt(&socket, encryptedData->length());
662                 writeSocketData(&socket, encryptedData);
663
664                 int lengthOfReturnData = readSocketInt(&socket);
665                 Array<char> *returnData = new Array<char>(lengthOfReturnData);
666                 readSocketData(&socket, returnData);
667                 timer->endTime();
668                 returnData = stripIVAndDecryptSlot(returnData);
669
670                 // We are done with this socket
671                 socket.stop();
672                 mac->update(returnData, 0, returnData->length() - CloudComm_HMAC_SIZE);
673                 Array<char> *realmac = mac->doFinal();
674                 Array<char> *recmac = new Array<char>(CloudComm_HMAC_SIZE);
675                 System_arraycopy(returnData, returnData->length() - realmac->length(), recmac, 0, realmac->length());
676
677                 if (!recmac->equals(realmac))
678                         //                      throw new Error("Local Error: Invalid HMAC!  Potential Attack!");
679                         myerror("Local Error: Invalid HMAC!  Potential Attack!\n");
680
681                 Array<char> *returnData2 = new Array<char>(lengthOfReturnData - recmac->length());
682                 System_arraycopy(returnData, 0, returnData2, 0, returnData2->length());
683
684                 return returnData2;
685                 /*      } catch (Exception *e) {
686                 printf("Exception\n");
687                 }*/
688
689         return NULL;
690 }
691
692 void CloudComm::localServerWorkerFunction() {
693         /*      int inputSocket = -1;
694         
695         try {
696                 // Local server socket
697                 inputSocket = createSocket(listeningPort);
698         } catch (Exception *e) {
699                 throw new Error("Local server setup failure...");
700         }
701         
702         while (!doEnd) {
703                 try {
704                         // Accept incoming socket
705                         int socket = acceptSocket(inputSocket);
706                         
707                         // Get the encrypted data from the server
708                         int dataSize = readSocketInt(socket);
709                         Array<char> *readData = new Array<char>(dataSize);
710                         readSocketData(socket, readData);
711                         timer->endTime();
712                         
713                         // Decrypt the data
714                         readData = stripIVAndDecryptSlot(readData);
715                         mac->update(readData, 0, readData->length() - CloudComm_HMAC_SIZE);
716                         Array<char> *genmac = mac->doFinal();
717                         Array<char> *recmac = new Array<char>(CloudComm_HMAC_SIZE);
718                         System_arraycopy(readData, readData->length() - recmac->length(), recmac, 0, recmac->length());
719
720                         if (!recmac->equals(genmac))
721                                 //                              throw new Error("Local Error: Invalid HMAC!  Potential Attack!");
722                                 error("Local Error: Invalid HMAC!  Potential Attack!\n");
723
724                         Array<char> *returnData = new Array<char>(readData->length() - recmac->length());
725                         System_arraycopy(readData, 0, returnData, 0, returnData->length());
726
727                         // Process the data
728                         Array<char> *sendData = table->acceptDataFromLocal(returnData);
729                         mac->update(sendData, 0, sendData->length());
730                         Array<char> *realmac = mac->doFinal();
731                         Array<char> *totalData = new Array<char>(sendData->length() + realmac->length());
732                         System_arraycopy(sendData, 0, totalData, 0, sendData->length());
733                         System_arraycopy(realmac, 0, totalData, sendData->length(), realmac->length());
734
735                         // Encrypt the data for sending
736                         Array<char> *iv = createIV(table->getMachineId(), table->getLocalSequenceNumber());
737                         Array<char> *encryptedData = encryptSlotAndPrependIV(totalData, iv);
738
739                         timer->startTime();
740                         // Send data to output (length of data, the data)
741                         writeSocketInt(socket, encryptedData->length());
742                         writeSocketData(socket, encryptedData);
743                         close(socket);
744                 } catch (Exception *e) {
745                 }
746         }
747         
748         if (inputSocket != -1) {
749                 try {
750                         close(inputSocket);
751                 } catch (Exception *e) {
752                         throw new Error("Local server close failure...");
753                 }
754                 }*/
755 }
756
757 void CloudComm::closeCloud() {
758         doEnd = true;
759
760         /*      if (listeningPort > 0) {
761                 if (pthread_join(localServerThread, NULL) != 0)
762                         throw new Error("Local Server thread join issue...");
763                         }*/
764 }