From 8a70059fed66daa00dd9f8558748255735c91846 Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 24 Dec 2012 16:25:39 -0800 Subject: added nickserver daemon --- README.md | 25 +++++++++++++++++---- bin/nickserver | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/nickserver/server.rb | 43 +++++++++++++++++++---------------- nickserver.gemspec | 1 + test/unit/server_test.rb | 11 +++++---- 5 files changed, 111 insertions(+), 27 deletions(-) create mode 100755 bin/nickserver diff --git a/README.md b/README.md index 344c3cc..fd1bd89 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ public key information for that nick. Nickserver has the following properties: * Written in Ruby, licensed GPLv3 -* Lightweight and scalable +* Lightweight and scalable (high concurrency, reasonable latency) * Uses asynchronous network IO for both server and client connections (via EventMachine) * Attempts to reply to queries using four different methods: * Cached key in CouchDB (coming soon) @@ -45,7 +45,7 @@ You query the nickserver via HTTP. The API is very minimal at the moment: curl -X GET hostname:6425/key/ -Returns the OpenPGP public key for uid. +Returns the OpenPGP public key for uid (ascii encoded). Installation ================================== @@ -72,6 +72,23 @@ Install for development: Usage ================================== -None yet, just a bunch of unit tests. + Usage: nickserver -- - rake test \ No newline at end of file + * where is one of: + start start an instance of the application + stop stop all instances of the application + restart stop all instances and restart them afterwards + reload send a SIGHUP to all instances of the application + run start the application and stay on top + zap set the application to a stopped state + status show status (PID) of application instances + + * and where may contain several of the following: + + -t, --ontop Stay on top (does not daemonize) + -f, --force Force operation + -n, --no_wait Do not wait for processes to stop + + Common options: + -h, --help Show this message + --version Show version diff --git a/bin/nickserver b/bin/nickserver new file mode 100755 index 0000000..b0cabac --- /dev/null +++ b/bin/nickserver @@ -0,0 +1,58 @@ +#!/usr/bin/ruby +# +# Nickserver key discovery daemon +# + +# +# bootstrap nickserver library +# +begin # try without rubygems (might be already loaded or not present) + require 'nickserver' +rescue LoadError + begin # try with rubygems + require 'rubygems' + require 'nickserver' + rescue LoadError # try manually + BASE_DIR = File.expand_path('../..', File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__) + $LOAD_PATH << "#{BASE_DIR}/lib" + require "nickserver" + end +end + +# +# Handle craceful Ctrl-C +# +Signal.trap("SIGINT") do + puts "\nQuit" + exit +end + +# +# Handle '--version' ourselves +# +if ARGV.grep(/--version/).any? + puts "nickserver #{Nickserver::VERSION}, ruby #{RUBY_VERSION}" + exit(0) +end + +# +# Start the daemon +# +require 'daemons' + +options = {:app_name => 'nickserver', :multiple => false, :backtrace => true} + +# pick where the pid file should go (must be readable/writable by current user) +if File.writable?('/var/run/nickserver') + options.merge!(:dir_mode => :normal, :dir => '/var/run/nickserver') +elsif ENV["USER"] == "root" + options.merge!(:dir_mode => :system) +else + options.merge!(:dir_mode => :normal, :dir => '/tmp') +end + +Daemons.run_proc('nickserver', options) do + EventMachine.run do + Nickserver::Server.start + end +end diff --git a/lib/nickserver/server.rb b/lib/nickserver/server.rb index 4201cef..21975d4 100644 --- a/lib/nickserver/server.rb +++ b/lib/nickserver/server.rb @@ -1,31 +1,36 @@ require 'eventmachine' require 'evma_httpserver' - # # This is the main HTTP server that clients connect to in order to fetch keys # +# For now, its API is very simple: +# +# GET /keys/ --> returns OpenPGP key for uid. +# module Nickserver class Server < EM::Connection include EM::HttpServer + # + # Starts the Nickserver. Must be run inside an EM.run block. + # + # Available options: + # + # * :port (default Nickserver::Config.port) + # * :host (default 0.0.0.0) + # + def self.start(opts={}) + options = {:host => '0.0.0.0', :port => Nickserver::Config.port}.merge(opts) + EM.start_server options[:host], options[:port], Nickserver::Server + end + def post_init super no_environment_strings end def process_http_request - # the http request details are available via the following instance variables: - # @http_protocol - # @http_request_method - # @http_cookie - # @http_if_none_match - # @http_content_type - # @http_path_info - # @http_request_uri - # @http_query_string - # @http_post_content - # @http_headers if @http_request_method == "GET" if @http_path_info =~ /^\/key\// send_key @@ -43,13 +48,6 @@ module Nickserver send_response(:status => 500, :content => msg) end - def send_key - uid = CGI.unescape @http_path_info.sub(/^\/key\/(.*)/, '\1') - get_key_from_uid(uid) do |key| - send_response(:content => key) - end - end - def send_response(opts = {}) options = {:status => 200, :content_type => 'text/plain', :content => ''}.merge(opts) response = EM::DelegatedHttpResponse.new(self) @@ -59,6 +57,13 @@ module Nickserver response.send_response end + def send_key + uid = CGI.unescape @http_path_info.sub(/^\/key\/(.*)/, '\1') + get_key_from_uid(uid) do |key| + send_response(:content => key) + end + end + def get_key_from_uid(uid) Nickserver::HKP::FetchKey.new.get(uid).callback {|key| yield key diff --git a/nickserver.gemspec b/nickserver.gemspec index 5d0d807..2c87585 100644 --- a/nickserver.gemspec +++ b/nickserver.gemspec @@ -24,4 +24,5 @@ Gem::Specification.new do |gem| gem.add_dependency 'eventmachine' gem.add_dependency 'em-http-request' gem.add_dependency 'eventmachine_httpserver' + gem.add_dependency 'daemons' end diff --git a/test/unit/server_test.rb b/test/unit/server_test.rb index e4c2dc6..5a6bd8d 100644 --- a/test/unit/server_test.rb +++ b/test/unit/server_test.rb @@ -2,6 +2,9 @@ require File.expand_path('test_helper', File.dirname(__FILE__)) class ServerTest < MiniTest::Unit::TestCase + # + # this test works because http requests to localhost are not stubbed, but requests to other domains are. + # def test_server uid = 'cloudadmin@leap.se' key_id = 'E818C478D3141282F7590D29D041EB11B1647490' @@ -9,19 +12,19 @@ class ServerTest < MiniTest::Unit::TestCase stub_get_response(key_id, :body => file_content(:leap_public_key)) EM.run do - EM.start_server '0.0.0.0', Nickserver::Config.port, Nickserver::Server - + Nickserver::Server.start params = {:query => {}, :path => "key/#{CGI.escape(uid)}"} http = EventMachine::HttpRequest.new("http://localhost:#{Nickserver::Config.port}").get(params) http.callback { assert_equal file_content(:leap_public_key), http.response EM.stop + return }.errback { - puts http.error + flunk http.error EM.stop } end + flunk 'should not get here' end end - -- cgit v1.2.3