throttle 0.0.1
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 +4 -0
- data/Gemfile +4 -0
- data/README.md +50 -0
- data/Rakefile +1 -0
- data/bin/throttle +47 -0
- data/lib/throttle/bandwidth.rb +27 -0
- data/lib/throttle/client.rb +34 -0
- data/lib/throttle/ipfw.rb +15 -0
- data/lib/throttle/pipe.rb +93 -0
- data/lib/throttle/version.rb +3 -0
- data/lib/throttle.rb +11 -0
- data/throttle.gemspec +24 -0
- metadata +58 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Throttle
|
2
|
+
Uses ipfw on Mac OSX to simulate slower connection speed.
|
3
|
+
|
4
|
+
## Purpose
|
5
|
+
Many times I've found myself needing to test applications on slower connections. However, that is never an easy task. Throttle allows you to simulate a slower connection by allowing you to specify an exact bandwidth you would like to experience.
|
6
|
+
|
7
|
+
## Development
|
8
|
+
At the moment the code is REAAAAAAL ugly and needs much improvement. There are also a lot more features I would like to add. Mostly being able to specify source and destination ip:port so you can filter which traffic will be throttled. Also the ability to have multiple filters going at once. Right now you can only have one.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
### Prerequisites
|
13
|
+
|
14
|
+
* Mac OSX 10.5, 10.6, 10.7
|
15
|
+
* ruby 1.8.7
|
16
|
+
* rubygems
|
17
|
+
|
18
|
+
### Installation
|
19
|
+
|
20
|
+
```
|
21
|
+
gem install throttle
|
22
|
+
```
|
23
|
+
|
24
|
+
### Getting Started
|
25
|
+
From the command line:
|
26
|
+
|
27
|
+
#### Start throttling
|
28
|
+
|
29
|
+
Limit traffic to 100 Kilobits per second
|
30
|
+
```
|
31
|
+
throttle limit 100Kbit/s
|
32
|
+
```
|
33
|
+
|
34
|
+
#### Current Status
|
35
|
+
|
36
|
+
List all current limits in place.
|
37
|
+
|
38
|
+
```
|
39
|
+
throttle status
|
40
|
+
```
|
41
|
+
|
42
|
+
|
43
|
+
#### Bandwidth
|
44
|
+
|
45
|
+
Bandwidth must be specified in [Kilo/Mega][bits/Bytes]/s.
|
46
|
+
|
47
|
+
* 500Kbps - 500 Kilobytes per second
|
48
|
+
* 1MBps - 1 Megabyte per second
|
49
|
+
|
50
|
+
IPFW doesn't allow bandwidth greater than 268 MBps.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/throttle
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'throttle'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require 'throttle'
|
8
|
+
end
|
9
|
+
|
10
|
+
#throttle limit 500Kbps
|
11
|
+
#throttle limit 600Kbps
|
12
|
+
#throttle status
|
13
|
+
#throttle reset
|
14
|
+
|
15
|
+
def error(str)
|
16
|
+
puts "Error: #{str}"
|
17
|
+
end
|
18
|
+
|
19
|
+
throttle = Throttle.new
|
20
|
+
|
21
|
+
case ARGV[0]
|
22
|
+
when "limit"
|
23
|
+
if ARGV[1]
|
24
|
+
throttle.limit(ARGV[1])
|
25
|
+
puts "Currently throttled at : #{throttle.status}"
|
26
|
+
else
|
27
|
+
error("Please provide a valid bit rate to limit.")
|
28
|
+
end
|
29
|
+
when "status"
|
30
|
+
puts throttle.status
|
31
|
+
when "reset"
|
32
|
+
throttle.reset
|
33
|
+
puts throttle.status
|
34
|
+
else
|
35
|
+
puts "Throttle Help!"
|
36
|
+
|
37
|
+
puts "\nThrottling: "
|
38
|
+
puts "throttle limit [bandwidth]"
|
39
|
+
puts "throttle limit 500KBps"
|
40
|
+
puts "throttle limit 12Mbps"
|
41
|
+
|
42
|
+
puts "\nGet the current status:"
|
43
|
+
puts "throttle status"
|
44
|
+
|
45
|
+
puts "\nTurn off:"
|
46
|
+
puts "throttle reset"
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Throttle
|
2
|
+
module Bandwidth
|
3
|
+
def parse_bandwidth(str)
|
4
|
+
amount = nil
|
5
|
+
units = "KBp/s"
|
6
|
+
|
7
|
+
if /(\d*)/.match(str)
|
8
|
+
amount = Regexp.last_match(0).to_i
|
9
|
+
|
10
|
+
if /((K|M|k|m)(b|B)(p|P))/.match(str)
|
11
|
+
units = Regexp.last_match(0)
|
12
|
+
units.gsub!('P', 'p')
|
13
|
+
units.gsub!('/s', '')
|
14
|
+
units += '/s'
|
15
|
+
end
|
16
|
+
|
17
|
+
# Maximum allowed MBps
|
18
|
+
amount = 268 if units == "MBp/s" && amount > 268
|
19
|
+
|
20
|
+
"#{amount}#{units}"
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Throttle
|
2
|
+
class Client
|
3
|
+
include Bandwidth
|
4
|
+
|
5
|
+
def status
|
6
|
+
pipes = Pipe.all
|
7
|
+
status = ""
|
8
|
+
pipes.each do |p|
|
9
|
+
status += "#{p.bandwidth}"
|
10
|
+
end
|
11
|
+
|
12
|
+
status = "No Limits." if status.empty?
|
13
|
+
return status
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
Pipe.reset
|
18
|
+
status
|
19
|
+
end
|
20
|
+
|
21
|
+
def limit(bandwidth)
|
22
|
+
Pipe.reset
|
23
|
+
|
24
|
+
options = {
|
25
|
+
:id => 1,
|
26
|
+
:bandwidth => parse_bandwidth(bandwidth)
|
27
|
+
}
|
28
|
+
|
29
|
+
Pipe.new(options).set
|
30
|
+
status
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Throttle
|
2
|
+
class Pipe
|
3
|
+
attr_accessor :id, :bandwidth, :rule_id
|
4
|
+
|
5
|
+
def self.all
|
6
|
+
pipes = []
|
7
|
+
pipe_lines = []
|
8
|
+
|
9
|
+
ipfw('list').split("\n").each do |line|
|
10
|
+
if /^\d{5} pipe.*$/.match(line)
|
11
|
+
pipe_lines << Regexp.last_match(0)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
pipe_lines.each do |line|
|
16
|
+
id = parse_pipe_id(line)
|
17
|
+
bandwidth = Pipe.bandwidth(id)
|
18
|
+
|
19
|
+
pipes << Pipe.new({
|
20
|
+
:id => id,
|
21
|
+
:bandwidth => bandwidth
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
return pipes
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.bandwidth(id)
|
29
|
+
output = ipfw("pipe #{id} show")
|
30
|
+
|
31
|
+
if /^\d{5}:\W*(\d*\.\d* \S*).*$/.match(output)
|
32
|
+
Regexp.last_match(1)
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.reset
|
39
|
+
Pipe.all.each do |pipe|
|
40
|
+
pipe.delete
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(options = {})
|
45
|
+
@id = options[:id]
|
46
|
+
@bandwidth = options[:bandwidth]
|
47
|
+
end
|
48
|
+
|
49
|
+
def set
|
50
|
+
unless rule_id
|
51
|
+
ipfw("add pipe #{self.id} ip from any to any")
|
52
|
+
end
|
53
|
+
|
54
|
+
ipfw("pipe #{id} config bw #{self.bandwidth}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def bandwidth
|
58
|
+
@bandwidth || "Inactive"
|
59
|
+
end
|
60
|
+
|
61
|
+
def rule_id
|
62
|
+
@rule_id ||= set_rule_id
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_rule_id
|
66
|
+
regex = "^(\d{5}) pipe #{self.id}.*$"
|
67
|
+
|
68
|
+
if /^(\d{5}) pipe #{self.id}.*$/.match(ipfw("list"))
|
69
|
+
Regexp.last_match(1)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def delete
|
74
|
+
delete_rule
|
75
|
+
|
76
|
+
unless @bandwidth.nil?
|
77
|
+
ipfw("pipe #{@id} delete")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete_rule
|
82
|
+
if rule_id && rule_id != 0
|
83
|
+
ipfw("delete #{rule_id}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
include Ipfw
|
90
|
+
extend Ipfw
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
data/lib/throttle.rb
ADDED
data/throttle.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "throttle/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "throttle"
|
7
|
+
s.version = Throttle::VERSION
|
8
|
+
s.authors = ["brookemckim"]
|
9
|
+
s.email = ["brooke.mckim@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/brookemckim/throttle"
|
11
|
+
s.summary = %q{Throttle bandwidth on OS X}
|
12
|
+
s.description = %q{Throttle your local bandwidth with IPFW on OSX}
|
13
|
+
|
14
|
+
s.rubyforge_project = "throttle"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: throttle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- brookemckim
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-09 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Throttle your local bandwidth with IPFW on OSX
|
15
|
+
email:
|
16
|
+
- brooke.mckim@gmail.com
|
17
|
+
executables:
|
18
|
+
- throttle
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- bin/throttle
|
27
|
+
- lib/throttle.rb
|
28
|
+
- lib/throttle/bandwidth.rb
|
29
|
+
- lib/throttle/client.rb
|
30
|
+
- lib/throttle/ipfw.rb
|
31
|
+
- lib/throttle/pipe.rb
|
32
|
+
- lib/throttle/version.rb
|
33
|
+
- throttle.gemspec
|
34
|
+
homepage: https://github.com/brookemckim/throttle
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project: throttle
|
54
|
+
rubygems_version: 1.8.10
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Throttle bandwidth on OS X
|
58
|
+
test_files: []
|