proxymachine 0.2.3 → 0.2.6
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.md +25 -11
- data/VERSION.yml +1 -1
- data/bin/proxymachine +2 -1
- data/examples/long.rb +9 -0
- data/lib/proxymachine/client_connection.rb +3 -1
- data/lib/proxymachine.rb +51 -7
- data/proxymachine.gemspec +4 -2
- metadata +4 -2
data/README.md
CHANGED
@@ -20,20 +20,21 @@ contents of the transmission, then ProxyMachine will make your life easy!
|
|
20
20
|
The idea here is simple. For each client connection, start receiving data
|
21
21
|
chunks and placing them into a buffer. Each time a new chunk arrives, send the
|
22
22
|
buffer to a user specified block. The block's job is to parse the buffer to
|
23
|
-
determine where the connection should proxied. If the buffer contains
|
24
|
-
data to make a determination, the block returns the address and port of
|
25
|
-
correct backend server. If not, it can choose to
|
26
|
-
|
27
|
-
|
28
|
-
backend,
|
29
|
-
|
30
|
-
|
23
|
+
determine where the connection should be proxied. If the buffer contains
|
24
|
+
enough data to make a determination, the block returns the address and port of
|
25
|
+
the correct backend server. If not, it can choose to do nothing and wait for
|
26
|
+
more data to arrive, close the connection, or close the connection after
|
27
|
+
sending custom data. Once the block returns an address, a connection to the
|
28
|
+
backend is made, the buffer is replayed to the backend, and the client and
|
29
|
+
backend connections are hooked up to form a transparent proxy. This
|
30
|
+
bidirectional proxy continues to exist until either the client or backend
|
31
|
+
close the connection.
|
31
32
|
|
32
33
|
|
33
34
|
Installation
|
34
35
|
------------
|
35
36
|
|
36
|
-
gem install
|
37
|
+
$ gem install proxymachine -s http://gemcutter.org
|
37
38
|
|
38
39
|
|
39
40
|
Running
|
@@ -48,6 +49,19 @@ Running
|
|
48
49
|
-p, --port PORT Port to listen on. Default 5432
|
49
50
|
|
50
51
|
|
52
|
+
Signals
|
53
|
+
-------
|
54
|
+
|
55
|
+
QUIT - Graceful shutdown. Stop accepting connections immediately and
|
56
|
+
wait as long as necessary for all connections to close.
|
57
|
+
|
58
|
+
TERM - Fast shutdown. Stop accepting connections immediately and wait
|
59
|
+
up to 10 seconds for connections to close before forcing
|
60
|
+
termination.
|
61
|
+
|
62
|
+
INT - Same as TERM
|
63
|
+
|
64
|
+
|
51
65
|
Example routing config file
|
52
66
|
---------------------------
|
53
67
|
|
@@ -63,7 +77,7 @@ Example routing config file
|
|
63
77
|
# header information from the Git protocol is parsed to find the
|
64
78
|
# username and a lookup routine is run on the name to find the correct
|
65
79
|
# backend server. If no match can be made yet, do nothing with the
|
66
|
-
# connection
|
80
|
+
# connection.
|
67
81
|
proxy do |data|
|
68
82
|
if data =~ %r{^....git-upload-pack /([\w\.\-]+)/[\w\.\-]+\000host=\w+\000}
|
69
83
|
name = $1
|
@@ -80,7 +94,7 @@ Valid return values
|
|
80
94
|
`{ :remote => String }` - String is the host:port of the backend server that will be proxied.
|
81
95
|
`{ :remote => String, :data => String }` - Same as above, but send the given data instead.
|
82
96
|
`{ :noop => true }` - Do nothing.
|
83
|
-
`{ :close
|
97
|
+
`{ :close => true }` - Close the connection.
|
84
98
|
`{ :close => String }` - Close the connection after sending the String.
|
85
99
|
|
86
100
|
|
data/VERSION.yml
CHANGED
data/bin/proxymachine
CHANGED
@@ -32,7 +32,8 @@ EOF
|
|
32
32
|
opts.parse!
|
33
33
|
|
34
34
|
load(options[:config])
|
35
|
-
|
35
|
+
name = options[:config].split('/').last.chomp('.rb')
|
36
|
+
ProxyMachine.run(name, options[:host], options[:port])
|
36
37
|
rescue Exception => e
|
37
38
|
if e.instance_of?(SystemExit)
|
38
39
|
raise
|
data/examples/long.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# To try out the graceful exit via SIGQUIT, start up a proxymachine with this
|
2
|
+
# configuration, and run the following curl command a few times:
|
3
|
+
# curl http://localhost:5432/ubuntu-releases/9.10/ubuntu-9.10-beta-alternate-amd64.iso \
|
4
|
+
# -H "Host: mirrors.cat.pdx.edu" > /dev/null
|
5
|
+
# Then send a SIGQUIT to the process and stop the long downloads one by one.
|
6
|
+
|
7
|
+
proxy do |data|
|
8
|
+
{ :remote => "mirrors.cat.pdx.edu:80" }
|
9
|
+
end
|
@@ -2,8 +2,10 @@ module EventMachine
|
|
2
2
|
module Protocols
|
3
3
|
class ClientConnection < Connection
|
4
4
|
def self.start(host, port)
|
5
|
-
EM.start_server(host, port, self)
|
5
|
+
$server = EM.start_server(host, port, self)
|
6
6
|
puts "Listening on #{host}:#{port}"
|
7
|
+
puts "Send QUIT to quit after waiting for all connections to finish."
|
8
|
+
puts "Send TERM or INT to quit after waiting for up to 10 seconds for connections to finish."
|
7
9
|
end
|
8
10
|
|
9
11
|
def post_init
|
data/lib/proxymachine.rb
CHANGED
@@ -5,20 +5,30 @@ require 'proxymachine/client_connection'
|
|
5
5
|
require 'proxymachine/server_connection'
|
6
6
|
|
7
7
|
class ProxyMachine
|
8
|
-
|
9
|
-
|
8
|
+
MAX_FAST_SHUTDOWN_SECONDS = 10
|
9
|
+
|
10
|
+
def self.update_procline
|
11
|
+
$0 = "proxymachine - #{@@name} #{@@listen} - #{self.count} connections"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.count
|
15
|
+
@@counter
|
10
16
|
end
|
11
17
|
|
12
18
|
def self.incr
|
13
|
-
@@counter ||= 0
|
14
19
|
@@counter += 1
|
15
|
-
|
20
|
+
self.update_procline
|
21
|
+
@@counter
|
16
22
|
end
|
17
23
|
|
18
24
|
def self.decr
|
19
|
-
@@counter ||= 0
|
20
25
|
@@counter -= 1
|
21
|
-
|
26
|
+
if $server.nil?
|
27
|
+
puts "Waiting for #{@@counter} connections to finish."
|
28
|
+
end
|
29
|
+
self.update_procline
|
30
|
+
EM.stop if $server.nil? and @@counter == 0
|
31
|
+
@@counter
|
22
32
|
end
|
23
33
|
|
24
34
|
def self.set_router(block)
|
@@ -29,11 +39,45 @@ class ProxyMachine
|
|
29
39
|
@@router
|
30
40
|
end
|
31
41
|
|
32
|
-
def self.
|
42
|
+
def self.graceful_shutdown(signal)
|
43
|
+
EM.stop_server($server) if $server
|
44
|
+
puts "Received #{signal} signal. No longer accepting new connections."
|
45
|
+
puts "Waiting for #{ProxyMachine.count} connections to finish."
|
46
|
+
$server = nil
|
47
|
+
EM.stop if ProxyMachine.count == 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.fast_shutdown(signal)
|
51
|
+
EM.stop_server($server) if $server
|
52
|
+
puts "Received #{signal} signal. No longer accepting new connections."
|
53
|
+
puts "Maximum time to wait for connections is #{MAX_FAST_SHUTDOWN_SECONDS} seconds."
|
54
|
+
puts "Waiting for #{ProxyMachine.count} connections to finish."
|
55
|
+
$server = nil
|
56
|
+
EM.stop if ProxyMachine.count == 0
|
57
|
+
Thread.new do
|
58
|
+
sleep MAX_FAST_SHUTDOWN_SECONDS
|
59
|
+
exit!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.run(name, host, port)
|
64
|
+
@@counter = 0
|
65
|
+
@@name = name
|
66
|
+
@@listen = "#{host}:#{port}"
|
67
|
+
self.update_procline
|
33
68
|
EM.epoll
|
34
69
|
|
35
70
|
EM.run do
|
36
71
|
EventMachine::Protocols::ClientConnection.start(host, port)
|
72
|
+
trap('QUIT') do
|
73
|
+
self.graceful_shutdown('QUIT')
|
74
|
+
end
|
75
|
+
trap('TERM') do
|
76
|
+
self.fast_shutdown('TERM')
|
77
|
+
end
|
78
|
+
trap('INT') do
|
79
|
+
self.fast_shutdown('INT')
|
80
|
+
end
|
37
81
|
end
|
38
82
|
end
|
39
83
|
end
|
data/proxymachine.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{proxymachine}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.6"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Tom Preston-Werner"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-10-01}
|
10
10
|
s.default_executable = %q{proxymachine}
|
11
11
|
s.email = %q{tom@mojombo.com}
|
12
12
|
s.executables = ["proxymachine"]
|
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
"VERSION.yml",
|
24
24
|
"bin/proxymachine",
|
25
25
|
"examples/git.rb",
|
26
|
+
"examples/long.rb",
|
26
27
|
"examples/transparent.rb",
|
27
28
|
"lib/proxymachine.rb",
|
28
29
|
"lib/proxymachine/client_connection.rb",
|
@@ -40,6 +41,7 @@ Gem::Specification.new do |s|
|
|
40
41
|
"test/proxymachine_test.rb",
|
41
42
|
"test/test_helper.rb",
|
42
43
|
"examples/git.rb",
|
44
|
+
"examples/long.rb",
|
43
45
|
"examples/transparent.rb"
|
44
46
|
]
|
45
47
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proxymachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Preston-Werner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-01 00:00:00 -07:00
|
13
13
|
default_executable: proxymachine
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- VERSION.yml
|
41
41
|
- bin/proxymachine
|
42
42
|
- examples/git.rb
|
43
|
+
- examples/long.rb
|
43
44
|
- examples/transparent.rb
|
44
45
|
- lib/proxymachine.rb
|
45
46
|
- lib/proxymachine/client_connection.rb
|
@@ -79,4 +80,5 @@ test_files:
|
|
79
80
|
- test/proxymachine_test.rb
|
80
81
|
- test/test_helper.rb
|
81
82
|
- examples/git.rb
|
83
|
+
- examples/long.rb
|
82
84
|
- examples/transparent.rb
|