more code
[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   numqueueentries(DEFAULT_SIZE),
31   fd(-1)
32 {
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 int IoTQuery::checkDirectory() {
47   struct stat s;
48   int err=stat(directory, &s);
49   if (-1 == err)
50     return 0;
51   return S_ISDIR(s.st_mode);
52 }
53
54 void IoTQuery::processQuery() {
55   parseQuery();
56   getDirectory();
57   readData();
58
59   if (strncmp(method, "POST", 4) != 0)
60     return;
61   
62   if (directory == NULL ||
63       checkDirectory())
64     return;
65   
66   if (openStatusFile() < 0)
67     return;
68
69   flock(fd, LOCK_EX);
70   
71   cout << "Content-type: text/html\r\n"
72        << "\r\n"
73        << "<html>\n"
74        << "  <head>\n"
75        << "    <title>Hello, World!</title>\n"
76        << "  </head>\n"
77        << "  <body>\n"
78        << "    <h1>Hello, World!</h1>\n"
79        << "  </body>\n";
80   
81   cout << uri_str << " " << uri << "\n";
82   cout << query_str << " " << query << "\n";
83   cout << method_str << " " << method << "\n";
84   cout << iotcloudroot_str << " " << iotcloudroot << "\n";
85   if (data)
86     cout << "[" << data << "]";      
87   
88   
89   
90   cout << "</html>\n";
91 }
92
93
94 void IoTQuery::readData() {
95   if (length) {
96     data = new char[length+1];
97     memset(data, 0, length+1);
98     cin.read(data, length);
99   }
100   do {
101     char dummy;
102     cin >> dummy;
103   } while (!cin.eof());
104 }
105
106 void IoTQuery::parseQuery() {
107   uri = FCGX_GetParam(uri_str, request->envp);
108   query = FCGX_GetParam(query_str, request->envp);
109   method = FCGX_GetParam(method_str, request->envp);
110   iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp);
111
112   char * reqlength = FCGX_GetParam(length_str, request->envp);
113   if (length) {
114     length=strtol(reqlength, NULL, 10);
115   } else {
116     length=0;
117   }
118 }
119
120 void IoTQuery::getDirectory() {
121   char * split = strchr((char *)uri, '?');
122   if (split == NULL)
123     return;
124   int split_len = (int) (split-uri);
125   int rootdir_len = strlen(iotcloudroot);
126   int directory_len = split_len + rootdir_len + 1;
127   directory = new char[directory_len];
128   memcpy(directory, iotcloudroot, rootdir_len);
129   memcpy(directory + rootdir_len, uri, split_len);
130   directory[directory_len]=0;
131 }
132
133 int doread(int fd, void *ptr, size_t count, off_t offset) {
134   do {
135     size_t bytesread=pread(fd, ptr, count, offset);
136     if (bytesread==count) {
137       return 1;
138     } else if (bytesread==0) {
139       return 0;
140     }
141   } while(1);  
142 }
143
144 void IoTQuery::updateStatusFile() {
145   pwrite(fd, &numqueueentries, sizeof(numqueueentries), OFFSET_MAX);
146   pwrite(fd, &firstentry, sizeof(firstentry), OFFSET_FIRST);
147   pwrite(fd, &lastentry, sizeof(lastentry), OFFSET_LAST);
148 }
149
150 int IoTQuery::openStatusFile() {
151   char statusfile[]="queuestatus";
152   int len=strlen(directory);
153
154   char * filename=new char[len+sizeof(statusfile)+2];
155   memcpy(filename, directory, len);
156   filename[len]='/';
157   memcpy(filename+len+1, statusfile, sizeof(statusfile));
158   filename[len+sizeof(statusfile)+1]=0;
159   fd=open(filename, O_CREAT| O_RDWR, S_IRUSR| S_IWUSR);
160   delete filename;
161
162   if (fd < 0)
163     return fd;
164   
165   int size;
166   int needwrite=0;
167   if (doread(fd, &size, sizeof(size), OFFSET_MAX))
168     numqueueentries=size;
169   else
170     needwrite=1;
171
172   long entry;
173   if (doread(fd, &entry, sizeof(entry), OFFSET_FIRST))
174     firstentry=entry;
175   else
176     needwrite=1;
177
178   if (doread(fd, &entry, sizeof(entry), OFFSET_LAST))
179     lastentry=entry;
180   else
181     needwrite=1;
182       
183   if (needwrite)
184     updateStatusFile();
185   
186   return fd;
187 }
188
189