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