Merge branch 'master' of https://github.com/jtanx/MCTX3420 into jtanx-master
authorSam Moore <[email protected]>
Thu, 15 Aug 2013 05:27:12 +0000 (13:27 +0800)
committerSam Moore <[email protected]>
Thu, 15 Aug 2013 05:27:12 +0000 (13:27 +0800)
Conflicts:
server/log.c
server/main.c

Merged in Jeremy's changes to log functions with my changes
to the documentation.

.gitignore [new file with mode: 0644]
server/log.c
server/log.h
server/main.c
testing/fastcgi-approach/README.txt [new file with mode: 0644]
testing/fastcgi-approach/fastcgi_test.c [new file with mode: 0644]
testing/fastcgi-approach/nginx_server_config.txt [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..baf45a8
--- /dev/null
@@ -0,0 +1,12 @@
+*.so
+*.o
+*.exe
+*.dll
+
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
\ No newline at end of file
index 62fe890..6f44bb0 100644 (file)
@@ -11,7 +11,7 @@
 #include "options.h"
 
 // --- Static variables --- //
-static char * unspecified_funct = (char*)"???";
+static const char * unspecified_funct = "???";
 
 // --- Function implementations --- //
 
@@ -24,36 +24,41 @@ static char * unspecified_funct = (char*)"???";
  * @param fmt - A format string
  * @param ... - Arguments to be printed according to the format string
  */
-void Log(int level, char * funct, char * fmt, ...)
+void LogEx(int level, const char * funct, ...)
 {
+       const char *fmt;
+       va_list va;
+       va_start(va, funct);
+       fmt = va_arg(va, const char*);
+       
        if (fmt == NULL) // sanity check
-               Fatal("Log", "Format string is NULL");
+               FatalEx("Log", "Format string is NULL");
 
        // Don't print the message unless we need to
-       if (level > g_options.verbosity) 
+       if (level > g_options.verbosity)
                return;
 
        if (funct == NULL)
                funct = unspecified_funct;
 
        // Make a human readable severity string
-       char severity[BUFSIZ];
+       const char *severity;
        switch (level)
        {
                case LOGERR:
-                       sprintf(severity, "ERROR");
+                       severity = "ERROR";
                        break;
                case LOGWARN:
-                       sprintf(severity, "WARNING");
+                       severity = "WARNING";
                        break;
                case LOGNOTE:
-                       sprintf(severity, "NOTICE");
+                       severity = "NOTICE";
                        break;
                case LOGINFO:
-                       sprintf(severity, "INFO");
+                       severity = "INFO";
                        break;
                default:
-                       sprintf(severity, "DEBUG");
+                       severity = "DEBUG";
                        break;
        }
 
@@ -61,8 +66,6 @@ void Log(int level, char * funct, char * fmt, ...)
        fprintf(stderr, "%s [%d] : %s : %s - ", g_options.program, getpid(), severity, funct);
 
        // Then pass additional arguments with the format string to vfprintf for printing
-       va_list va;
-       va_start(va, fmt);
        vfprintf(stderr, fmt, va);
        va_end(va);
 
@@ -72,19 +75,23 @@ void Log(int level, char * funct, char * fmt, ...)
 
 /**
  * Handle a Fatal error in the program by printing a message and exiting the program
      CALLING THIS FUNCTION WILL CAUSE THE PROGAM TO EXIT
*     CALLING THIS FUNCTION WILL CAUSE THE PROGAM TO EXIT
  * @param funct - Name of the calling function
  * @param fmt - A format string
  * @param ... - Arguments to be printed according to the format string
  */
-void Fatal(char * funct, char * fmt, ...)
+void FatalEx(const char * funct, ...)
 {
+       const char *fmt;
+       va_list va;
+       va_start(va, funct);
+       fmt = va_arg(va, const char*);
        
        if (fmt == NULL)
        {
                // Fatal error in the Fatal function.
                // (This really shouldn't happen unless someone does something insanely stupid)
-               Fatal("Fatal", "Format string is NULL");
+               FatalEx("Fatal", "Format string is NULL");
                return; // Should never get here
        }
 
@@ -93,8 +100,6 @@ void Fatal(char * funct, char * fmt, ...)
 
        fprintf(stderr, "%s [%d] : %s : FATAL - ", g_options.program, getpid(), funct);
 
-       va_list va;
-       va_start(va, fmt);
        vfprintf(stderr, fmt, va);
        va_end(va);
        fprintf(stderr, "\n");
index 99d54d0..6db52f6 100644 (file)
 #include <stdbool.h>
 #include <stdarg.h>
 
+//To get around a 'pedantic' C99 rule that you must have at least 1 variadic arg, combine fmt into that.
+#define Log(level, ...) LogEx(level, __func__, __VA_ARGS__)
+#define Fatal(...) FatalEx(__func__, __VA_ARGS__)
 
 // An enum to make the severity of log messages human readable in code
 enum {LOGERR=0, LOGWARN=1, LOGNOTE=2, LOGINFO=3,LOGDEBUG=4};
 
-extern void Log(int level, char * funct, char * fmt,...); // General function for printing log messages to stderr
-extern void Fatal(char * funct, char * fmt, ...); // Function that deals with a fatal error (prints a message, then exits the program).
+extern void LogEx(int level, const char * funct, ...); // General function for printing log messages to stderr
+extern void FatalEx(const char * funct, ...); // Function that deals with a fatal error (prints a message, then exits the program).
 
 #endif //_LOG_H
 
index 56794f2..61ba76d 100644 (file)
@@ -30,7 +30,7 @@ void ParseArguments(int argc, char ** argv)
 {
        g_options.program = argv[0]; // program name
        g_options.verbosity = LOGDEBUG; // default log level
-       Log(LOGDEBUG, "ParseArguments", "Called as %s with %d arguments.", g_options.program, argc);
+       Log(LOGDEBUG, "Called as %s with %d arguments.", g_options.program, argc);
 }
 
 /**
@@ -41,7 +41,7 @@ void SignalHandler(int signal)
 {
        // At the moment just always exit.
        // Call `exit` so that Cleanup will be called to... clean up.
-       Log(LOGWARN, "SignalHandler", "Got signal %d (%s). Exiting.", signal, strsignal(signal));
+       Log(LOGWARN, "Got signal %d (%s). Exiting.", sig, strsignal(sig));
        exit(sig);
 }
 
@@ -50,8 +50,8 @@ void SignalHandler(int signal)
  */
 void Cleanup()
 {
-       Log(LOGDEBUG, "Cleanup", "Begin cleanup.");
-       Log(LOGDEBUG, "Cleanup", "Finish cleanup.");
+       Log(LOGDEBUG, "Begin cleanup.");
+       Log(LOGDEBUG, "Finish cleanup.");
 
 }
 
@@ -63,6 +63,7 @@ void Cleanup()
  */
 int main(int argc, char ** argv)
 {
+       ParseArguments(argc, argv, &g_options);
        return 0;
 }
 
diff --git a/testing/fastcgi-approach/README.txt b/testing/fastcgi-approach/README.txt
new file mode 100644 (file)
index 0000000..29cfd2c
--- /dev/null
@@ -0,0 +1,20 @@
+The application could be quite easily made to use FastCGI. Unlike normal CGI,
+with FastCGI (fcgi), the process is executed once, and continues to run. The
+process will receive responses from the browser in the response loop. Hence,
+sensor data can be read in another thread while the response loop runs.
+
+Setup:
+Compile fastcgi_test.c with: (the libfcgi-dev package must be installed)
+gcc fastcgi_test.c -lfcgi -o fastcgi_test
+
+Configure nginx to pass all requests to the address /cgi/ to the application:
+Edit /etc/nginx/sites-enabled/default by adding the contents of nginx_server_config.txt
+
+Restart nginx:
+/etc/init.d/nginx restart
+
+Run the application:
+spawn-fcgi -p9005 -n ./fastcgi_test
+
+You can see the results at:
+http://your.domain/cgi
\ No newline at end of file
diff --git a/testing/fastcgi-approach/fastcgi_test.c b/testing/fastcgi-approach/fastcgi_test.c
new file mode 100644 (file)
index 0000000..40543c6
--- /dev/null
@@ -0,0 +1,67 @@
+#include "fcgi_stdio.h" /* fcgi library; put it first*/
+#include <stdlib.h>
+
+/*
+       But the suggestion was: FunctionName, variable_name (local or member),
+    Structure, ENUMVALUE, Extern_FunctionName, g_global
+*/
+
+typedef struct Data Data;
+
+typedef void (*ModuleHandler) (Data *data, const char *params);
+
+static void SensorsHandler(Data *data, const char *params) {
+    printf("Sensors module!<br>");
+}
+
+/*
+   API Schema:
+   Sensors:
+   /cgi/sensors?get=x
+   *get=x is optional. Retrieves info for sensor with id x
+   Devices:
+   /cgi/devices?status=x&power=y&id=z
+   *status and power is optional
+   *status retrieves whether device with id x is operational
+   *power tells whether or not to power on/off the device with id z
+   
+   Response format:
+   200 OK if request was ok
+   400 bad request for malformed request
+      
+*/
+int main (int argc, char *argv[])
+{
+  Data *data = NULL;
+  int count = 0;
+
+  //FCGI Accept loop
+  while (FCGI_Accept() >= 0)   {
+    ModuleHandler module_handler = NULL;
+    const char *module = getenv("DOCUMENT_URI_LOCAL");
+    const char *params = getenv("QUERY_STRING");
+
+    if (!strcmp("sensors", module)) {
+        module_handler = SensorsHandler; //Replace with pointer to sensors handler
+    } else if (!strcmp("admin"), module) {
+        module_handler = NULL; //Replace with pointer to admin handler
+        printf("Admin module selected!\n");
+    }
+    
+    if (module_handler) {
+        printf("Content-type: text/html\r\n\r\n"); //Replace with actual type
+        module_handler(data, params);
+    } else {
+        printf("Status: 400 Bad Request\r\n"
+               "Content-type: text/html\r\n\r\n"
+               "<title>400 Bad Request</title>\n"
+               "Unknown module '%s' selected.<br>\n",
+               module);   
+    }
+    
+    //Debgging:
+    printf("Module: %s, Params: %s<br>\n", module, params);
+    printf("Request number %d, host <i>%s</i>\n",
+        count++, getenv("SERVER_HOSTNAME"));
+  }
+}
diff --git a/testing/fastcgi-approach/nginx_server_config.txt b/testing/fastcgi-approach/nginx_server_config.txt
new file mode 100644 (file)
index 0000000..c76a4e5
--- /dev/null
@@ -0,0 +1,27 @@
+        #Custom cgi
+        location ~ ^/cgi/([^?]*) {
+                fastcgi_pass 127.0.0.1:9005;
+                fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
+                fastcgi_param  SERVER_HOSTNAME    mctxsoft;
+                fastcgi_param  SERVER_SOFTWARE    nginx;
+
+                #Regex removed /cgi/ part, and any args
+                fastcgi_param  DOCUMENT_URI_LOCAL  $1;
+                fastcgi_param  QUERY_STRING       $query_string;
+
+                #Unused for now
+                fastcgi_param  REQUEST_METHOD     $request_method;
+                fastcgi_param  CONTENT_TYPE       $content_type;
+                fastcgi_param  CONTENT_LENGTH     $content_length;
+                fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script$
+                fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
+                fastcgi_param  REQUEST_URI        $request_uri;
+                fastcgi_param  DOCUMENT_URI       $document_uri;
+                fastcgi_param  DOCUMENT_ROOT      $document_root;
+                fastcgi_param  SERVER_PROTOCOL    $server_protocol;
+                fastcgi_param  REMOTE_ADDR        $remote_addr;
+                fastcgi_param  REMOTE_PORT        $remote_port;
+                fastcgi_param  SERVER_ADDR        $server_addr;
+                fastcgi_param  SERVER_PORT        $server_port;
+                fastcgi_param  SERVER_NAME        $server_name;
+        }

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