Initial commit of an experimental little Squid redirector.
authorMahlon E. Smith <mahlon@martini.nu>
Fri, 26 Aug 2011 14:40:51 -0700
changeset 0 eac7211fe522
child 1 823d42546cea
Initial commit of an experimental little Squid redirector.
.hgignore
Makefile
parser.rl
volta.c
volta.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Fri Aug 26 14:40:51 2011 -0700
@@ -0,0 +1,4 @@
+^volta$
+^parser.c$
+^parser_state.*
+.*debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Fri Aug 26 14:40:51 2011 -0700
@@ -0,0 +1,25 @@
+
+CFLAGS=-O2 -Wall
+CFLAGS_DEBUG=-Wall -DDEBUG -DPROG='"volta (debugmode)"'
+LIBS=-lsqlite3
+
+volta: parser.c volta.c volta.h
+	$(CC) $(CFLAGS) $(LIBS) -o $@ *.c
+	strip $@
+
+parser.c: parser.rl
+	ragel -L -C -e -G2 parser.rl -o $@
+
+debug: volta_debug
+
+volta_debug: parser_debug.c volta.h
+	$(CC) $(CFLAGS_DEBUG) $(LIBS) -o volta *.c
+
+parser_debug.c: parser.c
+	ragel -V parser.rl > parser_state.dot
+	ragel -C -e -G2 -V -x parser.rl -o parser_state.xml
+	dot -Tpng parser_state.dot > parser_state.png
+
+clean:
+	@rm -rf volta volta_debug* parser.c parser_state.*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parser.rl	Fri Aug 26 14:40:51 2011 -0700
@@ -0,0 +1,51 @@
+/* vim: set noet nosta sw=4 ts=4 ft=ragel : */
+
+#include "volta.h"
+
+/* state machine data */
+%%{
+	machine redirector;
+
+	action yay {
+		printf( "YAH\n" );
+	}
+
+	# http://, ftp://, https://, etc
+	proto = alpha{3,5} . '://';
+
+	# http://mahlon:password@example.com or http://mahlon@example.com
+    #       username              optional password
+	creds = ( alnum | [+._\-] )+ . ( ':' . any+ )? . '@';
+
+	main := ( proto . creds ) | proto @yay '\n';
+}%%
+%% write data;
+
+int
+parse( char *p )
+{
+   	/* initial machine state */
+	short int cs = 0;
+
+	/* the client request object */
+	request c_request;
+	request *cp_request = &c_request;
+
+	/*
+	char ip[ INET_ADDRSTRLEN ];
+	inet_pton( AF_INET, "127.0.0.1", &cp_request->ip );
+	inet_ntop( AF_INET, &cp_request->ip, ip, INET_ADDRSTRLEN );
+	*/
+
+	/* initalize state machine with current line */
+	char *pe = p + strlen(p) + 1;
+
+	/* enter state machine */
+	%% write init;
+	%% write exec;
+
+	/* reset the request */
+	/* c_request = reset_request; */
+	return( 0 );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/volta.c	Fri Aug 26 14:40:51 2011 -0700
@@ -0,0 +1,103 @@
+/* vim: set noet nosta sw=4 ts=4 ft=c : */
+/* Squid docs:
+---------------------------------------------------------------------------
+TAG: url_rewrite_program
+Specify the location of the executable for the URL rewriter.
+Since they can perform almost any function there isn't one included.
+
+For each requested URL rewriter will receive on line with the format
+
+URL <SP> client_ip "/" fqdn <SP> user <SP> method [<SP> kvpairs]<NL>
+
+In the future, the rewriter interface will be extended with
+key=value pairs ("kvpairs" shown above).  Rewriter programs
+should be prepared to receive and possibly ignore additional
+whitespace-separated tokens on each input line.
+
+And the rewriter may return a rewritten URL. The other components of
+the request line does not need to be returned (ignored if they are).
+
+The rewriter can also indicate that a client-side redirect should
+be performed to the new URL. This is done by prefixing the returned
+URL with "301:" (moved permanently) or 302: (moved temporarily).
+
+By default, a URL rewriter is not used.
+--------------------------------------------------------------------------- */
+
+/*
+ * TODO
+ *
+ * flush stdout on writes
+ * empty struct not necessary?
+ * inet_pton( AF_INET, *char src, dest )
+ *
+ */
+
+#include "volta.h"
+
+int
+main( int argc, char *argv[] ) {
+
+	int opt;
+
+	/* storage for line received from squid */
+	char line[ LINE_BUFSIZE ];
+
+	while ( (opt = getopt( argc, argv, "a:hv" )) != -1 ) {
+		switch ( opt ) {
+			case 'a':
+				printf( "a -> '%s' (no-op at the moment)\n", optarg );
+				break;
+			case 'h':
+				usage( argv[0] );
+				return( 0 );
+			case 'v':
+				printf( "%s version %s\n", PROG, VERSION );
+				return( 0 );
+			case '?':
+			default:
+				break;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	/* start stdin line loop */
+	while( fgets( line, LINE_BUFSIZE, stdin ) != NULL ) parse( line );
+
+	/* stdin closed */
+    debug( "End of stream, shutting down.\n" );
+    return( 0 );
+}
+
+/*
+ * Basic usage
+ */
+void
+usage( char *prg )
+{
+	printf( "%s [-vh] [-a <init>]\n", prg );
+	printf( "    -v Display version\n" );
+	printf( "    -h Usage (you're lookin' at it)\n" );
+	printf( "    -a Perform an action:\n" );
+	printf( "         init: Initialize a new database\n" );
+	printf( "\n" );
+	return;
+}
+
+
+/*
+ * Debug function, only output to stderr if -DDEBUG set
+ */
+void
+debug( const char *fmt, ... )
+{
+    va_list args;
+	va_start( args, fmt );
+#ifdef DEBUG
+	fprintf( stderr, "%s %d: ", PROG, getpid() );
+	vfprintf( stderr, fmt, args );
+#endif
+	va_end( args );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/volta.h	Fri Aug 26 14:40:51 2011 -0700
@@ -0,0 +1,45 @@
+
+#ifndef _VOLTA_H
+#define _VOLTA_H
+
+#ifndef PROG
+#define PROG    "volta"
+#endif
+#define VERSION "$Version$" /* expanded by mercurial */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+/* Maximum length per line from Squid */
+#define LINE_BUFSIZE 2048
+
+/* URL <SP> client_ip "/" fqdn <SP> user <SP> method [<SP> kvpairs]<NL> */
+typedef struct request {
+	char   *url;
+	char   *host;
+	struct sockaddr_in ip;
+	char   *ip_fqdn;
+	char   *user;
+	char   *method;
+	char   *kvpairs;
+} request;
+
+/* An "empty" request struct used for re-assignment */
+static const struct request reset_request;
+
+/* Prototypes */
+void usage( char *prg );
+void debug( const char *fmt, ... );
+int  parse( char *p );
+
+#endif
+