Sha256: 7366cdf7287cb463fab2663f6dc2fe292b98e2a83b7f2f2cc419c47b5641cc20

Contents?: true

Size: 1.55 KB

Versions: 1

Compression:

Stored size: 1.55 KB

Contents

#! /usr/bin/env ruby

require 'kqueue'
require 'socket'

class KqServer
  include Kqueue::Event::Constants

  def self.start(port)
    kqs = new(port)
    yield kqs
    loop do
      kqs.wait.each do |ev|
        ev.udata && ev.udata[1].call(ev.udata[0])
      end
    end
  end

  def initialize(port)
    @kq = Kqueue.new
    @server = TCPServer.open(port)
    set_event @server, EVFILT_READ do
      socket = @server.accept
      set_event socket, EVFILT_READ do |socket|
        loop do
          chunk = socket.recv(1024)
          @on_data && @on_data.call(chunk)
          break if chunk.length < 4 || chunk[-4..-1] == "\r\n\r\n"
        end
        set_event socket, EVFILT_WRITE do |socket|
          @on_end && @on_end.call(socket)
          del_event(socket, EVFILT_READ)
          del_event(socket, EVFILT_WRITE)
          socket.close
        end
      end
    end
  end

  def set_event(io, filter, &block)
    @kq.kevent([Kqueue::Event.new(io.fileno, filter, EV_ADD, 0, 0, [io, block])], 0)
  end

  def del_event(io, filter)
    @kq.kevent([Kqueue::Event.new(io.fileno, filter, EV_DELETE, 0, 0, nil)], 0)
  end

  def wait
    @kq.kevent(nil, 128, 5)
  end

  def on_data(&block)
    @on_data = block
  end

  def on_end(&block)
    @on_end = block
  end
end

puts "run http://127.0.0.1:4000/"

KqServer.start(4000) do |s|
  s.on_data do |chunk|
    print chunk
  end
  s.on_end do |socket|
    socket.write [
      "HTTP/1.0 200 OK\r\n",
      "Content-Length: 11\r\n",
      "Content-Type: text/html\r\n",
      "\r\n",
      "Hello World\r\n",
    ].join("")
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
kqueue-0.0.1 examples/kqueue_server.rb