191ffc4cde0b069ed9a3a74fb4f093f7b9086423
[iotcloud.git] / src / server / iotquery.cpp
1 #include "iotquery.h"
2 #include <string.h>
3 #include <sys/stat.h>
4 #include <sys/types.h>
5 #include <sys/file.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9
10 using namespace std;
11
12 const char * query_str="QUERY_STRING";
13 const char * uri_str="REQUEST_URI";
14 const char * method_str="REQUEST_METHOD";
15 const char * iotcloudroot_str="IOTCLOUD_ROOT";
16 const char * length_str="CONTENT_LENGTH";
17
18 IoTQuery::IoTQuery(FCGX_Request *request) :
19   request(request),
20   data(NULL),
21   directory(NULL),
22   uri(NULL),
23   query(NULL),
24   method(NULL),
25   iotcloudroot(NULL),
26   dir(NULL),
27   length(0),
28   firstentry(0),
29   lastentry(0),
30   requestsequencenumber(0),
31   numqueueentries(DEFAULT_SIZE),
32   fd(-1)
33 {
34 }
35
36 IoTQuery::~IoTQuery() {
37   if (fd >= 0)
38     close(fd);
39   if (directory)
40     delete directory;
41   if (data)
42     delete data;
43   if (dir != NULL)
44     closedir(dir);
45 }
46
47 bool IoTQuery::checkDirectory() {
48   struct stat s;
49   int err=stat(directory, &s);
50   if (-1 == err)
51     return false;
52   return S_ISDIR(s.st_mode);
53 }
54
55 void IoTQuery::decodeQuery() {
56   int len=strlen(query);
57   char * str=new char[len+1];
58   memcpy(str, query, len+1);
59   char *tok_ptr=str;
60   
61   /* Parse commands */
62   char *command=strsep(&tok_ptr, "&");
63   if (strncmp(command, "putslot", 7) == 0)
64     reqPutSlot = true;
65
66   if (strncmp(command, "getslot", 7) == 0)
67     reqGetSlot = true;
68   
69   /* Load Sequence Number for request */
70   char *sequencenumber_str = strsep(&tok_ptr, "&");
71
72   if (sequencenumber_str != NULL)
73     requestsequencenumber = strtol(sequencenumber_str, NULL, 10);
74
75   /* Update size if we get request */
76   char * numqueueentries_str = tok_ptr;
77   if (numqueueentries_str != NULL)
78     numqueueentries = strtol(numqueueentries_str, NULL, 10);
79   
80   delete str;
81 }
82
83 void IoTQuery::getSlot() {
84   
85 }
86
87 void IoTQuery::putSlot() {
88   
89 }
90
91 void IoTQuery::processQuery() {
92   getQuery();
93   getDirectory();
94   readData();
95   
96   if (strncmp(method, "POST", 4) != 0)
97     return;
98   
99   if (directory == NULL ||
100       !checkDirectory())
101     return;
102   
103   if (!openStatusFile())
104     return;
105   
106   flock(fd, LOCK_EX);
107
108   decodeQuery();
109
110   if (reqGetSlot)
111     getSlot();
112   else if (reqPutSlot)
113     putSlot();
114   else return;
115 }
116
117 void IoTQuery::readData() {
118   if (length) {
119     data = new char[length+1];
120     memset(data, 0, length+1);
121     cin.read(data, length);
122   }
123   do {
124     char dummy;
125     cin >> dummy;
126   } while (!cin.eof());
127 }
128
129 void IoTQuery::getQuery() {
130   uri = FCGX_GetParam(uri_str, request->envp);
131   query = FCGX_GetParam(query_str, request->envp);
132   method = FCGX_GetParam(method_str, request->envp);
133   iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp);
134
135   char * reqlength = FCGX_GetParam(length_str, request->envp);
136   if (length) {
137     length=strtol(reqlength, NULL, 10);
138   } else {
139     length=0;
140   }
141 }
142
143 void IoTQuery::getDirectory() {
144   char * split = strchr((char *)uri, '?');
145   if (split == NULL)
146     return;
147   int split_len = (int) (split-uri);
148   int rootdir_len = strlen(iotcloudroot);
149   int directory_len = split_len + rootdir_len + 1;
150   directory = new char[directory_len];
151   memcpy(directory, iotcloudroot, rootdir_len);
152   memcpy(directory + rootdir_len, uri, split_len);
153   directory[directory_len]=0;
154 }
155
156 int doread(int fd, void *ptr, size_t count, off_t offset) {
157   do {
158     size_t bytesread=pread(fd, ptr, count, offset);
159     if (bytesread==count) {
160       return 1;
161     } else if (bytesread==0) {
162       return 0;
163     }
164   } while(1);  
165 }
166
167 void IoTQuery::updateStatusFile() {
168   pwrite(fd, &numqueueentries, sizeof(numqueueentries), OFFSET_MAX);
169   pwrite(fd, &firstentry, sizeof(firstentry), OFFSET_FIRST);
170   pwrite(fd, &lastentry, sizeof(lastentry), OFFSET_LAST);
171 }
172
173 bool IoTQuery::openStatusFile() {
174   char statusfile[]="queuestatus";
175   int len=strlen(directory);
176
177   char * filename=new char[len+sizeof(statusfile)+2];
178   memcpy(filename, directory, len);
179   filename[len]='/';
180   memcpy(filename+len+1, statusfile, sizeof(statusfile));
181   filename[len+sizeof(statusfile)+1]=0;
182   fd=open(filename, O_CREAT| O_RDWR, S_IRUSR| S_IWUSR);
183   delete filename;
184
185   if (fd < 0)
186     return false;
187   
188   int size;
189   int needwrite=0;
190   if (doread(fd, &size, sizeof(size), OFFSET_MAX))
191     numqueueentries=size;
192   else
193     needwrite=1;
194
195   long entry;
196   if (doread(fd, &entry, sizeof(entry), OFFSET_FIRST))
197     firstentry=entry;
198   else
199     needwrite=1;
200
201   if (doread(fd, &entry, sizeof(entry), OFFSET_LAST))
202     lastentry=entry;
203   else
204     needwrite=1;
205       
206   if (needwrite)
207     updateStatusFile();
208   
209   return true;
210 }
211
212