ebb 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +4 -7
- data/benchmark/application.rb +12 -4
- data/benchmark/server_test.rb +10 -11
- data/bin/ebb_rails +0 -0
- data/libev/ev.c +235 -128
- data/libev/ev.h +84 -27
- data/libev/ev_epoll.c +30 -22
- data/libev/ev_kqueue.c +30 -22
- data/libev/ev_poll.c +30 -22
- data/libev/ev_port.c +30 -22
- data/libev/ev_select.c +34 -26
- data/libev/ev_vars.h +49 -0
- data/libev/ev_win32.c +31 -23
- data/libev/ev_wrap.h +12 -0
- data/ruby_lib/ebb.rb +94 -67
- data/ruby_lib/ebb/runner.rb +4 -5
- data/ruby_lib/ebb/runner/rails.rb +1 -4
- data/ruby_lib/rack/adapter/rails.rb +5 -0
- data/src/ebb.c +261 -387
- data/src/ebb.h +19 -29
- data/src/ebb_ruby.c +113 -108
- data/src/extconf.rb +0 -1
- data/src/parser.c +1755 -724
- data/src/parser.h +13 -10
- data/test/basic_test.rb +18 -1
- data/test/env_test.rb +6 -5
- data/test/helper.rb +53 -1
- metadata +3 -4
- data/benchmark/bench_results.rb +0 -58
    
        data/libev/ev_vars.h
    CHANGED
    
    | @@ -1,3 +1,42 @@ | |
| 1 | 
            +
            /*
         | 
| 2 | 
            +
             * loop member variable declarations
         | 
| 3 | 
            +
             *
         | 
| 4 | 
            +
             * Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
         | 
| 5 | 
            +
             * All rights reserved.
         | 
| 6 | 
            +
             *
         | 
| 7 | 
            +
             * Redistribution and use in source and binary forms, with or without modifica-
         | 
| 8 | 
            +
             * tion, are permitted provided that the following conditions are met:
         | 
| 9 | 
            +
             * 
         | 
| 10 | 
            +
             *   1.  Redistributions of source code must retain the above copyright notice,
         | 
| 11 | 
            +
             *       this list of conditions and the following disclaimer.
         | 
| 12 | 
            +
             * 
         | 
| 13 | 
            +
             *   2.  Redistributions in binary form must reproduce the above copyright
         | 
| 14 | 
            +
             *       notice, this list of conditions and the following disclaimer in the
         | 
| 15 | 
            +
             *       documentation and/or other materials provided with the distribution.
         | 
| 16 | 
            +
             * 
         | 
| 17 | 
            +
             * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
         | 
| 18 | 
            +
             * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
         | 
| 19 | 
            +
             * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
         | 
| 20 | 
            +
             * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
         | 
| 21 | 
            +
             * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
         | 
| 22 | 
            +
             * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
         | 
| 23 | 
            +
             * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
         | 
| 24 | 
            +
             * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
         | 
| 25 | 
            +
             * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
         | 
| 26 | 
            +
             * OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
| 27 | 
            +
             *
         | 
| 28 | 
            +
             * Alternatively, the contents of this file may be used under the terms of
         | 
| 29 | 
            +
             * the GNU General Public License ("GPL") version 2 or any later version,
         | 
| 30 | 
            +
             * in which case the provisions of the GPL are applicable instead of
         | 
| 31 | 
            +
             * the above. If you wish to allow the use of your version of this file
         | 
| 32 | 
            +
             * only under the terms of the GPL and not to allow others to use your
         | 
| 33 | 
            +
             * version of this file under the BSD license, indicate your decision
         | 
| 34 | 
            +
             * by deleting the provisions above and replace them with the notice
         | 
| 35 | 
            +
             * and other provisions required by the GPL. If you do not delete the
         | 
| 36 | 
            +
             * provisions above, a recipient may use your version of this file under
         | 
| 37 | 
            +
             * either the BSD or the GPL.
         | 
| 38 | 
            +
             */
         | 
| 39 | 
            +
             | 
| 1 40 | 
             
            #define VARx(type,name) VAR(name, type name)
         | 
| 2 41 |  | 
| 3 42 | 
             
            VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */
         | 
| @@ -16,6 +55,9 @@ VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */ | |
| 16 55 | 
             
            VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))
         | 
| 17 56 | 
             
            VAR (backend_poll  , void (*backend_poll)(EV_P_ ev_tstamp timeout))
         | 
| 18 57 |  | 
| 58 | 
            +
            VAR (evpipe, int evpipe [2])
         | 
| 59 | 
            +
            VARx(ev_io, pipeev)
         | 
| 60 | 
            +
             | 
| 19 61 | 
             
            #if !defined(_WIN32) || EV_GENWRAP
         | 
| 20 62 | 
             
            VARx(pid_t, curpid)
         | 
| 21 63 | 
             
            #endif
         | 
| @@ -98,6 +140,13 @@ VARx(int, forkmax) | |
| 98 140 | 
             
            VARx(int, forkcnt)
         | 
| 99 141 | 
             
            #endif
         | 
| 100 142 |  | 
| 143 | 
            +
            VARx(EV_ATOMIC_T, gotasync)
         | 
| 144 | 
            +
            #if EV_ASYNC_ENABLE || EV_GENWRAP
         | 
| 145 | 
            +
            VARx(struct ev_async **, asyncs)
         | 
| 146 | 
            +
            VARx(int, asyncmax)
         | 
| 147 | 
            +
            VARx(int, asynccnt)
         | 
| 148 | 
            +
            #endif
         | 
| 149 | 
            +
             | 
| 101 150 | 
             
            #if EV_USE_INOTIFY || EV_GENWRAP
         | 
| 102 151 | 
             
            VARx(int, fs_fd)
         | 
| 103 152 | 
             
            VARx(ev_io, fs_w)
         | 
    
        data/libev/ev_win32.c
    CHANGED
    
    | @@ -1,32 +1,40 @@ | |
| 1 1 | 
             
            /*
         | 
| 2 | 
            -
             * libev win32 compatibility cruft
         | 
| 2 | 
            +
             * libev win32 compatibility cruft (_not_ a backend)
         | 
| 3 3 | 
             
             *
         | 
| 4 4 | 
             
             * Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
         | 
| 5 5 | 
             
             * All rights reserved.
         | 
| 6 6 | 
             
             *
         | 
| 7 | 
            -
             * Redistribution and use in source and binary forms, with or without
         | 
| 8 | 
            -
             *  | 
| 9 | 
            -
             *  | 
| 7 | 
            +
             * Redistribution and use in source and binary forms, with or without modifica-
         | 
| 8 | 
            +
             * tion, are permitted provided that the following conditions are met:
         | 
| 9 | 
            +
             * 
         | 
| 10 | 
            +
             *   1.  Redistributions of source code must retain the above copyright notice,
         | 
| 11 | 
            +
             *       this list of conditions and the following disclaimer.
         | 
| 12 | 
            +
             * 
         | 
| 13 | 
            +
             *   2.  Redistributions in binary form must reproduce the above copyright
         | 
| 14 | 
            +
             *       notice, this list of conditions and the following disclaimer in the
         | 
| 15 | 
            +
             *       documentation and/or other materials provided with the distribution.
         | 
| 16 | 
            +
             * 
         | 
| 17 | 
            +
             * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
         | 
| 18 | 
            +
             * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
         | 
| 19 | 
            +
             * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
         | 
| 20 | 
            +
             * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
         | 
| 21 | 
            +
             * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
         | 
| 22 | 
            +
             * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
         | 
| 23 | 
            +
             * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
         | 
| 24 | 
            +
             * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
         | 
| 25 | 
            +
             * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
         | 
| 26 | 
            +
             * OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
| 10 27 | 
             
             *
         | 
| 11 | 
            -
             * | 
| 12 | 
            -
             * | 
| 13 | 
            -
             *
         | 
| 14 | 
            -
             * | 
| 15 | 
            -
             * | 
| 16 | 
            -
             * | 
| 17 | 
            -
             * | 
| 18 | 
            -
             *
         | 
| 19 | 
            -
             *  | 
| 20 | 
            -
             *  | 
| 21 | 
            -
             * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
         | 
| 22 | 
            -
             * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
         | 
| 23 | 
            -
             * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
         | 
| 24 | 
            -
             * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
         | 
| 25 | 
            -
             * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
         | 
| 26 | 
            -
             * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
         | 
| 27 | 
            -
             * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
         | 
| 28 | 
            -
             * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         | 
| 29 | 
            -
             * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
| 28 | 
            +
             * Alternatively, the contents of this file may be used under the terms of
         | 
| 29 | 
            +
             * the GNU General Public License ("GPL") version 2 or any later version,
         | 
| 30 | 
            +
             * in which case the provisions of the GPL are applicable instead of
         | 
| 31 | 
            +
             * the above. If you wish to allow the use of your version of this file
         | 
| 32 | 
            +
             * only under the terms of the GPL and not to allow others to use your
         | 
| 33 | 
            +
             * version of this file under the BSD license, indicate your decision
         | 
| 34 | 
            +
             * by deleting the provisions above and replace them with the notice
         | 
| 35 | 
            +
             * and other provisions required by the GPL. If you do not delete the
         | 
| 36 | 
            +
             * provisions above, a recipient may use your version of this file under
         | 
| 37 | 
            +
             * either the BSD or the GPL.
         | 
| 30 38 | 
             
             */
         | 
| 31 39 |  | 
| 32 40 | 
             
            #ifdef _WIN32
         | 
    
        data/libev/ev_wrap.h
    CHANGED
    
    | @@ -13,6 +13,8 @@ | |
| 13 13 | 
             
            #define backend_fudge ((loop)->backend_fudge)
         | 
| 14 14 | 
             
            #define backend_modify ((loop)->backend_modify)
         | 
| 15 15 | 
             
            #define backend_poll ((loop)->backend_poll)
         | 
| 16 | 
            +
            #define evpipe ((loop)->evpipe)
         | 
| 17 | 
            +
            #define pipeev ((loop)->pipeev)
         | 
| 16 18 | 
             
            #define curpid ((loop)->curpid)
         | 
| 17 19 | 
             
            #define postfork ((loop)->postfork)
         | 
| 18 20 | 
             
            #define vec_ri ((loop)->vec_ri)
         | 
| @@ -61,6 +63,10 @@ | |
| 61 63 | 
             
            #define forks ((loop)->forks)
         | 
| 62 64 | 
             
            #define forkmax ((loop)->forkmax)
         | 
| 63 65 | 
             
            #define forkcnt ((loop)->forkcnt)
         | 
| 66 | 
            +
            #define gotasync ((loop)->gotasync)
         | 
| 67 | 
            +
            #define asyncs ((loop)->asyncs)
         | 
| 68 | 
            +
            #define asyncmax ((loop)->asyncmax)
         | 
| 69 | 
            +
            #define asynccnt ((loop)->asynccnt)
         | 
| 64 70 | 
             
            #define fs_fd ((loop)->fs_fd)
         | 
| 65 71 | 
             
            #define fs_w ((loop)->fs_w)
         | 
| 66 72 | 
             
            #define fs_hash ((loop)->fs_hash)
         | 
| @@ -78,6 +84,8 @@ | |
| 78 84 | 
             
            #undef backend_fudge
         | 
| 79 85 | 
             
            #undef backend_modify
         | 
| 80 86 | 
             
            #undef backend_poll
         | 
| 87 | 
            +
            #undef evpipe
         | 
| 88 | 
            +
            #undef pipeev
         | 
| 81 89 | 
             
            #undef curpid
         | 
| 82 90 | 
             
            #undef postfork
         | 
| 83 91 | 
             
            #undef vec_ri
         | 
| @@ -126,6 +134,10 @@ | |
| 126 134 | 
             
            #undef forks
         | 
| 127 135 | 
             
            #undef forkmax
         | 
| 128 136 | 
             
            #undef forkcnt
         | 
| 137 | 
            +
            #undef gotasync
         | 
| 138 | 
            +
            #undef asyncs
         | 
| 139 | 
            +
            #undef asyncmax
         | 
| 140 | 
            +
            #undef asynccnt
         | 
| 129 141 | 
             
            #undef fs_fd
         | 
| 130 142 | 
             
            #undef fs_w
         | 
| 131 143 | 
             
            #undef fs_hash
         | 
    
        data/ruby_lib/ebb.rb
    CHANGED
    
    | @@ -3,33 +3,37 @@ | |
| 3 3 | 
             
            # See README file for details.
         | 
| 4 4 | 
             
            require 'stringio'
         | 
| 5 5 | 
             
            module Ebb
         | 
| 6 | 
            +
              VERSION = "0.2.0"
         | 
| 6 7 | 
             
              LIBDIR = File.dirname(__FILE__)
         | 
| 7 | 
            -
              require Ebb::LIBDIR + '/../src/ebb_ext'
         | 
| 8 8 | 
             
              autoload :Runner, LIBDIR + '/ebb/runner'
         | 
| 9 | 
            +
              autoload :FFI, LIBDIR + '/../src/ebb_ext'
         | 
| 9 10 |  | 
| 10 11 | 
             
              def self.start_server(app, options={})
         | 
| 11 | 
            -
                 | 
| 12 | 
            -
             | 
| 13 | 
            -
                   | 
| 12 | 
            +
                if options.has_key?(:fileno)
         | 
| 13 | 
            +
                  fd = options[:fileno].to_i
         | 
| 14 | 
            +
                  FFI::server_listen_on_fd(fd)
         | 
| 15 | 
            +
                  log.puts "Ebb is listening on file descriptor #{fd}"
         | 
| 16 | 
            +
                elsif options.has_key?(:unix_socket)
         | 
| 17 | 
            +
                  socketfile = options[:unix_socket]
         | 
| 18 | 
            +
                  FFI::server_listen_on_unix_socket(socketfile)
         | 
| 19 | 
            +
                  log.puts "Ebb is listening on unix socket #{socketfile}"
         | 
| 14 20 | 
             
                else
         | 
| 15 | 
            -
                   | 
| 21 | 
            +
                  port = (options[:port] || 4001).to_i
         | 
| 22 | 
            +
                  FFI::server_listen_on_port(port)
         | 
| 23 | 
            +
                  log.puts "Ebb is listening at http://0.0.0.0:#{port}/"
         | 
| 16 24 | 
             
                end
         | 
| 25 | 
            +
                log.puts "Ebb PID #{Process.pid}"
         | 
| 17 26 |  | 
| 18 | 
            -
                Client::BASE_ENV['rack.multithread'] = threaded_processing
         | 
| 19 | 
            -
                
         | 
| 20 | 
            -
                FFI::server_listen_on_port(port)
         | 
| 21 27 | 
             
                @running = true
         | 
| 22 28 | 
             
                trap('INT')  { stop_server }
         | 
| 23 29 |  | 
| 24 | 
            -
                log.puts "Ebb listening at http://0.0.0.0:#{port}/ (#{threaded_processing ? 'threaded' : 'sequential'} processing, PID #{Process.pid})"
         | 
| 25 | 
            -
                
         | 
| 26 30 | 
             
                while @running
         | 
| 27 31 | 
             
                  FFI::server_process_connections()
         | 
| 28 | 
            -
                  while client = FFI:: | 
| 29 | 
            -
                    if  | 
| 30 | 
            -
                      Thread.new(client) { |c| process(app, c) }
         | 
| 31 | 
            -
                    else
         | 
| 32 | 
            +
                  while client = FFI::server_waiting_clients.shift
         | 
| 33 | 
            +
                    if app.respond_to?(:deferred?) and !app.deferred?(client.env)
         | 
| 32 34 | 
             
                      process(app, client)
         | 
| 35 | 
            +
                    else
         | 
| 36 | 
            +
                      Thread.new(client) { |c| process(app, c) }
         | 
| 33 37 | 
             
                    end
         | 
| 34 38 | 
             
                  end
         | 
| 35 39 | 
             
                end
         | 
| @@ -45,34 +49,40 @@ module Ebb | |
| 45 49 | 
             
              end
         | 
| 46 50 |  | 
| 47 51 | 
             
              def self.process(app, client)
         | 
| 48 | 
            -
                 | 
| 49 | 
            -
             | 
| 50 | 
            -
                rescue
         | 
| 51 | 
            -
                  raise if $DEBUG
         | 
| 52 | 
            -
                  status = 500
         | 
| 53 | 
            -
                  headers = {'Content-Type' => 'text/plain'}
         | 
| 54 | 
            -
                  body = "Internal Server Error\n"
         | 
| 55 | 
            -
                end
         | 
| 52 | 
            +
                #p client.env
         | 
| 53 | 
            +
                status, headers, body = app.call(client.env)
         | 
| 56 54 |  | 
| 55 | 
            +
                # Write the status
         | 
| 57 56 | 
             
                client.write_status(status)
         | 
| 58 57 |  | 
| 59 | 
            -
                 | 
| 60 | 
            -
             | 
| 58 | 
            +
                # Add Content-Length to the headers.
         | 
| 59 | 
            +
                if headers['Content-Length'].nil? and
         | 
| 60 | 
            +
                   headers.respond_to?(:[]=) and 
         | 
| 61 | 
            +
                   body.respond_to?(:length) and 
         | 
| 62 | 
            +
                   status != 304
         | 
| 63 | 
            +
                then
         | 
| 61 64 | 
             
                  headers['Content-Length'] = body.length.to_s
         | 
| 62 65 | 
             
                end
         | 
| 63 66 |  | 
| 67 | 
            +
                # Decide if we should keep the connection alive or not
         | 
| 68 | 
            +
                if headers['Connection'].nil?
         | 
| 69 | 
            +
                  if headers['Content-Length'] and client.should_keep_alive?
         | 
| 70 | 
            +
                    headers['Connection'] = 'Keep-Alive'
         | 
| 71 | 
            +
                  else
         | 
| 72 | 
            +
                    headers['Connection'] = 'close'
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
                
         | 
| 76 | 
            +
                # Write the headers
         | 
| 64 77 | 
             
                headers.each { |field, value| client.write_header(field, value) }
         | 
| 65 | 
            -
                client.write("\r\n")
         | 
| 66 78 |  | 
| 79 | 
            +
                # Write the body
         | 
| 67 80 | 
             
                if body.kind_of?(String)
         | 
| 68 | 
            -
                  client. | 
| 69 | 
            -
                  client.body_written()
         | 
| 70 | 
            -
                  client.begin_transmission()
         | 
| 81 | 
            +
                  client.write_body(body)
         | 
| 71 82 | 
             
                else
         | 
| 72 | 
            -
                  client. | 
| 73 | 
            -
                  body.each { |p| client.write(p) }
         | 
| 74 | 
            -
                  client.body_written()
         | 
| 83 | 
            +
                  body.each { |p| client.write_body(p) }
         | 
| 75 84 | 
             
                end
         | 
| 85 | 
            +
                
         | 
| 76 86 | 
             
              rescue => e
         | 
| 77 87 | 
             
                log.puts "Ebb Error! #{e.class}  #{e.message}"
         | 
| 78 88 | 
             
                log.puts e.backtrace.join("\n")
         | 
| @@ -88,16 +98,12 @@ module Ebb | |
| 88 98 | 
             
                @@log
         | 
| 89 99 | 
             
              end
         | 
| 90 100 |  | 
| 91 | 
            -
              # This array is created and manipulated in the C extension.
         | 
| 92 | 
            -
              def FFI.waiting_clients
         | 
| 93 | 
            -
                @waiting_clients
         | 
| 94 | 
            -
              end
         | 
| 95 | 
            -
              
         | 
| 96 101 | 
             
              class Client
         | 
| 102 | 
            +
                attr_reader :fd, :body_head, :content_length
         | 
| 97 103 | 
             
                BASE_ENV = {
         | 
| 98 104 | 
             
                  'SERVER_NAME' => '0.0.0.0',
         | 
| 99 105 | 
             
                  'SCRIPT_NAME' => '',
         | 
| 100 | 
            -
                  'SERVER_SOFTWARE' => "Ebb #{Ebb::VERSION}",
         | 
| 106 | 
            +
                  'SERVER_SOFTWARE' => "Ebb-Ruby #{Ebb::VERSION}",
         | 
| 101 107 | 
             
                  'SERVER_PROTOCOL' => 'HTTP/1.1',
         | 
| 102 108 | 
             
                  'rack.version' => [0, 1],
         | 
| 103 109 | 
             
                  'rack.errors' => STDERR,
         | 
| @@ -107,9 +113,11 @@ module Ebb | |
| 107 113 | 
             
                }
         | 
| 108 114 |  | 
| 109 115 | 
             
                def env
         | 
| 110 | 
            -
                  env  | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 116 | 
            +
                  @env ||= begin
         | 
| 117 | 
            +
                    env = FFI::client_env(self).update(BASE_ENV)
         | 
| 118 | 
            +
                    env['rack.input'] = RequestBody.new(self)
         | 
| 119 | 
            +
                    env
         | 
| 120 | 
            +
                  end
         | 
| 113 121 | 
             
                end
         | 
| 114 122 |  | 
| 115 123 | 
             
                def write_status(status)
         | 
| @@ -117,8 +125,8 @@ module Ebb | |
| 117 125 | 
             
                  FFI::client_write_status(self, s, HTTP_STATUS_CODES[s])
         | 
| 118 126 | 
             
                end
         | 
| 119 127 |  | 
| 120 | 
            -
                def  | 
| 121 | 
            -
                  FFI:: | 
| 128 | 
            +
                def write_body(data)
         | 
| 129 | 
            +
                  FFI::client_write_body(self, data)
         | 
| 122 130 | 
             
                end
         | 
| 123 131 |  | 
| 124 132 | 
             
                def write_header(field, value)
         | 
| @@ -127,50 +135,53 @@ module Ebb | |
| 127 135 | 
             
                  end
         | 
| 128 136 | 
             
                end
         | 
| 129 137 |  | 
| 130 | 
            -
                def  | 
| 131 | 
            -
                  FFI:: | 
| 138 | 
            +
                def release
         | 
| 139 | 
            +
                  FFI::client_release(self)
         | 
| 132 140 | 
             
                end
         | 
| 133 141 |  | 
| 134 | 
            -
                def  | 
| 135 | 
            -
                  FFI:: | 
| 142 | 
            +
                def set_keep_alive
         | 
| 143 | 
            +
                  FFI::client_set_keep_alive(self)
         | 
| 136 144 | 
             
                end
         | 
| 137 145 |  | 
| 138 | 
            -
                def  | 
| 139 | 
            -
                   | 
| 146 | 
            +
                def should_keep_alive?
         | 
| 147 | 
            +
                  if env['HTTP_VERSION'] == 'HTTP/1.0' 
         | 
| 148 | 
            +
                    return true if env['HTTP_CONNECTION'] =~ /Keep-Alive/i
         | 
| 149 | 
            +
                  else
         | 
| 150 | 
            +
                    return true unless env['HTTP_CONNECTION'] =~ /close/i
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
                  false
         | 
| 140 153 | 
             
                end
         | 
| 141 154 | 
             
              end
         | 
| 142 155 |  | 
| 143 156 | 
             
              class RequestBody
         | 
| 144 157 | 
             
                def initialize(client)
         | 
| 145 | 
            -
                  @ | 
| 158 | 
            +
                  @content_length = client.content_length
         | 
| 159 | 
            +
                  if client.body_head
         | 
| 160 | 
            +
                    @body_head = StringIO.new(client.body_head)
         | 
| 161 | 
            +
                    if @body_head.length < @content_length
         | 
| 162 | 
            +
                      @socket = IO.new(client.fd)
         | 
| 163 | 
            +
                    end
         | 
| 164 | 
            +
                  end
         | 
| 165 | 
            +
                  @total_read = 0
         | 
| 146 166 | 
             
                end
         | 
| 147 167 |  | 
| 148 168 | 
             
                def read(len = nil)
         | 
| 149 | 
            -
                   | 
| 150 | 
            -
             | 
| 151 | 
            -
                   | 
| 152 | 
            -
                    if  | 
| 153 | 
            -
             | 
| 154 | 
            -
                      while(chunk = read(10*1024)) do
         | 
| 155 | 
            -
                        s << chunk
         | 
| 156 | 
            -
                      end
         | 
| 157 | 
            -
                      s
         | 
| 158 | 
            -
                    else
         | 
| 159 | 
            -
                      FFI::client_read_input(@client, len)
         | 
| 160 | 
            -
                    end
         | 
| 169 | 
            +
                  to_read =  len.nil? ? @content_length - @total_read : min(len, @content_length - @total_read)
         | 
| 170 | 
            +
                  return nil if to_read == 0 or @body_head.nil?
         | 
| 171 | 
            +
                  unless out = @body_head.read(to_read)
         | 
| 172 | 
            +
                    return nil if @socket.nil?
         | 
| 173 | 
            +
                    out = @socket.read(to_read)
         | 
| 161 174 | 
             
                  end
         | 
| 175 | 
            +
                  @total_read += out.length
         | 
| 176 | 
            +
                  out
         | 
| 162 177 | 
             
                end
         | 
| 163 178 |  | 
| 164 179 | 
             
                def gets
         | 
| 165 | 
            -
                   | 
| 180 | 
            +
                  raise NotImplemented
         | 
| 166 181 | 
             
                end
         | 
| 167 182 |  | 
| 168 183 | 
             
                def each(&block)
         | 
| 169 | 
            -
                   | 
| 170 | 
            -
                end
         | 
| 171 | 
            -
                
         | 
| 172 | 
            -
                def io
         | 
| 173 | 
            -
                  @io ||= StringIO.new(read)
         | 
| 184 | 
            +
                  raise NotImplemented
         | 
| 174 185 | 
             
                end
         | 
| 175 186 | 
             
              end
         | 
| 176 187 |  | 
| @@ -215,3 +226,19 @@ module Ebb | |
| 215 226 | 
             
                505  => 'HTTP Version not supported'
         | 
| 216 227 | 
             
              }.freeze
         | 
| 217 228 | 
             
            end
         | 
| 229 | 
            +
             | 
| 230 | 
            +
             | 
| 231 | 
            +
            module Rack
         | 
| 232 | 
            +
              module Handler
         | 
| 233 | 
            +
                module Ebb
         | 
| 234 | 
            +
                  def self.run(app, options={})
         | 
| 235 | 
            +
                    ::Ebb.start_server(app, options)
         | 
| 236 | 
            +
                  end
         | 
| 237 | 
            +
                end
         | 
| 238 | 
            +
              end
         | 
| 239 | 
            +
            end
         | 
| 240 | 
            +
             | 
| 241 | 
            +
            # cause i don't want to create an array
         | 
| 242 | 
            +
            def min(a,b)
         | 
| 243 | 
            +
              a > b ? b : a
         | 
| 244 | 
            +
            end
         | 
    
        data/ruby_lib/ebb/runner.rb
    CHANGED
    
    | @@ -58,8 +58,7 @@ module Ebb | |
| 58 58 | 
             
                  @parser = OptionParser.new
         | 
| 59 59 | 
             
                  @options = {
         | 
| 60 60 | 
             
                    :port => 4001,
         | 
| 61 | 
            -
                    :timeout => 60 | 
| 62 | 
            -
                    :threaded_processing => true
         | 
| 61 | 
            +
                    :timeout => 60
         | 
| 63 62 | 
             
                  }
         | 
| 64 63 | 
             
                end
         | 
| 65 64 |  | 
| @@ -69,8 +68,8 @@ module Ebb | |
| 69 68 | 
             
                  extra_options if respond_to?(:extra_options)
         | 
| 70 69 |  | 
| 71 70 | 
             
                  @parser.separator ""
         | 
| 72 | 
            -
                   | 
| 73 | 
            -
                  @parser.on("- | 
| 71 | 
            +
                  @parser.on("-p", "--port PORT", "(default: #{@options[:port]})") { |p| @options[:port] = p }
         | 
| 72 | 
            +
                  @parser.on("-s", "--socket SOCKET", "listen on unix domain socket") { |socket| options[:unix_socket] = socket }
         | 
| 74 73 | 
             
                  @parser.on("-d", "--daemonize", "Daemonize") { @options[:daemonize] = true }
         | 
| 75 74 | 
             
                  @parser.on("-l", "--log-file FILE", "File to redirect output") { |f| @options[:log_file]=f }
         | 
| 76 75 | 
             
                  @parser.on("-P", "--pid-file FILE", "File to store PID") { |f| @options[:pid_file]=f }
         | 
| @@ -82,7 +81,7 @@ module Ebb | |
| 82 81 | 
             
                    exit
         | 
| 83 82 | 
             
                  end
         | 
| 84 83 | 
             
                  @parser.on_tail('-v', '--version', "Show version") do
         | 
| 85 | 
            -
                    Ebb.log.puts  | 
| 84 | 
            +
                    Ebb.log.puts Ebb::Client::BASE_ENV['SERVER_SOFTWARE']
         | 
| 86 85 | 
             
                    exit
         | 
| 87 86 | 
             
                  end
         | 
| 88 87 |  |