Local communication support
[iotcloud.git] / version2 / src / server / iotquery.cpp
index 0b1c4b302870b9ea92547ee7430b70ac522f306b..64639b39785885bbaf200734180ea317d1b1e178 100644 (file)
 
 using namespace std;
 
-const char * query_str="QUERY_STRING";
-const char * uri_str="REQUEST_URI";
-const char * method_str="REQUEST_METHOD";
-const char * iotcloudroot_str="IOTCLOUD_ROOT";
-const char * length_str="CONTENT_LENGTH";
+const char * query_str = "QUERY_STRING";
+const char * uri_str = "REQUEST_URI";
+const char * method_str = "REQUEST_METHOD";
+const char * iotcloudroot_str = "IOTCLOUD_ROOT";
+const char * length_str = "CONTENT_LENGTH";
 
 IoTQuery::IoTQuery(FCGX_Request *request) :
        request(request),
@@ -52,7 +52,7 @@ IoTQuery::~IoTQuery() {
 
 bool IoTQuery::checkDirectory() {
        struct stat s;
-       int err=stat(directory, &s);
+       int err = stat(directory, &s);
        if (-1 == err)
                return false;
        return S_ISDIR(s.st_mode);
@@ -65,13 +65,13 @@ bool IoTQuery::checkDirectory() {
  */
 
 void IoTQuery::decodeQuery() {
-       int len=strlen(query);
-       char * str=new char[len+1];
-       memcpy(str, query, len+1);
-       char *tok_ptr=str;
-       
+       int len = strlen(query);
+       char * str = new char[len + 1];
+       memcpy(str, query, len + 1);
+       char *tok_ptr = str;
+
        /* Parse commands */
-       char *command=strsep(&tok_ptr, "&");
+       char *command = strsep(&tok_ptr, "&");
        if (strncmp(command, "req=putslot", 11) == 0)
                reqPutSlot = true;
        else if (strncmp(command, "req=getslot", 11) == 0)
@@ -84,7 +84,7 @@ void IoTQuery::decodeQuery() {
        /* Load Sequence Number for request */
        char *sequencenumber_str = strsep(&tok_ptr, "&");
        if (sequencenumber_str != NULL &&
-                       strncmp(sequencenumber_str, "seq=", 4) == 0) {
+               strncmp(sequencenumber_str, "seq=", 4) == 0) {
                sequencenumber_str = strchr(sequencenumber_str, '=');
                if (sequencenumber_str != NULL) {
                        requestsequencenumber = strtoll(sequencenumber_str + 1, NULL, 10);
@@ -98,7 +98,7 @@ void IoTQuery::decodeQuery() {
        /* Update size if we get request */
        char * numqueueentries_str = tok_ptr;
        if (numqueueentries_str != NULL &&
-                       strncmp(numqueueentries_str, "max=", 4) == 0) {
+               strncmp(numqueueentries_str, "max=", 4) == 0) {
                numqueueentries_str = strchr(numqueueentries_str, '=') + 1;
                numqueueentries = strtoll(numqueueentries_str, NULL, 10);
        }
@@ -111,9 +111,9 @@ void IoTQuery::decodeQuery() {
  */
 
 void doWrite(int fd, char *data, long long length) {
-       long long offset=0;
+       long long offset = 0;
        do {
-               long long byteswritten=write(fd, &data[offset], length);
+               long long byteswritten = write(fd, &data[offset], length);
                if (byteswritten > 0) {
                        length -= byteswritten;
                        offset += byteswritten;
@@ -124,21 +124,21 @@ void doWrite(int fd, char *data, long long length) {
                        }
                        return;
                }
-       } while(length != 0);
+       } while (length != 0);
 }
 
 /** Helper function to read data from file. */
 bool doRead(int fd, void *buf, int numbytes) {
-       int offset=0;
-       char *ptr=(char *)buf;
+       int offset = 0;
+       char *ptr = (char *)buf;
        do {
-               int bytesread=read(fd, ptr+offset, numbytes);
+               int bytesread = read(fd, ptr + offset, numbytes);
                if (bytesread > 0) {
                        offset += bytesread;
                        numbytes -= bytesread;
                } else
                        return false;
-       } while (numbytes!=0);
+       } while (numbytes != 0);
        return true;
 }
 
@@ -147,50 +147,50 @@ bool doRead(int fd, void *buf, int numbytes) {
  */
 
 void IoTQuery::getSlot() {
-       int numrequeststosend = (int)((newestentry-requestsequencenumber)+1);
+       int numrequeststosend = (int)((newestentry - requestsequencenumber) + 1);
        if (numrequeststosend < 0)
                numrequeststosend = 0;
        long long numbytes = 0;
        int filesizes[numrequeststosend];
        int fdarray[numrequeststosend];
-       int index=0;
-       for(long long seqn = requestsequencenumber; seqn <= newestentry; seqn++, index++) {
+       int index = 0;
+       for (long long seqn = requestsequencenumber; seqn <= newestentry; seqn++, index++) {
                struct stat st;
-               char *filename=getSlotFileName(seqn);
+               char *filename = getSlotFileName(seqn);
                if (stat(filename, &st) == 0) {
-                       fdarray[index]=open(filename, O_RDONLY);
-                       filesizes[index]=st.st_size;
-                       numbytes+=filesizes[index];
+                       fdarray[index] = open(filename, O_RDONLY);
+                       filesizes[index] = st.st_size;
+                       numbytes += filesizes[index];
                } else {
-                       fdarray[index]=-1;
-                       filesizes[index]=0;
+                       fdarray[index] = -1;
+                       filesizes[index] = 0;
                }
                delete filename;
        }
-       const char header[]="getslot";
+       const char header[] = "getslot";
 
        /* Size is the header + the payload + space for number of requests
                 plus sizes of each slot */
 
-       long long size=sizeof(header)-1+sizeof(numrequeststosend)+4*numrequeststosend+numbytes;
+       long long size = sizeof(header) - 1 + sizeof(numrequeststosend) + 4 * numrequeststosend + numbytes;
        char * response = new char[size];
-       long long offset=0;
-       memcpy(response, header, sizeof(header)-1);
-       offset+=sizeof(header)-1;
-       int numreq=htonl(numrequeststosend);
+       long long offset = 0;
+       memcpy(response, header, sizeof(header) - 1);
+       offset += sizeof(header) - 1;
+       int numreq = htonl(numrequeststosend);
        memcpy(response + offset, &numreq, sizeof(numreq));
-       offset+=sizeof(numrequeststosend);
-       for(int i=0; i<numrequeststosend; i++) {
-               int filesize=htonl(filesizes[i]);
+       offset += sizeof(numrequeststosend);
+       for (int i = 0; i < numrequeststosend; i++) {
+               int filesize = htonl(filesizes[i]);
                memcpy(response + offset, &filesize, sizeof(filesize));
-               offset+=sizeof(int);
+               offset += sizeof(int);
        }
 
        /* Read the file data into the buffer */
-       for(int i=0; i<numrequeststosend; i++) {
-               if (fdarray[i]>=0) {
-                       doRead(fdarray[i], response+offset, filesizes[i]);
-                       offset+=filesizes[i];
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0) {
+                       doRead(fdarray[i], response + offset, filesizes[i]);
+                       offset += filesizes[i];
                }
        }
 
@@ -199,7 +199,7 @@ void IoTQuery::getSlot() {
 
        /* Delete the response buffer and close the files. */
        delete response;
-       for(int i=0; i<numrequeststosend; i++) {
+       for (int i = 0; i < numrequeststosend; i++) {
                if (fdarray[i] >= 0)
                        close(fdarray[i]);
        }
@@ -212,12 +212,27 @@ void IoTQuery::getSlot() {
 void IoTQuery::setSalt() {
        /* Write the slot data we received to a SLOT file */
        char *filename = getSaltFileName();
-       int saltfd = open(filename, O_CREAT|O_WRONLY, S_IRUSR| S_IWUSR);
-       doWrite(saltfd, data, length);
-       char response[0];
-       sendResponse(response, 0);
-       close(saltfd);
+       char * response = new char[1];
+
+       if (access(filename, F_OK) == 0)
+       {
+               /* Already Exists */
+               response[0] = 1;
+       }
+       else
+       {
+               /* Does not exist so create it */
+               int saltfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+               doWrite(saltfd, data, length);
+               close(saltfd);
+               response[0] = 0;
+       }
+
+
+       sendResponse(response, 1);
+
        delete filename;
+       delete response;
 }
 
 /**
@@ -230,7 +245,7 @@ void IoTQuery::getSalt() {
        int filesize = 0;
        struct stat st;
        if (stat(filename, &st) == 0) {
-               filesize=st.st_size;
+               filesize = st.st_size;
        } else {
                delete filename;
                return;
@@ -238,8 +253,8 @@ void IoTQuery::getSalt() {
        int saltfd = open(filename, O_RDONLY);
        int responsesize = filesize + sizeof(int);
        char * response = new char[responsesize];
-       doRead(saltfd, response+ sizeof(int), filesize);
-       int n_filesize=htonl(filesize);
+       doRead(saltfd, response + sizeof(int), filesize);
+       int n_filesize = htonl(filesize);
        *((int*) response) = n_filesize;
        sendResponse(response, responsesize);
        close(saltfd);
@@ -254,20 +269,20 @@ void IoTQuery::getSalt() {
 void IoTQuery::putSlot() {
        /* Check if the request is stale and send update in that case.  This
                 servers as an implicit failure of the request. */
-       if (requestsequencenumber!=(newestentry+1)) {
+       if (requestsequencenumber != (newestentry + 1)) {
                getSlot();
                return;
        }
 
        /* See if we have too many slots and if so, delete the old one */
-       int numberofliveslots=(int) ((newestentry-oldestentry)+1);
+       int numberofliveslots = (int) ((newestentry - oldestentry) + 1);
        if (numberofliveslots >=  numqueueentries) {
                removeOldestSlot();
        }
 
        /* Write the slot data we received to a SLOT file */
        char *filename = getSlotFileName(requestsequencenumber);
-       int slotfd = open(filename, O_CREAT|O_WRONLY, S_IRUSR| S_IWUSR);
+       int slotfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
        doWrite(slotfd, data, length);
        close(slotfd);
        delete filename;
@@ -277,8 +292,8 @@ void IoTQuery::putSlot() {
        updateStatusFile();
 
        /* Send response acknowledging success */
-       char command[]="putslot";
-       sendResponse(command, sizeof(command)-1);
+       char command[] = "putslot";
+       sendResponse(command, sizeof(command) - 1);
 }
 
 /**
@@ -288,8 +303,8 @@ void IoTQuery::putSlot() {
 
 void IoTQuery::sendResponse(char * bytes, int len) {
        cout << "Accept-Ranges: bytes\r\n"
-                        << "Content-Length: " << len << "\r\n"
-                        << "\r\n";
+            << "Content-Length: " << len << "\r\n"
+            << "\r\n";
        cout.write(bytes, len);
 }
 
@@ -298,14 +313,14 @@ void IoTQuery::sendResponse(char * bytes, int len) {
  */
 
 char * IoTQuery::getSlotFileName(long long seqnum) {
-       int directorylen=strlen(directory);
+       int directorylen = strlen(directory);
 
        /* Size is 19 digits for ASCII representation of a long + 4
                 characters for SLOT string + 1 character for null termination +
                 directory size*/
 
-       char * filename=new char[25+directorylen];
-       snprintf(filename, 25+directorylen, "%s/SLOT%lld", directory, seqnum);
+       char * filename = new char[25 + directorylen];
+       snprintf(filename, 25 + directorylen, "%s/SLOT%lld", directory, seqnum);
        return filename;
 }
 
@@ -314,13 +329,13 @@ char * IoTQuery::getSlotFileName(long long seqnum) {
  */
 
 char * IoTQuery::getSaltFileName() {
-       int directorylen=strlen(directory);
+       int directorylen = strlen(directory);
 
        /* Size is 4 characters for SALT string + 1 character for null
                 termination + directory size*/
 
-       char * filename=new char[6+directorylen];
-       snprintf(filename, 6+directorylen, "%s/SALT", directory);
+       char * filename = new char[6 + directorylen];
+       snprintf(filename, 6 + directorylen, "%s/SALT", directory);
        return filename;
 }
 
@@ -329,8 +344,8 @@ char * IoTQuery::getSaltFileName() {
  */
 
 void IoTQuery::removeOldestSlot() {
-       if (oldestentry!=0) {
-               char * filename=getSlotFileName(oldestentry);
+       if (oldestentry != 0) {
+               char * filename = getSlotFileName(oldestentry);
                unlink(filename);
                delete filename;
        }
@@ -344,7 +359,11 @@ void IoTQuery::removeOldestSlot() {
 void IoTQuery::processQuery() {
        getQuery();
        getDirectory();
-       readData();
+       if (!readData())
+       {
+               return;
+       }
+
 
        /* Verify that we receive a post request. */
        if (strncmp(method, "POST", 4) != 0) {
@@ -354,7 +373,7 @@ void IoTQuery::processQuery() {
 
        /* Make sure the directory is okay. */
        if (directory == NULL ||
-                       !checkDirectory()) {
+               !checkDirectory()) {
                cerr << "Directory " << directory << " does not exist" << endl;
                return;
        }
@@ -371,7 +390,7 @@ void IoTQuery::processQuery() {
 
        /* Decode query. */
        decodeQuery();
-       
+
        /* Handle request. */
        if (reqGetSlot)
                getSlot();
@@ -392,16 +411,26 @@ void IoTQuery::processQuery() {
  * inserted.
  */
 
-void IoTQuery::readData() {
+bool IoTQuery::readData() {
        if (length) {
-               data = new char[length+1];
-               memset(data, 0, length+1);
+               data = new char[length + 1];
+               memset(data, 0, length + 1);
                cin.read(data, length);
        }
        do {
                char dummy;
                cin >> dummy;
        } while (!cin.eof());
+
+       if (length)
+       {
+               if (cin.fail())
+               {
+                       return false;
+               }
+       }
+
+       return true;
 }
 
 
@@ -418,9 +447,9 @@ void IoTQuery::getQuery() {
        /** We require the content-length header to be sent. */
        char * reqlength = FCGX_GetParam(length_str, request->envp);
        if (reqlength) {
-               length=strtoll(reqlength, NULL, 10);
+               length = strtoll(reqlength, NULL, 10);
        } else {
-               length=0;
+               length = 0;
        }
 }
 
@@ -432,13 +461,13 @@ void IoTQuery::getDirectory() {
        char * split = strchr((char *)uri, '?');
        if (split == NULL)
                return;
-       int split_len = (int) (split-uri);
+       int split_len = (int) (split - uri);
        int rootdir_len = strlen(iotcloudroot);
        int directory_len = split_len + rootdir_len + 1;
        directory = new char[directory_len];
        memcpy(directory, iotcloudroot, rootdir_len);
        memcpy(directory + rootdir_len, uri, split_len);
-       directory[directory_len-1]=0;
+       directory[directory_len - 1] = 0;
 }
 
 /**
@@ -447,13 +476,13 @@ void IoTQuery::getDirectory() {
 
 int doread(int fd, void *ptr, size_t count, off_t offset) {
        do {
-               size_t bytesread=pread(fd, ptr, count, offset);
-               if (bytesread==count) {
+               size_t bytesread = pread(fd, ptr, count, offset);
+               if (bytesread == count) {
                        return 1;
-               } else if (bytesread==0) {
+               } else if (bytesread == 0) {
                        return 0;
                }
-       } while(1);
+       } while (1);
 }
 
 
@@ -473,15 +502,15 @@ void IoTQuery::updateStatusFile() {
  */
 
 bool IoTQuery::openStatusFile() {
-       char statusfile[]="queuestatus";
-       int len=strlen(directory);
+       char statusfile[] = "queuestatus";
+       int len = strlen(directory);
 
-       char * filename=new char[len+sizeof(statusfile)+2];
+       char * filename = new char[len + sizeof(statusfile) + 2];
        memcpy(filename, directory, len);
-       filename[len]='/';
-       memcpy(filename+len+1, statusfile, sizeof(statusfile));
-       filename[len+sizeof(statusfile)+1]=0;
-       fd=open(filename, O_CREAT| O_RDWR, S_IRUSR| S_IWUSR);
+       filename[len] = '/';
+       memcpy(filename + len + 1, statusfile, sizeof(statusfile));
+       filename[len + sizeof(statusfile) + 1] = 0;
+       fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
        delete filename;
 
        if (fd < 0) {
@@ -491,22 +520,22 @@ bool IoTQuery::openStatusFile() {
 
        /* Read in queue size, oldest sequence number, and newest sequence number. */
        int size;
-       int needwrite=0;
+       int needwrite = 0;
        if (doread(fd, &size, sizeof(size), OFFSET_MAX))
-               numqueueentries=size;
+               numqueueentries = size;
        else
-               needwrite=1;
+               needwrite = 1;
 
        long long entry;
        if (doread(fd, &entry, sizeof(entry), OFFSET_OLD))
-               oldestentry=entry;
+               oldestentry = entry;
        else
-               needwrite=1;
+               needwrite = 1;
 
        if (doread(fd, &entry, sizeof(entry), OFFSET_NEW))
-               newestentry=entry;
+               newestentry = entry;
        else
-               needwrite=1;
+               needwrite = 1;
 
        if (needwrite)
                updateStatusFile();