OSDN Git Service

[dennco] integrated engine related changes from denncoCreator
[dennco/dennco.git] / Source / DNServerHTTP.cpp
1 //  Copyright (c) 2012 Dennco Project
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 //
17 //  Created by tkawata on 1/28/2012.
18 //
19
20 #include "DNServerHTTPImpl.h"
21 #include "DNServerHTTP.h"
22 #include "DNServerBase.h"
23 #include "DNEngine.h"
24 #include "DNUtils.h"
25
26 #include <string>
27 #ifndef _MSC_VER
28     #include <string.h>
29 #endif
30 #include <stdio.h>
31
32 const unsigned int DNServerHTTP::HTTPDEFAULTPORT = 50000;
33
34
35 DNServerHTTP::DNServerHTTP(DNEngine* engine) : DNServerBase(engine)
36 {
37     impl = DNServerHTTPImpl::create(this, DNServerHTTP::clientRequestHandler);
38 }
39
40 DNServerHTTP::~DNServerHTTP()
41 {
42     if (impl)
43         delete impl;
44 }
45
46 bool DNServerHTTP::isRunning()
47 {
48     return impl->isRunning();
49 }
50
51 void DNServerHTTP::start()
52 {
53     impl->start();
54 }
55
56 void DNServerHTTP::stop()
57 {
58     impl->stop();
59 }
60
61 void DNServerHTTP::setPortNumber(unsigned int portNumber)
62 {
63     impl->setPortNumber(portNumber);
64 }
65
66 void DNServerHTTP::replyWithStatusCode(int code, const char* message)
67 {
68     impl->replyWithStatusCode(code, message);
69 }
70
71 void DNServerHTTP::replyWithFile(const char* filePath)
72 {
73     impl->replyWithFile(filePath);
74 }
75
76 //static
77 void DNServerHTTP::clientRequestHandler(DNServerHTTP *server, const char *path, const char *body)
78 {
79     bool valid = true;
80     std::string errorMsg;
81     const char *p = path;
82     if (strlen(p) > 7)
83     {
84         if (strncmp(p, "http://", 7) == 0)
85         {
86             p += 7;
87         }
88         else
89         {
90             valid = false;
91             errorMsg = "Request path is not a valid HTTP path";
92         }
93     }
94     else
95     {
96         valid = false;
97         errorMsg = "Request path is not correct";
98     }
99     
100     if (valid)
101     {
102         while(*p && *p != '/')
103             p++;
104     }
105     if (!*p)
106     {
107         valid = false;
108         errorMsg = "no request URL. It should be /get or /set";
109     }
110     
111     bool isUIRequest = false;
112     bool isQueryRequest = true;
113     const char *pathPart = p;
114     if (valid)
115     {
116         if (strlen(p) >= 3)
117         {
118             if (strncmp(p, "/ui",3) == 0)
119             {
120                 isUIRequest = true;
121             }
122         }
123         if (!isUIRequest && strlen(p) >= 4)
124         {
125             if (strncmp(p, "/get",4) == 0)
126             {
127                 isQueryRequest = true;
128                 p+=4;
129             }
130             else if (strncmp(p, "/set",4) == 0)
131             {
132                 isQueryRequest = false;
133                 p+=4;
134             }
135             else
136             {
137                 valid = false;
138                 errorMsg = "request path is not valid. It should be /get or /set";
139             }
140             
141         }
142     }
143     if (!isUIRequest && valid)
144     {
145         if (*p != 0 && *p != ' ' && *p != '?')
146         {
147             valid = false;
148             errorMsg = "request path is not valid. It should be /get or /set";
149         }
150     }
151     
152     if (valid)
153     {
154         std::string response;
155         if (isUIRequest)
156         {
157             server->doUIRequest(pathPart);
158         }
159         else if(isQueryRequest)
160         {
161             server->doQueryRequest(body);
162         }
163         else
164         {
165             server->doSetRequest(body);
166         }
167     }
168     else
169     {
170         server->doBadRequest(errorMsg);
171     }
172     
173 }
174
175 void DNServerHTTP::doQueryRequest(std::string requestBody)
176 {
177     const char *oc = requestBody.c_str();
178     size_t oclen = strlen(oc);
179     char *c = new char[oclen + 1];
180     strncpy(c, oc, oclen + 1);
181     
182     std::string resultString;
183     
184     const char *value = c;
185     const char *name = c;
186     bool       first = true;
187     while(*c)
188     {
189         c++;
190         
191         switch (*c)
192         {
193             case '&':
194             case 0:
195                 *c = 0;
196                 
197                 if (value != name)
198                 {
199                     if (strlen(name) == 4 && strncmp(name, "path", 4) == 0)
200                     {
201                         //valid request. do the query
202                         float result = mEngine->doClientGetRequest(value);
203                         if (!first)
204                             resultString.append(1,',');
205                         
206                         char rs[16];
207                         sprintf(rs, "%12f", result);
208                         resultString.append(rs);
209                     }
210                 }
211                 name = c + 1;
212                 break;
213                 
214             case '=':
215                 *c = 0;
216                 value = c + 1;
217                 break;
218         }
219     }
220     replyWithStatusCode(200, resultString.c_str());
221 }
222
223 void DNServerHTTP::doSetRequest(std::string requestBody)
224 {
225     const char *oc = requestBody.c_str();
226     size_t oclen = strlen(oc);
227     char *c = new char[oclen + 1];
228     strncpy(c, oc, oclen + 1);
229     
230     std::string resultString;
231     
232     const char *value = c;
233     const char *name = c;
234     int        cnt = 0;
235     while(*c)
236     {
237         c++;
238         
239         switch (*c)
240         {
241             case '&':
242             case 0:
243                 *c = 0;
244                 
245                 if (value != name)
246                 {
247                     mEngine->doClientSetRequest(name, value);
248                     cnt++;
249                 }
250                 name = c + 1;
251                 break;
252                 
253             case '=':
254                 *c = 0;
255                 value = c + 1;
256                 break;
257         }
258     }
259     
260     char rs[16];
261     sprintf(rs, "%12d", cnt);
262     replyWithStatusCode(200, rs);
263 }
264
265 void DNServerHTTP::doUIRequest(const char *path)
266 {
267     std::string filepath = getContentPath();
268     trimString(filepath);
269     if (filepath.at(filepath.length()-1) != '/')
270     {
271         filepath.append(1,'/');
272     }
273     filepath.append(path+1);
274     replyWithFile(filepath.c_str());
275     
276 }
277
278 void DNServerHTTP::doBadRequest(std::string errorMsg)
279 {
280     replyWithStatusCode(400, errorMsg.c_str());
281 }
282
283 std::string DNServerHTTP::getContentPath()
284 {
285     return mEngine->getContainerRootPath();
286 }
287 /*
288 //static
289 DNHTTPRequest* DNServerHTTP::parseHttpRequest(const char *message)
290 {
291     size_t len = strlen(message);
292     
293     bool isPost = false;
294     bool isValid = true;
295     std::string path;
296     std::string host;
297     int contentLen = 0;
298     std::string postbody;
299     
300     const char *p;
301     if (len < 5)
302     {
303         //illegal message
304         return NULL;
305     }
306     if (strncmp(message, "POST ", 5) == 0)
307     {
308         //POST message
309         p = message + 4;
310         isPost = true;
311     }
312     else if (strncmp(message, "GET ", 4) == 0)
313     {
314         //GET message
315         p = message + 3;
316         isPost = false;
317     }
318     else
319     {
320         //non supported message
321         isValid = false;
322     }
323     
324     //get URI
325     if (isValid)
326     {
327         while (*p && *p == ' ' && *p != '\r' && *p != '\n')
328         {
329             p++;
330         }
331         if (!*p || *p == '\r' || *p == '\n')
332         {
333             isValid = false;
334         }
335         else
336         {
337             const char *s = p;
338             while (*p && *p != ' ' &&  *p != '\r' && *p != '\n')
339                 p++;
340             
341             if (*p != ' ' && p - s < 1)
342             {
343                 isValid = false;
344             }
345             else
346             {
347                 path = std::string(s, p - s);
348             }
349         }
350     }
351     
352     if (isValid)
353     {
354         while(*p)
355         {
356             if (*p == '\n' && *(p-1) == '\r')
357             {
358                 break;
359             }
360             p++;
361         }
362         if (!*p)
363             isValid = false;
364     }
365     
366     if (isValid)
367     {
368         p++;
369         const char *hs = p;
370         const char *he = p-1;
371         while (*p)
372         {
373             if (*p == '\n' && *(p-1) == '\r' && *(p-2) == '\n')
374             {
375                 he = p;
376             }
377             p++;
378         }
379         
380         p = hs;
381         while(p <= he && *p)
382         {
383             if (*p == ':')
384             {
385                 //Host:
386                 if (p-hs >= 5 && strncmp("Host", p-4, 4))
387                 {
388                     p++;
389                     const char *tmp = p;
390                     while(p <= hs && *p && *p !='\r')
391                     {
392                         p++;
393                     }
394                     if (tmp < p - 1)
395                     {
396                         host = std::string(tmp, p - tmp - 1);
397                     }
398                 }
399                 
400                 //Content-Length:
401                 if (p-hs >= 15 && strncmp("Content-Length", p-14,14))
402                 {
403                     p++;
404                     const char *tmp = p;
405                     while(p <= hs && *p && *p !='\r')
406                     {
407                         p++;
408                     }
409                     if (tmp < p - 1)
410                     {
411                         contentLen = atoi(std::string(tmp, p - tmp - 1).c_str());
412                     }                    
413                 }
414             }
415             
416             p++;
417         }
418         
419         //POST BODY
420         if (isPost && contentLen>0)
421         {
422             int bl = 0;
423             const char *ps = he+1;
424             while (*(ps + bl) && bl < contentLen)
425             {
426                 bl++;
427             }
428             
429             postbody = std::string(ps, bl);
430         }
431     }
432     
433     if (isValid)
434     {
435         DNHTTPRequest *request = new DNHTTPRequest();
436         request->isPost = isPost;
437         request->uri = path;
438         if (isPost)
439         {
440             request->postData = postbody;
441         }
442         return request;
443     }
444     else
445     {
446         return NULL;
447     }
448 }
449  */
450