Permalink
Browse files

initial files

  • Loading branch information...
0 parents commit 18bbafe9a05968459badac55f0f58c40f9ded49a Lakshan committed Dec 10, 2009
@@ -0,0 +1,38 @@
+ # Store HTTP header name-value pairs direcly to a string
+ # and allow duplicated entries on some names.
+ class Headers
+ HEADER_FORMAT = "%s: %s\r\n".freeze
+ ALLOWED_DUPLICATES = %w(Set-Cookie Set-Cookie2 Warning WWW-Authenticate).freeze
+
+ def initialize
+ @sent = {}
+ @out = []
+ end
+
+ # Add <tt>key: value</tt> pair to the headers.
+ # Ignore if already sent and no duplicates are allowed
+ # for this +key+.
+ def []=(key, value)
+ if !@sent.has_key?(key) || ALLOWED_DUPLICATES.include?(key)
+ @sent[key] = true
+ value = case value
+ when Time
+ value.httpdate
+ when NilClass
+ return
+ else
+ value.to_s
+ end
+ @out << HEADER_FORMAT % [key, value]
+ end
+ end
+
+ def has_key?(key)
+ @sent[key]
+ end
+
+ def to_s
+ @out.join
+ end
+ end
+
@@ -0,0 +1,105 @@
+require "thin_parser"
+require "stringio"
+
+class InvalidRequest < IOError; end
+
+ # A request sent by the client to the server.
+class Request
+ # Maximum request body size before it is moved out of memory
+ # and into a tempfile for reading.
+ MAX_BODY = 1024 * (80 + 32)
+ BODY_TMPFILE = 'thin-body'.freeze
+ MAX_HEADER = 1024 * (80 + 32)
+
+ INITIAL_BODY = ''
+ # Force external_encoding of request's body to ASCII_8BIT
+ INITIAL_BODY.encode!(Encoding::ASCII_8BIT) if INITIAL_BODY.respond_to?(:encode)
+
+ # Freeze some HTTP header names & values
+ SERVER_SOFTWARE = 'SERVER_SOFTWARE'.freeze
+ SERVER_NAME = 'SERVER_NAME'.freeze
+ LOCALHOST = 'localhost'.freeze
+ HTTP_VERSION = 'HTTP_VERSION'.freeze
+ HTTP_1_0 = 'HTTP/1.0'.freeze
+ REMOTE_ADDR = 'REMOTE_ADDR'.freeze
+ CONTENT_LENGTH = 'CONTENT_LENGTH'.freeze
+ CONNECTION = 'HTTP_CONNECTION'.freeze
+ KEEP_ALIVE_REGEXP = /\bkeep-alive\b/i.freeze
+ CLOSE_REGEXP = /\bclose\b/i.freeze
+
+ # Freeze some Rack header names
+ RACK_INPUT = 'rack.input'.freeze
+ RACK_VERSION = 'rack.version'.freeze
+ RACK_ERRORS = 'rack.errors'.freeze
+ RACK_MULTITHREAD = 'rack.multithread'.freeze
+ RACK_MULTIPROCESS = 'rack.multiprocess'.freeze
+ RACK_RUN_ONCE = 'rack.run_once'.freeze
+ ASYNC_CALLBACK = 'async.callback'.freeze
+ ASYNC_CLOSE = 'async.close'.freeze
+
+ # CGI-like request environment variables
+ attr_reader :env
+
+ # Unparsed data of the request
+ attr_reader :data
+
+ # Request body
+ # attr_reader :body
+ attr_accessor :messages
+
+ def initialize
+ @parser = Thin::HttpParser.new
+ @data = ''
+ @nparsed = 0
+ @messages = "" #StringIO.new(INITIAL_BODY.dup)
+ @env = {
+ SERVER_SOFTWARE => "WebSocketThin",
+ SERVER_NAME => LOCALHOST,
+
+ # Rack stuff
+ RACK_INPUT => @messages,
+
+ RACK_VERSION => [1, 0].freeze, #VERSION::RACK,
+ RACK_ERRORS => STDERR,
+
+ RACK_MULTITHREAD => false,
+ RACK_MULTIPROCESS => false,
+ RACK_RUN_ONCE => false
+ }
+ end
+
+ # Parse a chunk of data into the request environment
+ # Raises a +InvalidRequest+ if invalid.
+ # Returns +true+ if the parsing is complete.
+ def parse(data)
+ if @parser.finished? # Header finished, can only be some more body
+ @messages << data
+ else # Parse more header using the super parser
+ @data << data
+ raise InvalidRequest, 'Header longer than allowed' if @data.size > MAX_HEADER
+
+ @nparsed = @parser.execute(@env, @data, @nparsed)
+
+ # Transfert to a tempfile if body is very big
+ # move_body_to_tempfile if @parser.finished? && content_length > MAX_BODY
+ end
+
+ if finished? # Check if header and body are complete
+ @data = nil
+ #@body.rewind
+ true # Request is fully parsed
+ else
+ false # Not finished, need more data
+ end
+ end
+
+ # +true+ if headers and body are finished parsing
+ def finished?
+ @parser.finished? && @messages.size >= content_length
+ end
+
+ # Expected size of the body
+ def content_length
+ @env[CONTENT_LENGTH].to_i
+ end
+end
@@ -0,0 +1,157 @@
+
+SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = .
+topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
+hdrdir = $(topdir)
+VPATH = $(srcdir):$(topdir):$(hdrdir)
+exec_prefix = $(prefix)
+prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
+sharedstatedir = $(prefix)/com
+mandir = $(DESTDIR)/usr/share/man
+psdir = $(docdir)
+oldincludedir = $(DESTDIR)/usr/include
+localedir = $(datarootdir)/locale
+bindir = $(exec_prefix)/bin
+libexecdir = $(exec_prefix)/libexec
+sitedir = $(DESTDIR)/Library/Ruby/Site
+htmldir = $(docdir)
+vendorarchdir = $(vendorlibdir)/$(sitearch)
+includedir = $(prefix)/include
+infodir = $(DESTDIR)/usr/share/info
+vendorlibdir = $(vendordir)/$(ruby_version)
+sysconfdir = $(prefix)/etc
+libdir = $(exec_prefix)/lib
+sbindir = $(exec_prefix)/sbin
+rubylibdir = $(libdir)/ruby/$(ruby_version)
+docdir = $(datarootdir)/doc/$(PACKAGE)
+dvidir = $(docdir)
+vendordir = $(libdir)/ruby/vendor_ruby
+datarootdir = $(prefix)/share
+pdfdir = $(docdir)
+archdir = $(rubylibdir)/$(arch)
+sitearchdir = $(sitelibdir)/$(sitearch)
+datadir = $(datarootdir)
+localstatedir = $(prefix)/var
+sitelibdir = $(sitedir)/$(ruby_version)
+
+CC = gcc
+LIBRUBY = $(LIBRUBY_SO)
+LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
+LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
+LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
+
+RUBY_EXTCONF_H =
+CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags)
+INCFLAGS = -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I.
+DEFS =
+CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE
+CXXFLAGS = $(CFLAGS)
+ldflags = -L. -arch i386 -arch x86_64
+dldflags =
+archflag =
+DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
+LDSHARED = cc -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
+AR = ar
+EXEEXT =
+
+RUBY_INSTALL_NAME = ruby
+RUBY_SO_NAME = ruby
+arch = universal-darwin10.0
+sitearch = universal-darwin10.0
+ruby_version = 1.8
+ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
+RUBY = $(ruby)
+RM = rm -f
+MAKEDIRS = mkdir -p
+INSTALL = /usr/bin/install -c
+INSTALL_PROG = $(INSTALL) -m 0755
+INSTALL_DATA = $(INSTALL) -m 644
+COPY = cp
+
+#### End of system configuration section. ####
+
+preload =
+
+libpath = . $(libdir)
+LIBPATH = -L. -L$(libdir)
+DEFFILE =
+
+CLEANFILES = mkmf.log
+DISTCLEANFILES =
+
+extout =
+extout_prefix =
+target_prefix =
+LOCAL_LIBS =
+LIBS = $(LIBRUBYARG_SHARED) -lc -lpthread -ldl
+SRCS = parser.c thin.c
+OBJS = parser.o thin.o
+TARGET = thin_parser
+DLLIB = $(TARGET).bundle
+EXTSTATIC =
+STATIC_LIB =
+
+BINDIR = $(bindir)
+RUBYCOMMONDIR = $(sitedir)$(target_prefix)
+RUBYLIBDIR = $(sitelibdir)$(target_prefix)
+RUBYARCHDIR = $(sitearchdir)$(target_prefix)
+
+TARGET_SO = $(DLLIB)
+CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
+CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
+
+all: $(DLLIB)
+static: $(STATIC_LIB)
+
+clean:
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
+
+distclean: clean
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
+
+realclean: distclean
+install: install-so install-rb
+
+install-so: $(RUBYARCHDIR)
+install-so: $(RUBYARCHDIR)/$(DLLIB)
+$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
+install-rb: pre-install-rb install-rb-default
+install-rb-default: pre-install-rb-default
+pre-install-rb: Makefile
+pre-install-rb-default: Makefile
+$(RUBYARCHDIR):
+ $(MAKEDIRS) $@
+
+site-install: site-install-so site-install-rb
+site-install-so: install-so
+site-install-rb: install-rb
+
+.SUFFIXES: .c .m .cc .cxx .cpp .C .o
+
+.cc.o:
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
+
+.cxx.o:
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
+
+.cpp.o:
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
+
+.C.o:
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
+
+.c.o:
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
+
+$(DLLIB): $(OBJS)
+ @-$(RM) $@
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
+
+
+
+$(OBJS): ruby.h defines.h
@@ -0,0 +1,55 @@
+%%{
+
+ machine http_parser_common;
+
+#### HTTP PROTOCOL GRAMMAR
+# line endings
+ CRLF = "\r\n";
+
+# character types
+ CTL = (cntrl | 127);
+ safe = ("$" | "-" | "_" | ".");
+ extra = ("!" | "*" | "'" | "(" | ")" | ",");
+ reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+");
+ sorta_safe = ("\"" | "<" | ">");
+ unsafe = (CTL | " " | "#" | "%" | sorta_safe);
+ national = any -- (alpha | digit | reserved | extra | safe | unsafe);
+ unreserved = (alpha | digit | safe | extra | national);
+ escape = ("%" xdigit xdigit);
+ uchar = (unreserved | escape | sorta_safe);
+ pchar = (uchar | ":" | "@" | "&" | "=" | "+");
+ tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
+
+# elements
+ token = (ascii -- (CTL | tspecials));
+
+# URI schemes and absolute paths
+ scheme = ( alpha | digit | "+" | "-" | "." )* ;
+ absolute_uri = (scheme ":" (uchar | reserved )*);
+
+ path = ( pchar+ ( "/" pchar* )* ) ;
+ query = ( uchar | reserved )* %query_string ;
+ param = ( pchar | "/" )* ;
+ params = ( param ( ";" param )* ) ;
+ rel_path = ( path? (";" params)? %request_path) ("?" %start_query query)?;
+ absolute_path = ( "/"+ rel_path );
+
+ Request_URI = ( "*" | absolute_uri | absolute_path ) >mark %request_uri;
+ Fragment = ( uchar | reserved )* >mark %fragment;
+ Method = ( upper | digit | safe ){1,20} >mark %request_method;
+
+ http_number = ( digit+ "." digit+ ) ;
+ HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
+ Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
+
+ field_name = ( token -- ":" )+ >start_field %write_field;
+
+ field_value = any* >start_value %write_value;
+
+ message_header = field_name ":" " "* field_value :> CRLF;
+
+ Request = Request_Line ( message_header )* ( CRLF @done );
+
+main := Request;
+
+}%%
@@ -0,0 +1,14 @@
+#ifndef ext_help_h
+#define ext_help_h
+
+#define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
+#define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
+#define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
+
+#ifdef DEBUG
+#define TRACE() fprintf(stderr, "> %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
+#else
+#define TRACE()
+#endif
+
+#endif
@@ -0,0 +1,6 @@
+require 'mkmf'
+
+dir_config("thin_parser")
+have_library("c", "main")
+
+create_makefile("thin_parser")
@@ -0,0 +1,12 @@
+have_library: checking for main() in -lc... -------------------- yes
+
+"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lc -lpthread -ldl "
+checked program was:
+/* begin */
+1: /*top*/
+2: int main() { return 0; }
+3: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
+/* end */
+
+--------------------
+
Oops, something went wrong.

0 comments on commit 18bbafe

Please sign in to comment.