redcap 0.1.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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENCE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Pat Allan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.require :default, :development
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ require 'rspec/core/rake_task'
9
+ RSpec::Core::RakeTask.new
data/bin/redcap ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'redcap'
3
+
4
+ Redcap::App.daemonise!
5
+ Redcap::App.run
data/lib/redcap/app.rb ADDED
@@ -0,0 +1,95 @@
1
+ class Redcap::App
2
+ include Singleton
3
+
4
+ attr_reader :server
5
+
6
+ def self.run
7
+ instance.run
8
+ end
9
+
10
+ def self.daemonise!
11
+ # Daemon won't need these
12
+ $stdin.reopen '/dev/null'
13
+ $stdout.reopen '/dev/null', 'w'
14
+ $stderr.reopen '/dev/null', 'w'
15
+
16
+ # Send to the background
17
+ pid = fork
18
+ if pid
19
+ # This is in the context of the parent - save the pid file, then exit.
20
+ File.open(instance.pid_file, 'w') { |file| file.puts pid }
21
+ exit!
22
+ end
23
+ end
24
+
25
+ def run
26
+ update_procline
27
+
28
+ EventMachine.epoll
29
+ EventMachine.run do
30
+ @server = EventMachine.start_server('127.0.0.1', 11000, Redcap::Server) do |connection|
31
+ connection.logger = logger
32
+ end
33
+
34
+ setup_signal_handlers
35
+ end
36
+ end
37
+
38
+ def stop!(signal)
39
+ logger.info "Received #{signal} signal, stopping server."
40
+ stop_listening
41
+ forget_server
42
+ stop
43
+ end
44
+
45
+ def die(message)
46
+ $stderr.puts message
47
+ logger.fatal message
48
+
49
+ exit 1
50
+ end
51
+
52
+ private
53
+
54
+ def update_procline
55
+ $0 = 'redcap'
56
+ end
57
+
58
+ def log_file
59
+ @log_file ||= '/var/log/redcap.log'
60
+ end
61
+
62
+ def pid_file
63
+ @log_file ||= '/var/tmp/redcap.pid'
64
+ end
65
+
66
+ def logger
67
+ @logger ||= begin
68
+ logger = Logger.new(log_file)
69
+ logger.formatter = Logger::Formatter.new
70
+ logger.datetime_format = '%Y-%m-%d %H:%M:%S'
71
+ logger.progname = 'redcap'
72
+ logger.level = Logger::INFO
73
+
74
+ logger
75
+ end
76
+ end
77
+
78
+ def setup_signal_handlers
79
+ %w{ QUIT TERM INT }.each do |signal|
80
+ trap(signal) { stop!(signal) and exit! }
81
+ end
82
+ end
83
+
84
+ def stop_listening
85
+ EventMachine.stop_server(server) unless server.nil?
86
+ end
87
+
88
+ def forget_server
89
+ @server = nil
90
+ end
91
+
92
+ def stop
93
+ EventMachine.stop
94
+ end
95
+ end
@@ -0,0 +1,19 @@
1
+ class Redcap::Server < EventMachine::Protocols::LineAndTextProtocol
2
+ attr_accessor :logger
3
+
4
+ def receive_line(line)
5
+ port = line.to_i
6
+ pid = pid_for_port(port)
7
+
8
+ logger.info "port: #{port} -> pid: #{pid}"
9
+
10
+ send_data pid
11
+ close_connection_after_writing
12
+ end
13
+
14
+ private
15
+
16
+ def pid_for_port(port)
17
+ `lsof -i :#{port} | grep ssh | awk '{print $2}'`[/\d+/] || 'Unknown'
18
+ end
19
+ end
@@ -0,0 +1 @@
1
+ Redcap::Version = '0.1.0'
data/lib/redcap.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'socket'
2
+ require 'singleton'
3
+ require 'logger'
4
+ require 'eventmachine'
5
+
6
+ module Redcap
7
+ def self.pid_for_port(port, options = {})
8
+ options[:server] ||= '127.0.0.1'
9
+ options[:port] ||= 11000
10
+
11
+ socket = TCPSocket.new options[:server], options[:port]
12
+ socket.write "#{port}\n"
13
+ pid = socket.read.to_i
14
+ socket.close
15
+
16
+ pid
17
+ end
18
+ end
19
+
20
+ require 'redcap/app'
21
+ require 'redcap/server'
22
+ require 'redcap/version'
data/redcap.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'redcap'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'redcap'
7
+ s.version = Redcap::Version
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Pat Allan']
10
+ s.email = ['pat@freelancing-gods.com']
11
+ s.homepage = 'http://github.com/flying-sphinx/redcap'
12
+ s.summary = %q{Translates SSH forward ports to process IDs}
13
+ s.description = %q{A service that translates SSH forward ports to process IDs. Built for Flying Sphinx.}
14
+
15
+ s.rubyforge_project = 'redcap'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f|
20
+ File.basename(f)
21
+ }
22
+ s.require_paths = ['lib']
23
+
24
+ s.add_runtime_dependency 'eventmachine', ['>= 0.12.10']
25
+ s.add_development_dependency 'rspec', ['2.5.0']
26
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redcap::Server do
4
+ describe '#receive_line' do
5
+ let(:server) { Redcap::Server.new :spec }
6
+ let(:logger) { stub('logger', :info => nil) }
7
+
8
+ before :each do
9
+ server.logger = logger
10
+ server.stub!(
11
+ :` => '24',
12
+ :close_connection_after_writing => nil,
13
+ :send_data => nil
14
+ )
15
+ end
16
+
17
+ it "sends the process id for a given port" do
18
+ server.should_receive(:send_data).with('24')
19
+
20
+ server.receive_line('101')
21
+ end
22
+
23
+ it "closes the connection once writing is finished" do
24
+ server.should_receive(:close_connection_after_writing)
25
+
26
+ server.receive_line('101')
27
+ end
28
+
29
+ it "logs the request" do
30
+ logger.should_receive(:info).with('port: 101 -> pid: 24')
31
+
32
+ server.receive_line('101')
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redcap do
4
+ describe '.pid_for_port' do
5
+ let(:socket) { stub('socket', :write => nil, :read => '42', :close => nil) }
6
+
7
+ before :each do
8
+ TCPSocket.stub! :new => socket
9
+ end
10
+
11
+ it "sends the given port to the socket" do
12
+ socket.should_receive(:write).with("101\n")
13
+
14
+ Redcap.pid_for_port(101)
15
+ end
16
+
17
+ it "returns the socket output as an integer" do
18
+ Redcap.pid_for_port(101).should == 42
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ $:.unshift File.dirname(__FILE__) + '/../lib'
5
+ $:.unshift File.dirname(__FILE__) + '/..'
6
+
7
+ Bundler.require :default, :development
8
+
9
+ require 'redcap'
10
+
11
+ RSpec.configure do |config|
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redcap
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Pat Allan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-09 00:00:00 +10:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: eventmachine
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.12.10
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - "="
33
+ - !ruby/object:Gem::Version
34
+ version: 2.5.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ description: A service that translates SSH forward ports to process IDs. Built for Flying Sphinx.
39
+ email:
40
+ - pat@freelancing-gods.com
41
+ executables:
42
+ - redcap
43
+ extensions: []
44
+
45
+ extra_rdoc_files: []
46
+
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENCE
51
+ - README.textile
52
+ - Rakefile
53
+ - bin/redcap
54
+ - lib/redcap.rb
55
+ - lib/redcap/app.rb
56
+ - lib/redcap/server.rb
57
+ - lib/redcap/version.rb
58
+ - redcap.gemspec
59
+ - spec/redcap/server_spec.rb
60
+ - spec/redcap_spec.rb
61
+ - spec/spec_helper.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/flying-sphinx/redcap
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 2640545869079275918
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 2640545869079275918
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ requirements: []
90
+
91
+ rubyforge_project: redcap
92
+ rubygems_version: 1.6.2
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Translates SSH forward ports to process IDs
96
+ test_files:
97
+ - spec/redcap/server_spec.rb
98
+ - spec/redcap_spec.rb
99
+ - spec/spec_helper.rb