Merge pull request #14 from jtanx/master
[matches/MCTX3420.git] / testing / fastcgi-approach / fastcgi.c
1 /**
2  * @file fastcgi.c
3  * @purpose Runs the FCGI request loop to handle web interface requests.
4  * 
5  * fcgi_stdio.h must be included before all else so the stdio function
6  * redirection works ok.
7  */
8  
9 #include <fcgi_stdio.h>
10 #include "fastcgi.h"
11 //#include "common.h"
12
13 /**
14  * Extracts a key/value pair from a request string.
15  * Note that the input is modified by this function.
16  * @param in The string from which to extract the pair
17  * @param key A pointer to a variable to hold the key string
18  * @param value A pointer to a variable to hold the value string
19  * @return A pointer to the start of the next search location, or NULL if
20  *         the EOL is reached.
21  */
22 char *FCGI_KeyPair(char *in, const char **key, const char **value)
23 {
24         char *ptr;
25         if (!in || !*in) { //Invalid input or string is EOL
26                 return NULL;
27         }
28
29         *key = in;
30         //Find either = or &, whichever comes first
31         if ((ptr = strpbrk(in, "=&"))) {
32                 if (*ptr == '&') { //No value specified
33                         *value = ptr;
34                         *ptr++ = 0;
35                 } else {
36                         //Stopped at an '=' sign
37                         *ptr++ = 0;
38                         *value = ptr;
39                         if ((ptr = strchr(ptr,'&'))) {
40                                 *ptr++ = 0;
41                         } else {
42                                 ptr = "";
43                         }
44                 }
45         } else { //No value specified and no other pair
46                 ptr = "";
47                 *value = ptr;
48         }
49         return ptr;
50 }
51
52 /**
53  * Begins a response to the client in JSON format.
54  * @param status_code The HTTP status code to be returned.
55  * @param module The name of the module that initiated the response.
56  */
57 void FCGI_BeginJSON(StatusCodes status_code, const char *module)
58 {
59         switch (status_code) {
60                 case STATUS_OK:
61                         break;
62                 case STATUS_UNAUTHORIZED:
63                         printf("Status: 401 Unauthorized\r\n");
64                         break;
65                 default:
66                         printf("Status: 400 Bad Request\r\n");
67         }
68         printf("Content-type: application/json; charset=utf-8\r\n\r\n");
69         printf("{\r\n");
70         printf("\t\"module\" : \"%s\"", module);
71 }
72
73 /**
74  * Adds a key/value pair to a JSON response. The response must have already
75  * been initiated by FCGI_BeginJSON. Note that characters are not escaped.
76  * @param key The key of the JSON entry
77  * &param value The value associated with the key.
78  */
79 void FCGI_BuildJSON(const char *key, const char *value)
80 {
81         printf(",\r\n\t\"%s\" : \"%s\"", key, value);
82 }
83
84 /**
85  * Ends a JSON response that was initiated by FCGI_BeginJSON.
86  */
87 void FCGI_EndJSON() 
88 {
89         printf("\r\n}\r\n");
90 }
91
92 /**
93  * Main FCGI request loop that receives/responds to client requests.
94  * @param data A data field to be passed to the selected module handler.
95  */ 
96 void FCGI_RequestLoop (void *data)
97 {
98         int count = 0;
99         while (FCGI_Accept() >= 0)   {
100                 ModuleHandler module_handler = NULL;
101                 char module[BUFSIZ], params[BUFSIZ];
102
103                 //strncpy doesn't zero-truncate properly
104                 snprintf(module, BUFSIZ, "%s", getenv("DOCUMENT_URI_LOCAL"));
105                 snprintf(params, BUFSIZ, "%s", getenv("QUERY_STRING"));
106                 
107                 //Remove trailing slashes (if present) from module query
108                 size_t lastchar = strlen(module) - 1;
109                 if (lastchar > 0 && module[lastchar] == '/')
110                         module[lastchar] = 0;
111                 
112
113                 if (!strcmp("sensors", module)) {
114                         //module_handler = Handler_Sensors;
115                 } else if (!strcmp("actuators", module)) {
116                         
117                 }
118
119                 if (module_handler) {
120                         module_handler(data, params);
121                 } else {
122                         char buf[BUFSIZ];
123                         
124                         FCGI_BeginJSON(400, module);
125                         FCGI_BuildJSON("description", "400 Invalid response");
126                         snprintf(buf, BUFSIZ, "%d", count);
127                         FCGI_BuildJSON("request-number", buf);
128                         FCGI_BuildJSON("params", params);
129                         FCGI_BuildJSON("host", getenv("SERVER_HOSTNAME"));
130                         FCGI_EndJSON();
131                 }
132
133                 count++;
134         }
135 }

UCC git Repository :: git.ucc.asn.au