From: Sam Moore Date: Tue, 13 Aug 2013 07:23:11 +0000 (+0800) Subject: Changed directory structure, updated READMEs X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=131ef1b39cd490d976012afb3bab211401f87a9d;p=matches%2FMCTX3420.git Changed directory structure, updated READMEs Create directory "rpi" for anything that runs on the Raspberry Pi. --- diff --git a/rpi/Makefile b/rpi/Makefile new file mode 100644 index 0000000..24310f3 --- /dev/null +++ b/rpi/Makefile @@ -0,0 +1,29 @@ +# Makefile for web2io testing stuff +CXX = gcc +FLAGS = -std=c99 -Wall -Werror -pedantic -g +LIB = +OBJ = network.o log.o webserver.o +RM = rm -f + +BIN = webserver + +$(BIN) : $(OBJ) + $(CXX) $(FLAGS) -o $(BIN) $(OBJ) + + +%.o : %.c + $(CXX) $(FLAGS) -c $< + + + +clean : + $(RM) $(BIN) + $(RM) *.o + +clean_full: #cleans up all backup files + $(RM) $(BIN) $(OBJ) $(LINKOBJ) + $(RM) *.*~ + $(RM) *~ + + + diff --git a/rpi/README b/rpi/README new file mode 100644 index 0000000..835ef0d --- /dev/null +++ b/rpi/README @@ -0,0 +1,7 @@ +This code will run on the Raspberry Pi server. + +The software will implement an interface between requests made by a browser using HTTP and low level sensors/control on the server. + +Multiple threads will be used; one running a HTTP server, and one or more for interacting with sensors/actuators. +A watchdog program should be created to start the main server program and handle software crashes. + diff --git a/rpi/log.c b/rpi/log.c new file mode 100644 index 0000000..3a8c55c --- /dev/null +++ b/rpi/log.c @@ -0,0 +1,67 @@ +#include "log.h" +#include "options.h" +#include + +static int last_len = 0; + +void log_print(int level, char * funct, char * fmt, ...) +{ + if (level > options.verbosity) + return; + + + + char severity[BUFSIZ]; + switch (level) + { + case LOGERR: + sprintf(severity, "ERROR"); + break; + case LOGWARN: + sprintf(severity, "WARNING"); + break; + case LOGNOTE: + sprintf(severity, "NOTICE"); + break; + case LOGINFO: + sprintf(severity, "INFO"); + break; + default: + sprintf(severity, "DEBUG"); + break; + } + + if (funct != NULL) + last_len = fprintf(stderr, "%s [%d] : %s : %s - ", options.program, getpid(), severity, funct); + else + { + for (int i = 0; i < last_len; ++i); + fprintf(stderr, " "); + } + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + fprintf(stderr, "\n"); +} + +void error(char * funct, char * fmt, ...) +{ + if (funct != NULL) + last_len = fprintf(stderr, "%s [%d] : Fatal error in %s - ", options.program, getpid(), funct); + else + { + for (int i = 0; i < last_len; ++i) + fprintf(stderr, " "); + fprintf(stderr, "Fatal - "); + } + va_list va; + va_start(va, fmt); + vfprintf(stderr, fmt, va); + va_end(va); + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + + diff --git a/rpi/log.h b/rpi/log.h new file mode 100644 index 0000000..75e2780 --- /dev/null +++ b/rpi/log.h @@ -0,0 +1,17 @@ +#ifndef _LOG_H +#define _LOG_H + +#include +#include +#include + +#include + +enum {LOGERR=0, LOGWARN=1, LOGNOTE=2, LOGINFO=3,LOGDEBUG=4}; + +extern void log_print(int level, char * funct, char * fmt,...); +extern void error(char * funct, char * fmt, ...); + +#endif //_LOG_H + +//EOF diff --git a/rpi/network.c b/rpi/network.c new file mode 100644 index 0000000..1a1b862 --- /dev/null +++ b/rpi/network.c @@ -0,0 +1,174 @@ +#include "network.h" +#include +#include +#include +#include "log.h" + +#define h_addr h_addr_list[0] + + + + + +int Network_get_port(int sfd) +{ + static struct sockaddr_in sin; + static socklen_t len = sizeof(struct sockaddr_in); + + if (getsockname(sfd, (struct sockaddr *)&sin, &len) != 0) + error("Network_port", "getsockname : %s", strerror(errno)); + return ntohs(sin.sin_port); +} + +int Network_server_bind(int port, int * bound) +{ + int sfd = socket(PF_INET, SOCK_STREAM, 0); + if (sfd < 0) + { + error("Network_server", "Creating socket on port %d : %s", port, strerror(errno)); + } + + struct sockaddr_in name; + + name.sin_family = AF_INET; + name.sin_addr.s_addr = htonl(INADDR_ANY); + name.sin_port = htons(port); + + if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0) + { + error("Network_server", "Binding socket on port %d : %s", port, strerror(errno)); + } + + if (bound != NULL) + *bound = Network_get_port(sfd); + return sfd; +} + +int Network_server_listen(int sfd, char * addr) +{ + int port = Network_get_port(sfd); + if (listen(sfd, 1) < 0) + { + error("Network_server", "Listening on port %d : %s", port, strerror(errno)); + } + + int psd; + if (addr == NULL) + psd = accept(sfd, 0, 0); + else + { + struct sockaddr_in client; + struct hostent *hp; + + client.sin_family = AF_INET; + hp = gethostbyname(addr); + bcopy ( hp->h_addr, &(client.sin_addr.s_addr), hp->h_length); + client.sin_port = htons(port); + socklen_t len = sizeof(client); + + psd = accept(sfd, (struct sockaddr*)&client, &len); + } + //close(sfd); // don't close the bind socket here; we might want to reuse the port + assert(psd >= 0); + return psd; +} + +int Network_server(char * addr, int port) +{ + int bind = Network_server_bind(port, &port); + int sfd = Network_server_listen(bind, addr); + close(bind); // won't be able to reuse the port (it goes into TIME_WAIT) + return sfd; +} + +int Network_client(const char * addr, int port, int timeout) +{ + int sfd = socket(PF_INET, SOCK_STREAM, 0); + + //log_print(2, "Network_client", "Created socket"); + long arg = fcntl(sfd, F_GETFL, NULL); + arg |= O_NONBLOCK; + fcntl(sfd, F_SETFL, arg); + + if (sfd < 0) + { + error("Network_client", "Creating socket for address %s:%d : %s", addr, port, strerror(errno)); + } + struct sockaddr_in server; + struct hostent *hp; + + + server.sin_family = AF_INET; + hp = gethostbyname(addr); + if (hp == NULL) + { + error("Network_client", "Can't get host by name %s", addr); + } + bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length); + server.sin_port = htons(port); + + + int res = connect(sfd, (struct sockaddr *) &server, sizeof(server)); + + + if (res < 0 && errno == EINPROGRESS) + { + + fd_set writeSet; + FD_ZERO(&writeSet); + FD_SET(sfd, &writeSet); + + struct timeval tv; + tv.tv_sec = timeout; + tv.tv_usec = 0; + + struct timeval * tp; + tp = (timeout < 0) ? NULL : &tv; + + int err = select(sfd+1, NULL, &writeSet, NULL, tp); + + if (err == 0) + { + error("Network_client", "Timed out trying to connect to %s:%d after %d seconds", addr, port, timeout); + } + else if (err < 0) + { + error("Network_client", "Connecting to %s:%d - Error in select(2) call : %s", addr, port, strerror(errno)); + } + else if (FD_ISSET(sfd, &writeSet)) + { + int so_error; + socklen_t len = sizeof so_error; + getsockopt(sfd, SOL_SOCKET, SO_ERROR, &so_error, &len); + if (so_error != 0) + { + error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(so_error)); + } + } + else + { + error("Network_client", "select(2) returned %d but the socket is not writable!?", err); + } + } + else + { + error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(errno)); + } + + arg = fcntl(sfd, F_GETFL, NULL); + arg &= (~O_NONBLOCK); + fcntl(sfd, F_SETFL, arg); + + + + return sfd; +} + +void Network_close(int sfd) +{ + if (shutdown(sfd, 2) != 0) + { + error("Network_close", "Closing socket : %s", strerror(errno)); + } + close(sfd); +} diff --git a/rpi/network.h b/rpi/network.h new file mode 100644 index 0000000..07c9459 --- /dev/null +++ b/rpi/network.h @@ -0,0 +1,29 @@ +#ifndef _NETWORK_H +#define _NETWORK_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int Network_get_port(int socket); // get port used by socket +extern int Network_server(char * addr, int port); +extern int Network_client(const char * addr, int port, int timeout); + +extern int Network_server_bind(int port, int * bound); +extern int Network_server_listen(int sfd, char * addr); + +extern void Network_close(int sfd); + +#endif //_NETWORK_H + +//EOF diff --git a/rpi/options.h b/rpi/options.h new file mode 100644 index 0000000..2a6d323 --- /dev/null +++ b/rpi/options.h @@ -0,0 +1,20 @@ +/** + * @file options.h + * @purpose Declaration of structure to handle options passed to program + */ + +#include + +typedef struct +{ + const char * program; //name of program + uint8_t verbosity; // verbosity level + int port; // port to use for webserver + int bound_sfd; // socket webserver has bound to + int sfd; // socket connected to client + +} Options; + + + +extern Options options; diff --git a/rpi/webserver.c b/rpi/webserver.c new file mode 100644 index 0000000..6ff4f46 --- /dev/null +++ b/rpi/webserver.c @@ -0,0 +1,243 @@ +/** + * @file webserver.c + * @purpose Test implementing a minimalistic webserver + * + */ + +#define _POSIX_C_SOURCE 200809L // needed for some POSIX stuff to work + +// --- Standard headers --- // +#include +#include +#include // string helper functions +#include // character types +#include // for signal handling + +// --- Custom headers --- // +#include "log.h" // C functions to handle logging +#include "options.h" // Options structure +#include "network.h" // C functions to handle low level networking + +// --- Variable definitions --- // +Options options; // declared in "options.h" + +// --- Function definitions --- // + +/** + * @funct ParseArguments + * @purpose Parse Arguments and setup the global options variable + * @param argc - Num args + * @param argv - Array of args + */ +void ParseArguments(int argc, char ** argv) +{ + options.program = argv[0]; + options.verbosity = LOGDEBUG; + if (argc > 1) + options.port = atoi(argv[1]); // Allow us change the port for testing (I keep getting "address in use" errors) + else + options.port = 8080; // Using 8080 instead of 80 for now because to use 80 you have to run the program as root + options.sfd = -1; + options.bound_sfd = -1; + log_print(LOGDEBUG, "ParseArguments", "Called as %s with %d arguments.", options.program, argc); +} + +/** + * @funct SignalHandler + * @purpose Handle signals + * @param sig - The signal + */ +void SignalHandler(int sig) +{ + // At the moment just always exit. + // Call `exit` so that Cleanup will be called to... clean up. + log_print(LOGWARN, "SignalHandler", "Got signal %d (%s). Exiting.", sig, strsignal(sig)); + exit(sig); +} + +/** + * @funct Cleanup + * @purpose Called when program exits + */ +void Cleanup() +{ + log_print(LOGDEBUG, "Cleanup", "Begin cleanup."); + if (options.sfd >= 0) + { + Network_close(options.sfd); // close socket + options.sfd = -1; + } + if (options.bound_sfd >= 0) + { + Network_close(options.bound_sfd); // unbind + options.bound_sfd = -1; + } + log_print(LOGDEBUG, "Cleanup", "Unbound from port %d successfully", options.port); + log_print(LOGDEBUG, "Cleanup", "Done."); + +} + + +/** + * @funct Get + * @purpose Respond to a GET request + * @param request - The request string + * @param sfd - Socket to respond through + */ +void Get(char * request, int sfd) +{ + log_print(LOGDEBUG, "Get", "Got GET request: \"%s\"", request); + + int i = 0; + while (!isspace(request[++i]) && request[i] != '\0'); //NOTE: Don't need to check first character + request[i] = '\0'; + + char response[BUFSIZ]; + // TODO: Magical low level interfacing stuff! + + int len = sprintf(response, "HTTP/1.1 200 OK\nContent-type: text/html\n\n"); + write(sfd, response, len); + len = 0; + + if (strcmp("/sensor", request) == 0) // dummy test + { + len = sprintf(response, "SENSOR OFFLINE\n"); + } + else + { + FILE * f = fopen(request+1, "r"); + if (f == NULL) + { + log_print(LOGWARN, "Get", "File \"%s\" doesn't exist", request+1); + len = sprintf(response, "You requested \"%s\" using GET\n", request); + } + else + { + while (fgets(response, sizeof(response), f) != NULL) + { + write(sfd, response, strlen(response)); + } + } + } + if (len > 0) + write(sfd, response, len); +} + +/** + * @funct Post + * @purpose Respond to a POST request + * @param request - The request string + * @param sfd - Socket to respond through + */ +void Post(char * request, int sfd) +{ + log_print(LOGDEBUG, "Post", "Got POST request: \"%s\"", request); + int i = 0; + while (!isspace(request[++i]) && request[i] != '\0'); //NOTE: Don't need to check first character + request[i] = '\0'; + + char response[BUFSIZ]; + int len = sprintf(response, "HTTP/1.1 200 OK\nContent-type: text/html\n\n"); + write(sfd, response, len); + len = 0; + + // TODO: Magical low level interfacing stuff! + + + if (strcmp("/actuator", request) == 0) // dummy test + { + len = sprintf(response, "ACTUATOR OFFLINE\n"); + } + else + { + len = sprintf(response, "You requested \"%s\" using POST\n", request); + } + if (len > 0) + write(sfd, response, len); + +} + +/** + * @funct main + * @purpose Main program + * @param argc - Num arguments + * @param argv - Argument string array + * @returns error code (0 for no error) + */ + +int main(int argc, char ** argv) +{ + // Parse Arguments + ParseArguments(argc, argv); + // Set Cleanup to be called on program exit + atexit(Cleanup); + + // Setup signal handlers + int signals_to_handle[] = {SIGTERM, SIGINT, SIGHUP, SIGPIPE}; + for (int i = 0; i < sizeof(signals_to_handle)/sizeof(int); ++i) + { + int s = signals_to_handle[i]; + if (signal(s, SignalHandler) == SIG_ERR) + error("main", "Setting signal handler for %d (%s): %s", s, strsignal(s), strerror(errno)); + } + + // Bind to the port + options.bound_sfd = Network_server_bind(options.port, &(options.port)); + log_print(LOGDEBUG, "main", "Bound to port %d succesfully", options.port); + + while (true) + { + // Listen for a client + options.sfd = Network_server_listen(options.bound_sfd, NULL); + + log_print(LOGDEBUG, "main", "Connected to client"); + + char buffer[BUFSIZ]; //NOTE: Won't be able to respond to requests longer than BUFSIZ + // read a request + int len = read(options.sfd, buffer, sizeof(buffer)); + log_print(LOGDEBUG, "main", "Read %d characters. Buffer is \"%s\"", len, buffer); + + // Parse request + for (int i = 0; i < sizeof(buffer) && buffer[i] != '\0'; ++i) + { + // Look for "GET" or "POST" followed by a whitespace + if (isspace(buffer[i])) // whitespace + { + while (isspace(buffer[++i]) && buffer[i] != '\0'); // Skip whitespace + char * req = buffer+i; // set request string + + buffer[i-1] = '\0'; // terminate request type + while (buffer[++i] != '\n' && buffer[i] != '\0'); // find next newline + buffer[i-1] = '\0'; + + if (strcmp("GET", buffer) == 0) // Compare with "GET" + { + Get(req, options.sfd); + } + else if (strcmp("POST", buffer) == 0) // Compare with "POST" + { + Post(req, options.sfd); + } + else // Unknown request + { + log_print(LOGWARN, "main", "Unrecognised request type \"%s\" (request \"%s\")", buffer, req); + char response[] = "Error: Unrecognised request\n"; + write(options.sfd, response, sizeof(response)); + } + break; + } + } + + // Close connection + Network_close(options.sfd); + options.sfd = -1; + log_print(LOGDEBUG, "main", "Closed connection to client"); + } + + + + + return 0; +} + + diff --git a/testing/web2io/Makefile b/testing/web2io/Makefile deleted file mode 100644 index 24310f3..0000000 --- a/testing/web2io/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# Makefile for web2io testing stuff -CXX = gcc -FLAGS = -std=c99 -Wall -Werror -pedantic -g -LIB = -OBJ = network.o log.o webserver.o -RM = rm -f - -BIN = webserver - -$(BIN) : $(OBJ) - $(CXX) $(FLAGS) -o $(BIN) $(OBJ) - - -%.o : %.c - $(CXX) $(FLAGS) -c $< - - - -clean : - $(RM) $(BIN) - $(RM) *.o - -clean_full: #cleans up all backup files - $(RM) $(BIN) $(OBJ) $(LINKOBJ) - $(RM) *.*~ - $(RM) *~ - - - diff --git a/testing/web2io/README b/testing/web2io/README index 43353f4..2b8a7be 100644 --- a/testing/web2io/README +++ b/testing/web2io/README @@ -1,6 +1 @@ -This software will implement an interface between requests via HTTP and low level sensors/control on the server. - -Briefly investigated CGI scripts. Realised that interprocess communication will be difficult and complex. -Low level sensors will be polled continuously, but the client will not be continuously receiving information. - -Currently looking at implementing webserver and low level sensors/control in the same program on the server. +Testing directory for web stuff diff --git a/testing/web2io/jquery.flot.min.js b/testing/web2io/jquery.flot.min.js new file mode 100644 index 0000000..3706512 --- /dev/null +++ b/testing/web2io/jquery.flot.min.js @@ -0,0 +1,29 @@ +/* Javascript plotting library for jQuery, version 0.8.1. + +Copyright (c) 2007-2013 IOLA and Ole Laursen. +Licensed under the MIT license. + +*/// first an inline dependency, jquery.colorhelpers.js, we inline it here +// for convenience +/* Plugin for jQuery for working with colors. + * + * Version 1.1. + * + * Inspiration from jQuery color animation plugin by John Resig. + * + * Released under the MIT license by Ole Laursen, October 2009. + * + * Examples: + * + * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() + * var c = $.color.extract($("#mydiv"), 'background-color'); + * console.log(c.r, c.g, c.b, c.a); + * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" + * + * Note that .scale() and .add() return the same modified object + * instead of making a new one. + * + * V. 1.1: Fix error handling so e.g. parsing an empty string does + * produce a color rather than just crashing. + */(function(e){e.color={},e.color.make=function(t,n,r,i){var s={};return s.r=t||0,s.g=n||0,s.b=r||0,s.a=i!=null?i:1,s.add=function(e,t){for(var n=0;n=1?"rgb("+[s.r,s.g,s.b].join(",")+")":"rgba("+[s.r,s.g,s.b,s.a].join(",")+")"},s.normalize=function(){function e(e,t,n){return tn?n:t}return s.r=e(0,parseInt(s.r),255),s.g=e(0,parseInt(s.g),255),s.b=e(0,parseInt(s.b),255),s.a=e(0,s.a,1),s},s.clone=function(){return e.color.make(s.r,s.b,s.g,s.a)},s.normalize()},e.color.extract=function(t,n){var r;do{r=t.css(n).toLowerCase();if(r!=""&&r!="transparent")break;t=t.parent()}while(!e.nodeName(t.get(0),"body"));return r=="rgba(0, 0, 0, 0)"&&(r="transparent"),e.color.parse(r)},e.color.parse=function(n){var r,i=e.color.make;if(r=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10));if(r=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10),parseFloat(r[4]));if(r=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55);if(r=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55,parseFloat(r[4]));if(r=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(n))return i(parseInt(r[1],16),parseInt(r[2],16),parseInt(r[3],16));if(r=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(n))return i(parseInt(r[1]+r[1],16),parseInt(r[2]+r[2],16),parseInt(r[3]+r[3],16));var s=e.trim(n).toLowerCase();return s=="transparent"?i(255,255,255,0):(r=t[s]||[0,0,0],i(r[0],r[1],r[2]))};var t={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery),function(e){function n(t,n){var r=n.children("."+t)[0];if(r==null){r=document.createElement("canvas"),r.className=t,e(r).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(n);if(!r.getContext){if(!window.G_vmlCanvasManager)throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");r=window.G_vmlCanvasManager.initElement(r)}}this.element=r;var i=this.context=r.getContext("2d"),s=window.devicePixelRatio||1,o=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1;this.pixelRatio=s/o,this.resize(n.width(),n.height()),this.textContainer=null,this.text={},this._textCache={}}function r(t,r,s,o){function E(e,t){t=[w].concat(t);for(var n=0;nn&&(n=i))}t<=n&&(t=n+1);var s,o=[],f=a.colors,l=f.length,c=0;for(r=0;r=0?c<.5?c=-c-.2:c=0:c=-c),o[r]=s.scale("rgb",1+c);var h=0,p;for(r=0;re.datamax&&n!=r&&(e.datamax=n)}var t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,r=Number.MAX_VALUE,i,s,o,a,f,l,c,h,p,d,v,m,g,y,w,S;e.each(k(),function(e,r){r.datamin=t,r.datamax=n,r.used=!1});for(i=0;i0&&c[o-h]!=null&&c[o-h]!=c[o]&&c[o-h+1]!=c[o+1]){for(a=0;aO&&(O=m)),g.y&&(mM&&(M=m))}}if(l.bars.show){var _;switch(l.bars.align){case"left":_=0;break;case"right":_=-l.bars.barWidth;break;case"center":_=-l.bars.barWidth/2;break;default:throw new Error("Invalid bar alignment: "+l.bars.align)}l.bars.horizontal?(A+=_,M+=_+l.bars.barWidth):(L+=_,O+=_+l.bars.barWidth)}x(l.xaxis,L,O),x(l.yaxis,A,M)}e.each(k(),function(e,r){r.datamin==t&&(r.datamin=null),r.datamax==n&&(r.datamax=null)})}function D(){t.css("padding",0).children(":not(.flot-base,.flot-overlay)").remove(),t.css("position")=="static"&&t.css("position","relative"),f=new n("flot-base",t),l=new n("flot-overlay",t),h=f.context,p=l.context,c=e(l.element).unbind();var r=t.data("plot");r&&(r.shutdown(),l.clear()),t.data("plot",w)}function P(){a.grid.hoverable&&(c.mousemove(at),c.bind("mouseleave",ft)),a.grid.clickable&&c.click(lt),E(b.bindEvents,[c])}function H(){ot&&clearTimeout(ot),c.unbind("mousemove",at),c.unbind("mouseleave",ft),c.unbind("click",lt),E(b.shutdown,[c])}function B(e){function t(e){return e}var n,r,i=e.options.transform||t,s=e.options.inverseTransform;e.direction=="x"?(n=e.scale=g/Math.abs(i(e.max)-i(e.min)),r=Math.min(i(e.max),i(e.min))):(n=e.scale=y/Math.abs(i(e.max)-i(e.min)),n=-n,r=Math.max(i(e.max),i(e.min))),i==t?e.p2c=function(e){return(e-r)*n}:e.p2c=function(e){return(i(e)-r)*n},s?e.c2p=function(e){return s(r+e/n)}:e.c2p=function(e){return r+e/n}}function j(e){var t=e.options,n=e.ticks||[],r=t.labelWidth||0,i=t.labelHeight||0,s=r||e.direction=="x"?Math.floor(f.width/(n.length||1)):null;legacyStyles=e.direction+"Axis "+e.direction+e.n+"Axis",layer="flot-"+e.direction+"-axis flot-"+e.direction+e.n+"-axis "+legacyStyles,font=t.font||"flot-tick-label tickLabel";for(var o=0;o=0;--t)F(o[t]);q(),e.each(o,function(e,t){I(t)})}g=f.width-m.left-m.right,y=f.height-m.bottom-m.top,e.each(n,function(e,t){B(t)}),r&&G(),it()}function U(e){var t=e.options,n=+(t.min!=null?t.min:e.datamin),r=+(t.max!=null?t.max:e.datamax),i=r-n;if(i==0){var s=r==0?1:.01;t.min==null&&(n-=s);if(t.max==null||t.min!=null)r+=s}else{var o=t.autoscaleMargin;o!=null&&(t.min==null&&(n-=i*o,n<0&&e.datamin!=null&&e.datamin>=0&&(n=0)),t.max==null&&(r+=i*o,r>0&&e.datamax!=null&&e.datamax<=0&&(r=0)))}e.min=n,e.max=r}function z(t){var n=t.options,r;typeof n.ticks=="number"&&n.ticks>0?r=n.ticks:r=.3*Math.sqrt(t.direction=="x"?f.width:f.height);var s=(t.max-t.min)/r,o=-Math.floor(Math.log(s)/Math.LN10),u=n.tickDecimals;u!=null&&o>u&&(o=u);var a=Math.pow(10,-o),l=s/a,c;l<1.5?c=1:l<3?(c=2,l>2.25&&(u==null||o+1<=u)&&(c=2.5,++o)):l<7.5?c=5:c=10,c*=a,n.minTickSize!=null&&c0&&(n.min==null&&(t.min=Math.min(t.min,p[0])),n.max==null&&p.length>1&&(t.max=Math.max(t.max,p[p.length-1]))),t.tickGenerator=function(e){var t=[],n,r;for(r=0;r1&&/\..*0$/.test((g[1]-g[0]).toFixed(m))||(t.tickDecimals=m)}}}}function W(t){var n=t.options.ticks,r=[];n==null||typeof n=="number"&&n>0?r=t.tickGenerator(t):n&&(e.isFunction(n)?r=n(t):r=n);var i,s;t.ticks=[];for(i=0;i1&&(o=u[1])):s=+u,o==null&&(o=t.tickFormatter(s,t)),isNaN(s)||t.ticks.push({v:s,label:o})}}function X(e,t){e.options.autoscaleMargin&&t.length>0&&(e.options.min==null&&(e.min=Math.min(e.min,t[0].v)),e.options.max==null&&t.length>1&&(e.max=Math.max(e.max,t[t.length-1].v)))}function V(){f.clear(),E(b.drawBackground,[h]);var e=a.grid;e.show&&e.backgroundColor&&K(),e.show&&!e.aboveData&&Q();for(var t=0;ti){var a=r;r=i,i=a}return{from:r,to:i,axis:n}}function K(){h.save(),h.translate(m.left,m.top),h.fillStyle=bt(a.grid.backgroundColor,y,0,"rgba(255, 255, 255, 0)"),h.fillRect(0,0,g,y),h.restore()}function Q(){var t,n,r,i;h.save(),h.translate(m.left,m.top);var s=a.grid.markings;if(s){e.isFunction(s)&&(n=w.getAxes(),n.xmin=n.xaxis.min,n.xmax=n.xaxis.max,n.ymin=n.yaxis.min,n.ymax=n.yaxis.max,s=s(n));for(t=0;tu.axis.max||f.tof.axis.max)continue;u.from=Math.max(u.from,u.axis.min),u.to=Math.min(u.to,u.axis.max),f.from=Math.max(f.from,f.axis.min),f.to=Math.min(f.to,f.axis.max);if(u.from==u.to&&f.from==f.to)continue;u.from=u.axis.p2c(u.from),u.to=u.axis.p2c(u.to),f.from=f.axis.p2c(f.from),f.to=f.axis.p2c(f.to),u.from==u.to||f.from==f.to?(h.beginPath(),h.strokeStyle=o.color||a.grid.markingsColor,h.lineWidth=o.lineWidth||a.grid.markingsLineWidth,h.moveTo(u.from,f.from),h.lineTo(u.to,f.to),h.stroke()):(h.fillStyle=o.color||a.grid.markingsColor,h.fillRect(u.from,f.to,u.to-u.from,f.from-f.to))}}n=k(),r=a.grid.borderWidth;for(var l=0;lc.max||d=="full"&&(typeof r=="object"&&r[c.position]>0||r>0)&&(x==c.min||x==c.max))continue;c.direction=="x"?(v=c.p2c(x),S=d=="full"?-y:d,c.position=="top"&&(S=-S)):(b=c.p2c(x),E=d=="full"?-g:d,c.position=="left"&&(E=-E)),h.lineWidth==1&&(c.direction=="x"?v=Math.floor(v)+.5:b=Math.floor(b)+.5),h.moveTo(v,b),h.lineTo(v+E,b+S)}h.stroke()}r&&(i=a.grid.borderColor,typeof r=="object"||typeof i=="object"?(typeof r!="object"&&(r={top:r,right:r,bottom:r,left:r}),typeof i!="object"&&(i={top:i,right:i,bottom:i,left:i}),r.top>0&&(h.strokeStyle=i.top,h.lineWidth=r.top,h.beginPath(),h.moveTo(0-r.left,0-r.top/2),h.lineTo(g,0-r.top/2),h.stroke()),r.right>0&&(h.strokeStyle=i.right,h.lineWidth=r.right,h.beginPath(),h.moveTo(g+r.right/2,0-r.top),h.lineTo(g+r.right/2,y),h.stroke()),r.bottom>0&&(h.strokeStyle=i.bottom,h.lineWidth=r.bottom,h.beginPath(),h.moveTo(g+r.right,y+r.bottom/2),h.lineTo(0,y+r.bottom/2),h.stroke()),r.left>0&&(h.strokeStyle=i.left,h.lineWidth=r.left,h.beginPath(),h.moveTo(0-r.left/2,y+r.bottom),h.lineTo(0-r.left/2,0),h.stroke())):(h.lineWidth=r,h.strokeStyle=a.grid.borderColor,h.strokeRect(-r/2,-r/2,g+r,y+r))),h.restore()}function G(){e.each(k(),function(e,t){if(!t.show||t.ticks.length==0)return;var n=t.box,r=t.direction+"Axis "+t.direction+t.n+"Axis",i="flot-"+t.direction+"-axis flot-"+t.direction+t.n+"-axis "+r,s=t.options.font||"flot-tick-label tickLabel",o,u,a,l,c;f.removeText(i);for(var h=0;ht.max)continue;t.direction=="x"?(l="center",u=m.left+t.p2c(o.v),t.position=="bottom"?a=n.top+n.padding:(a=n.top+n.height-n.padding,c="bottom")):(c="middle",a=m.top+t.p2c(o.v),t.position=="left"?(u=n.left+n.width-n.padding,l="right"):u=n.left+n.padding),f.addText(i,u,a,o.label,s,null,null,l,c)}})}function Y(e){e.lines.show&&Z(e),e.bars.show&&nt(e),e.points.show&&et(e)}function Z(e){function t(e,t,n,r,i){var s=e.points,o=e.pointsize,u=null,a=null;h.beginPath();for(var f=o;f=d&&c>i.max){if(d>i.max)continue;l=(i.max-c)/(d-c)*(p-l)+l,c=i.max}else if(d>=c&&d>i.max){if(c>i.max)continue;p=(i.max-c)/(d-c)*(p-l)+l,d=i.max}if(l<=p&&l=p&&l>r.max){if(p>r.max)continue;c=(r.max-l)/(p-l)*(d-c)+c,l=r.max}else if(p>=l&&p>r.max){if(l>r.max)continue;d=(r.max-l)/(p-l)*(d-c)+c,p=r.max}(l!=u||c!=a)&&h.moveTo(r.p2c(l)+t,i.p2c(c)+n),u=p,a=d,h.lineTo(r.p2c(p)+t,i.p2c(d)+n)}h.stroke()}function n(e,t,n){var r=e.points,i=e.pointsize,s=Math.min(Math.max(0,n.min),n.max),o=0,u,a=!1,f=1,l=0,c=0;for(;;){if(i>0&&o>r.length+i)break;o+=i;var p=r[o-i],d=r[o-i+f],v=r[o],m=r[o+f];if(a){if(i>0&&p!=null&&v==null){c=o,i=-i,f=2;continue}if(i<0&&o==l+i){h.fill(),a=!1,i=-i,f=1,o=l=c+i;continue}}if(p==null||v==null)continue;if(p<=v&&p=v&&p>t.max){if(v>t.max)continue;d=(t.max-p)/(v-p)*(m-d)+d,p=t.max}else if(v>=p&&v>t.max){if(p>t.max)continue;m=(t.max-p)/(v-p)*(m-d)+d,v=t.max}a||(h.beginPath(),h.moveTo(t.p2c(p),n.p2c(s)),a=!0);if(d>=n.max&&m>=n.max){h.lineTo(t.p2c(p),n.p2c(n.max)),h.lineTo(t.p2c(v),n.p2c(n.max));continue}if(d<=n.min&&m<=n.min){h.lineTo(t.p2c(p),n.p2c(n.min)),h.lineTo(t.p2c(v),n.p2c(n.min));continue}var g=p,y=v;d<=m&&d=n.min?(p=(n.min-d)/(m-d)*(v-p)+p,d=n.min):m<=d&&m=n.min&&(v=(n.min-d)/(m-d)*(v-p)+p,m=n.min),d>=m&&d>n.max&&m<=n.max?(p=(n.max-d)/(m-d)*(v-p)+p,d=n.max):m>=d&&m>n.max&&d<=n.max&&(v=(n.max-d)/(m-d)*(v-p)+p,m=n.max),p!=g&&h.lineTo(t.p2c(g),n.p2c(d)),h.lineTo(t.p2c(p),n.p2c(d)),h.lineTo(t.p2c(v),n.p2c(m)),v!=y&&(h.lineTo(t.p2c(v),n.p2c(m)),h.lineTo(t.p2c(y),n.p2c(m)))}}h.save(),h.translate(m.left,m.top),h.lineJoin="round";var r=e.lines.lineWidth,i=e.shadowSize;if(r>0&&i>0){h.lineWidth=i,h.strokeStyle="rgba(0,0,0,0.1)";var s=Math.PI/18;t(e.datapoints,Math.sin(s)*(r/2+i/2),Math.cos(s)*(r/2+i/2),e.xaxis,e.yaxis),h.lineWidth=i/2,t(e.datapoints,Math.sin(s)*(r/2+i/4),Math.cos(s)*(r/2+i/4),e.xaxis,e.yaxis)}h.lineWidth=r,h.strokeStyle=e.color;var o=rt(e.lines,e.color,0,y);o&&(h.fillStyle=o,n(e.datapoints,e.xaxis,e.yaxis)),r>0&&t(e.datapoints,0,0,e.xaxis,e.yaxis),h.restore()}function et(e){function t(e,t,n,r,i,s,o,u){var a=e.points,f=e.pointsize;for(var l=0;ls.max||po.max)continue;h.beginPath(),c=s.p2c(c),p=o.p2c(p)+r,u=="circle"?h.arc(c,p,t,0,i?Math.PI:Math.PI*2,!1):u(h,c,p,t,i),h.closePath(),n&&(h.fillStyle=n,h.fill()),h.stroke()}}h.save(),h.translate(m.left,m.top);var n=e.points.lineWidth,r=e.shadowSize,i=e.points.radius,s=e.points.symbol;n==0&&(n=1e-4);if(n>0&&r>0){var o=r/2;h.lineWidth=o,h.strokeStyle="rgba(0,0,0,0.1)",t(e.datapoints,i,null,o+o/2,!0,e.xaxis,e.yaxis,s),h.strokeStyle="rgba(0,0,0,0.2)",t(e.datapoints,i,null,o/2,!0,e.xaxis,e.yaxis,s)}h.lineWidth=n,h.strokeStyle=e.color,t(e.datapoints,i,rt(e.points,e.color),0,!1,e.xaxis,e.yaxis,s),h.restore()}function tt(e,t,n,r,i,s,o,u,a,f,l,c){var h,p,d,v,m,g,y,b,w;l?(b=g=y=!0,m=!1,h=n,p=e,v=t+r,d=t+i,pu.max||va.max)return;hu.max&&(p=u.max,g=!1),da.max&&(v=a.max,y=!1),h=u.p2c(h),d=a.p2c(d),p=u.p2c(p),v=a.p2c(v),o&&(f.beginPath(),f.moveTo(h,d),f.lineTo(h,v),f.lineTo(p,v),f.lineTo(p,d),f.fillStyle=o(d,v),f.fill()),c>0&&(m||g||y||b)&&(f.beginPath(),f.moveTo(h,d+s),m?f.lineTo(h,v+s):f.moveTo(h,v+s),y?f.lineTo(p,v+s):f.moveTo(p,v+s),g?f.lineTo(p,d+s):f.moveTo(p,d+s),b?f.lineTo(h,d+s):f.moveTo(h,d+s),f.stroke())}function nt(e){function t(t,n,r,i,s,o,u){var a=t.points,f=t.pointsize;for(var l=0;l"),n.push(""),i=!0),n.push('
'+''+h.label+"")}i&&n.push("");if(n.length==0)return;var p=''+n.join("")+"
";if(a.legend.container!=null)e(a.legend.container).html(p);else{var d="",v=a.legend.position,g=a.legend.margin;g[0]==null&&(g=[g,g]),v.charAt(0)=="n"?d+="top:"+(g[1]+m.top)+"px;":v.charAt(0)=="s"&&(d+="bottom:"+(g[1]+m.bottom)+"px;"),v.charAt(1)=="e"?d+="right:"+(g[0]+m.right)+"px;":v.charAt(1)=="w"&&(d+="left:"+(g[0]+m.left)+"px;");var y=e('
'+p.replace('style="','style="position:absolute;'+d+";")+"
").appendTo(t);if(a.legend.backgroundOpacity!=0){var b=a.legend.backgroundColor;b==null&&(b=a.grid.backgroundColor,b&&typeof b=="string"?b=e.color.parse(b):b=e.color.extract(y,"background-color"),b.a=1,b=b.toString());var w=y.children();e('
').prependTo(y).css("opacity",a.legend.backgroundOpacity)}}}function ut(e,t,n){var r=a.grid.mouseActiveRadius,i=r*r+1,s=null,o=!1,f,l,c;for(f=u.length-1;f>=0;--f){if(!n(u[f]))continue;var h=u[f],p=h.xaxis,d=h.yaxis,v=h.datapoints.points,m=p.c2p(e),g=d.c2p(t),y=r/p.scale,b=r/d.scale;c=h.datapoints.pointsize,p.options.inverseTransform&&(y=Number.MAX_VALUE),d.options.inverseTransform&&(b=Number.MAX_VALUE);if(h.lines.show||h.points.show)for(l=0;ly||w-m<-y||E-g>b||E-g<-b)continue;var S=Math.abs(p.p2c(w)-e),x=Math.abs(d.p2c(E)-t),T=S*S+x*x;T=Math.min(k,w)&&g>=E+N&&g<=E+C:m>=w+N&&m<=w+C&&g>=Math.min(k,E)&&g<=Math.max(k,E))s=[f,l/c]}}}return s?(f=s[0],l=s[1],c=u[f].datapoints.pointsize,{datapoint:u[f].datapoints.points.slice(l*c,(l+1)*c),dataIndex:l,series:u[f],seriesIndex:f}):null}function at(e){a.grid.hoverable&&ct("plothover",e,function(e){return e["hoverable"]!=0})}function ft(e){a.grid.hoverable&&ct("plothover",e,function(e){return!1})}function lt(e){ct("plotclick",e,function(e){return e["clickable"]!=0})}function ct(e,n,r){var i=c.offset(),s=n.pageX-i.left-m.left,o=n.pageY-i.top-m.top,u=L({left:s,top:o});u.pageX=n.pageX,u.pageY=n.pageY;var f=ut(s,o,r);f&&(f.pageX=parseInt(f.series.xaxis.p2c(f.datapoint[0])+i.left+m.left,10),f.pageY=parseInt(f.series.yaxis.p2c(f.datapoint[1])+i.top+m.top,10));if(a.grid.autoHighlight){for(var l=0;ls.max||io.max)return;var a=t.points.radius+t.points.lineWidth/2;p.lineWidth=a,p.strokeStyle=u;var f=1.5*a;r=s.p2c(r),i=o.p2c(i),p.beginPath(),t.points.symbol=="circle"?p.arc(r,i,f,0,2*Math.PI,!1):t.points.symbol(p,r,i,f,!1),p.closePath(),p.stroke()}function yt(t,n){var r=typeof t.highlightColor=="string"?t.highlightColor:e.color.parse(t.color).scale("a",.5).toString(),i=r,s=t.bars.align=="left"?0:-t.bars.barWidth/2;p.lineWidth=t.bars.lineWidth,p.strokeStyle=r,tt(n[0],n[1],n[2]||0,s,s+t.bars.barWidth,0,function(){return i},t.xaxis,t.yaxis,p,t.bars.horizontal,t.bars.lineWidth)}function bt(t,n,r,i){if(typeof t=="string")return t;var s=h.createLinearGradient(0,r,0,n);for(var o=0,u=t.colors.length;o").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)),n=this.text[t]=e("
").addClass(t).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)),n},n.prototype.getTextInfo=function(t,n,r,i,s){var o,u,a,f;n=""+n,typeof r=="object"?o=r.style+" "+r.variant+" "+r.weight+" "+r.size+"px/"+r.lineHeight+"px "+r.family:o=r,u=this._textCache[t],u==null&&(u=this._textCache[t]={}),a=u[o],a==null&&(a=u[o]={}),f=a[n];if(f==null){var l=e("
").html(n).css({position:"absolute","max-width":s,top:-9999}).appendTo(this.getTextLayer(t));typeof r=="object"?l.css({font:o,color:r.color}):typeof r=="string"&&l.addClass(r),f=a[n]={width:l.outerWidth(!0),height:l.outerHeight(!0),element:l,positions:[]},l.detach()}return f},n.prototype.addText=function(e,t,n,r,i,s,o,u,a){var f=this.getTextInfo(e,r,i,s,o),l=f.positions;u=="center"?t-=f.width/2:u=="right"&&(t-=f.width),a=="middle"?n-=f.height/2:a=="bottom"&&(n-=f.height);for(var c=0,h;h=l[c];c++)if(h.x==t&&h.y==n){h.active=!0;return}h={active:!0,rendered:!1,element:l.length?f.element.clone():f.element,x:t,y:n},l.push(h),h.element.css({top:Math.round(n),left:Math.round(t),"text-align":u})},n.prototype.removeText=function(e,n,r,i,s,o){if(i==null){var u=this._textCache[e];if(u!=null)for(var a in u)if(t.call(u,a)){var f=u[a];for(var l in f)if(t.call(f,l)){var c=f[l].positions;for(var h=0,p;p=c[h];h++)p.active=!1}}}else{var c=this.getTextInfo(e,i,s,o).positions;for(var h=0,p;p=c[h];h++)p.x==n&&p.y==r&&(p.active=!1)}},e.plot=function(t,n,i){var s=new r(e(t),n,i,e.plot.plugins);return s},e.plot.version="0.8.1",e.plot.plugins=[],e.fn.plot=function(t,n){return this.each(function(){e.plot(this,t,n)})}}(jQuery); \ No newline at end of file diff --git a/testing/web2io/log.c b/testing/web2io/log.c deleted file mode 100644 index 3a8c55c..0000000 --- a/testing/web2io/log.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "log.h" -#include "options.h" -#include - -static int last_len = 0; - -void log_print(int level, char * funct, char * fmt, ...) -{ - if (level > options.verbosity) - return; - - - - char severity[BUFSIZ]; - switch (level) - { - case LOGERR: - sprintf(severity, "ERROR"); - break; - case LOGWARN: - sprintf(severity, "WARNING"); - break; - case LOGNOTE: - sprintf(severity, "NOTICE"); - break; - case LOGINFO: - sprintf(severity, "INFO"); - break; - default: - sprintf(severity, "DEBUG"); - break; - } - - if (funct != NULL) - last_len = fprintf(stderr, "%s [%d] : %s : %s - ", options.program, getpid(), severity, funct); - else - { - for (int i = 0; i < last_len; ++i); - fprintf(stderr, " "); - } - va_list va; - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - fprintf(stderr, "\n"); -} - -void error(char * funct, char * fmt, ...) -{ - if (funct != NULL) - last_len = fprintf(stderr, "%s [%d] : Fatal error in %s - ", options.program, getpid(), funct); - else - { - for (int i = 0; i < last_len; ++i) - fprintf(stderr, " "); - fprintf(stderr, "Fatal - "); - } - va_list va; - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - fprintf(stderr, "\n"); - - exit(EXIT_FAILURE); -} - - diff --git a/testing/web2io/log.h b/testing/web2io/log.h deleted file mode 100644 index 75e2780..0000000 --- a/testing/web2io/log.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _LOG_H -#define _LOG_H - -#include -#include -#include - -#include - -enum {LOGERR=0, LOGWARN=1, LOGNOTE=2, LOGINFO=3,LOGDEBUG=4}; - -extern void log_print(int level, char * funct, char * fmt,...); -extern void error(char * funct, char * fmt, ...); - -#endif //_LOG_H - -//EOF diff --git a/testing/web2io/network.c b/testing/web2io/network.c deleted file mode 100644 index 1a1b862..0000000 --- a/testing/web2io/network.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "network.h" -#include -#include -#include -#include "log.h" - -#define h_addr h_addr_list[0] - - - - - -int Network_get_port(int sfd) -{ - static struct sockaddr_in sin; - static socklen_t len = sizeof(struct sockaddr_in); - - if (getsockname(sfd, (struct sockaddr *)&sin, &len) != 0) - error("Network_port", "getsockname : %s", strerror(errno)); - return ntohs(sin.sin_port); -} - -int Network_server_bind(int port, int * bound) -{ - int sfd = socket(PF_INET, SOCK_STREAM, 0); - if (sfd < 0) - { - error("Network_server", "Creating socket on port %d : %s", port, strerror(errno)); - } - - struct sockaddr_in name; - - name.sin_family = AF_INET; - name.sin_addr.s_addr = htonl(INADDR_ANY); - name.sin_port = htons(port); - - if (bind( sfd, (struct sockaddr *) &name, sizeof(name) ) < 0) - { - error("Network_server", "Binding socket on port %d : %s", port, strerror(errno)); - } - - if (bound != NULL) - *bound = Network_get_port(sfd); - return sfd; -} - -int Network_server_listen(int sfd, char * addr) -{ - int port = Network_get_port(sfd); - if (listen(sfd, 1) < 0) - { - error("Network_server", "Listening on port %d : %s", port, strerror(errno)); - } - - int psd; - if (addr == NULL) - psd = accept(sfd, 0, 0); - else - { - struct sockaddr_in client; - struct hostent *hp; - - client.sin_family = AF_INET; - hp = gethostbyname(addr); - bcopy ( hp->h_addr, &(client.sin_addr.s_addr), hp->h_length); - client.sin_port = htons(port); - socklen_t len = sizeof(client); - - psd = accept(sfd, (struct sockaddr*)&client, &len); - } - //close(sfd); // don't close the bind socket here; we might want to reuse the port - assert(psd >= 0); - return psd; -} - -int Network_server(char * addr, int port) -{ - int bind = Network_server_bind(port, &port); - int sfd = Network_server_listen(bind, addr); - close(bind); // won't be able to reuse the port (it goes into TIME_WAIT) - return sfd; -} - -int Network_client(const char * addr, int port, int timeout) -{ - int sfd = socket(PF_INET, SOCK_STREAM, 0); - - //log_print(2, "Network_client", "Created socket"); - long arg = fcntl(sfd, F_GETFL, NULL); - arg |= O_NONBLOCK; - fcntl(sfd, F_SETFL, arg); - - if (sfd < 0) - { - error("Network_client", "Creating socket for address %s:%d : %s", addr, port, strerror(errno)); - } - struct sockaddr_in server; - struct hostent *hp; - - - server.sin_family = AF_INET; - hp = gethostbyname(addr); - if (hp == NULL) - { - error("Network_client", "Can't get host by name %s", addr); - } - bcopy ( hp->h_addr, &(server.sin_addr.s_addr), hp->h_length); - server.sin_port = htons(port); - - - int res = connect(sfd, (struct sockaddr *) &server, sizeof(server)); - - - if (res < 0 && errno == EINPROGRESS) - { - - fd_set writeSet; - FD_ZERO(&writeSet); - FD_SET(sfd, &writeSet); - - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - - struct timeval * tp; - tp = (timeout < 0) ? NULL : &tv; - - int err = select(sfd+1, NULL, &writeSet, NULL, tp); - - if (err == 0) - { - error("Network_client", "Timed out trying to connect to %s:%d after %d seconds", addr, port, timeout); - } - else if (err < 0) - { - error("Network_client", "Connecting to %s:%d - Error in select(2) call : %s", addr, port, strerror(errno)); - } - else if (FD_ISSET(sfd, &writeSet)) - { - int so_error; - socklen_t len = sizeof so_error; - getsockopt(sfd, SOL_SOCKET, SO_ERROR, &so_error, &len); - if (so_error != 0) - { - error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(so_error)); - } - } - else - { - error("Network_client", "select(2) returned %d but the socket is not writable!?", err); - } - } - else - { - error("Network_client", "Connecting to %s:%d : %s", addr, port, strerror(errno)); - } - - arg = fcntl(sfd, F_GETFL, NULL); - arg &= (~O_NONBLOCK); - fcntl(sfd, F_SETFL, arg); - - - - return sfd; -} - -void Network_close(int sfd) -{ - if (shutdown(sfd, 2) != 0) - { - error("Network_close", "Closing socket : %s", strerror(errno)); - } - close(sfd); -} diff --git a/testing/web2io/network.h b/testing/web2io/network.h deleted file mode 100644 index 07c9459..0000000 --- a/testing/web2io/network.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _NETWORK_H -#define _NETWORK_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int Network_get_port(int socket); // get port used by socket -extern int Network_server(char * addr, int port); -extern int Network_client(const char * addr, int port, int timeout); - -extern int Network_server_bind(int port, int * bound); -extern int Network_server_listen(int sfd, char * addr); - -extern void Network_close(int sfd); - -#endif //_NETWORK_H - -//EOF diff --git a/testing/web2io/options.h b/testing/web2io/options.h deleted file mode 100644 index 2a6d323..0000000 --- a/testing/web2io/options.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file options.h - * @purpose Declaration of structure to handle options passed to program - */ - -#include - -typedef struct -{ - const char * program; //name of program - uint8_t verbosity; // verbosity level - int port; // port to use for webserver - int bound_sfd; // socket webserver has bound to - int sfd; // socket connected to client - -} Options; - - - -extern Options options; diff --git a/testing/web2io/styles.css b/testing/web2io/styles.css new file mode 100644 index 0000000..762063b --- /dev/null +++ b/testing/web2io/styles.css @@ -0,0 +1,19 @@ +.graph { + box-sizing: border-box; + width: 850px; + height: 450px; + padding: 20px 15px 15px 15px; + margin: 15px auto 30px auto; + border: 1px solid #ddd; + background: #fff; + background: linear-gradient(#f6f6f6 0, #fff 50px); + background: -o-linear-gradient(#f6f6f6 0, #fff 50px); + background: -ms-linear-gradient(#f6f6f6 0, #fff 50px); + background: -moz-linear-gradient(#f6f6f6 0, #fff 50px); + background: -webkit-linear-gradient(#f6f6f6 0, #fff 50px); + box-shadow: 0 3px 10px rgba(0,0,0,0.15); + -o-box-shadow: 0 3px 10px rgba(0,0,0,0.1); + -ms-box-shadow: 0 3px 10px rgba(0,0,0,0.1); + -moz-box-shadow: 0 3px 10px rgba(0,0,0,0.1); + -webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1); +} diff --git a/testing/web2io/webserver.c b/testing/web2io/webserver.c deleted file mode 100644 index 6ff4f46..0000000 --- a/testing/web2io/webserver.c +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @file webserver.c - * @purpose Test implementing a minimalistic webserver - * - */ - -#define _POSIX_C_SOURCE 200809L // needed for some POSIX stuff to work - -// --- Standard headers --- // -#include -#include -#include // string helper functions -#include // character types -#include // for signal handling - -// --- Custom headers --- // -#include "log.h" // C functions to handle logging -#include "options.h" // Options structure -#include "network.h" // C functions to handle low level networking - -// --- Variable definitions --- // -Options options; // declared in "options.h" - -// --- Function definitions --- // - -/** - * @funct ParseArguments - * @purpose Parse Arguments and setup the global options variable - * @param argc - Num args - * @param argv - Array of args - */ -void ParseArguments(int argc, char ** argv) -{ - options.program = argv[0]; - options.verbosity = LOGDEBUG; - if (argc > 1) - options.port = atoi(argv[1]); // Allow us change the port for testing (I keep getting "address in use" errors) - else - options.port = 8080; // Using 8080 instead of 80 for now because to use 80 you have to run the program as root - options.sfd = -1; - options.bound_sfd = -1; - log_print(LOGDEBUG, "ParseArguments", "Called as %s with %d arguments.", options.program, argc); -} - -/** - * @funct SignalHandler - * @purpose Handle signals - * @param sig - The signal - */ -void SignalHandler(int sig) -{ - // At the moment just always exit. - // Call `exit` so that Cleanup will be called to... clean up. - log_print(LOGWARN, "SignalHandler", "Got signal %d (%s). Exiting.", sig, strsignal(sig)); - exit(sig); -} - -/** - * @funct Cleanup - * @purpose Called when program exits - */ -void Cleanup() -{ - log_print(LOGDEBUG, "Cleanup", "Begin cleanup."); - if (options.sfd >= 0) - { - Network_close(options.sfd); // close socket - options.sfd = -1; - } - if (options.bound_sfd >= 0) - { - Network_close(options.bound_sfd); // unbind - options.bound_sfd = -1; - } - log_print(LOGDEBUG, "Cleanup", "Unbound from port %d successfully", options.port); - log_print(LOGDEBUG, "Cleanup", "Done."); - -} - - -/** - * @funct Get - * @purpose Respond to a GET request - * @param request - The request string - * @param sfd - Socket to respond through - */ -void Get(char * request, int sfd) -{ - log_print(LOGDEBUG, "Get", "Got GET request: \"%s\"", request); - - int i = 0; - while (!isspace(request[++i]) && request[i] != '\0'); //NOTE: Don't need to check first character - request[i] = '\0'; - - char response[BUFSIZ]; - // TODO: Magical low level interfacing stuff! - - int len = sprintf(response, "HTTP/1.1 200 OK\nContent-type: text/html\n\n"); - write(sfd, response, len); - len = 0; - - if (strcmp("/sensor", request) == 0) // dummy test - { - len = sprintf(response, "SENSOR OFFLINE\n"); - } - else - { - FILE * f = fopen(request+1, "r"); - if (f == NULL) - { - log_print(LOGWARN, "Get", "File \"%s\" doesn't exist", request+1); - len = sprintf(response, "You requested \"%s\" using GET\n", request); - } - else - { - while (fgets(response, sizeof(response), f) != NULL) - { - write(sfd, response, strlen(response)); - } - } - } - if (len > 0) - write(sfd, response, len); -} - -/** - * @funct Post - * @purpose Respond to a POST request - * @param request - The request string - * @param sfd - Socket to respond through - */ -void Post(char * request, int sfd) -{ - log_print(LOGDEBUG, "Post", "Got POST request: \"%s\"", request); - int i = 0; - while (!isspace(request[++i]) && request[i] != '\0'); //NOTE: Don't need to check first character - request[i] = '\0'; - - char response[BUFSIZ]; - int len = sprintf(response, "HTTP/1.1 200 OK\nContent-type: text/html\n\n"); - write(sfd, response, len); - len = 0; - - // TODO: Magical low level interfacing stuff! - - - if (strcmp("/actuator", request) == 0) // dummy test - { - len = sprintf(response, "ACTUATOR OFFLINE\n"); - } - else - { - len = sprintf(response, "You requested \"%s\" using POST\n", request); - } - if (len > 0) - write(sfd, response, len); - -} - -/** - * @funct main - * @purpose Main program - * @param argc - Num arguments - * @param argv - Argument string array - * @returns error code (0 for no error) - */ - -int main(int argc, char ** argv) -{ - // Parse Arguments - ParseArguments(argc, argv); - // Set Cleanup to be called on program exit - atexit(Cleanup); - - // Setup signal handlers - int signals_to_handle[] = {SIGTERM, SIGINT, SIGHUP, SIGPIPE}; - for (int i = 0; i < sizeof(signals_to_handle)/sizeof(int); ++i) - { - int s = signals_to_handle[i]; - if (signal(s, SignalHandler) == SIG_ERR) - error("main", "Setting signal handler for %d (%s): %s", s, strsignal(s), strerror(errno)); - } - - // Bind to the port - options.bound_sfd = Network_server_bind(options.port, &(options.port)); - log_print(LOGDEBUG, "main", "Bound to port %d succesfully", options.port); - - while (true) - { - // Listen for a client - options.sfd = Network_server_listen(options.bound_sfd, NULL); - - log_print(LOGDEBUG, "main", "Connected to client"); - - char buffer[BUFSIZ]; //NOTE: Won't be able to respond to requests longer than BUFSIZ - // read a request - int len = read(options.sfd, buffer, sizeof(buffer)); - log_print(LOGDEBUG, "main", "Read %d characters. Buffer is \"%s\"", len, buffer); - - // Parse request - for (int i = 0; i < sizeof(buffer) && buffer[i] != '\0'; ++i) - { - // Look for "GET" or "POST" followed by a whitespace - if (isspace(buffer[i])) // whitespace - { - while (isspace(buffer[++i]) && buffer[i] != '\0'); // Skip whitespace - char * req = buffer+i; // set request string - - buffer[i-1] = '\0'; // terminate request type - while (buffer[++i] != '\n' && buffer[i] != '\0'); // find next newline - buffer[i-1] = '\0'; - - if (strcmp("GET", buffer) == 0) // Compare with "GET" - { - Get(req, options.sfd); - } - else if (strcmp("POST", buffer) == 0) // Compare with "POST" - { - Post(req, options.sfd); - } - else // Unknown request - { - log_print(LOGWARN, "main", "Unrecognised request type \"%s\" (request \"%s\")", buffer, req); - char response[] = "Error: Unrecognised request\n"; - write(options.sfd, response, sizeof(response)); - } - break; - } - } - - // Close connection - Network_close(options.sfd); - options.sfd = -1; - log_print(LOGDEBUG, "main", "Closed connection to client"); - } - - - - - return 0; -} - -