summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2012-12-24 16:25:39 -0800
committerelijah <elijah@riseup.net>2012-12-24 16:25:39 -0800
commit8a70059fed66daa00dd9f8558748255735c91846 (patch)
tree47d22bb1719d389f4c1cc9b3a91d7cdb94fdee84
parent8b5cd59867b00829dfe9d38531d44f1fdf4edbdc (diff)
added nickserver daemon
-rw-r--r--README.md25
-rwxr-xr-xbin/nickserver58
-rw-r--r--lib/nickserver/server.rb43
-rw-r--r--nickserver.gemspec1
-rw-r--r--test/unit/server_test.rb11
5 files changed, 111 insertions, 27 deletions
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/<uid>
-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 <command> <options> -- <application options>
- rake test \ No newline at end of file
+ * where <command> 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 <options> 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/<uid> --> 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
-