tochka 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40dc9ab742d3ff31b82292795a7b905782210488
4
+ data.tar.gz: 771f090404e1262e0f0e174ac961e60f0cf099f9
5
+ SHA512:
6
+ metadata.gz: 4b6b2639eecb4a961fa4de138a456b71d0f03167e67549a37ed8e4a3a3697b85288295923ac1f24207e56e50d11005d1f566f654a98f04f41f4bd47f16d970ad
7
+ data.tar.gz: a7a73e80b4536856fdb045d4ab911f598a1f5acf28db7ea5a5676053970bb5d171ceecd401b88ae2909313fc8c6d3b54eebd72ea8855a0babe9d46b2b8df7dd4
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tochka.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Tochka
2
+
3
+ "Tochka" is softwares to build Wi-Fi frame capturing box with Raspberry Pi + PiTFT.
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/tochka`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ TODO: Delete this and the text above, and describe your gem
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'tochka'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install tochka
24
+
25
+ ### install init.d scripts
26
+
27
+ 1. copy ext/tochkad, ext/tochka-miniui into /etc/init.d
28
+ 2. do chmod +x onto both
29
+ 3. do 'update-rc.d <name> defaults' to both
30
+
31
+ ## Usage
32
+
33
+ ### PiTFT UI
34
+
35
+ Tochka provides with user interface to start/stop capture on top of PiTFT.
36
+
37
+ ![tochka-miniui](http://amber.glenda9.org/~enukane/images/tochka-miniui.jpg)
38
+
39
+ TOUCHSCREEN is currently of NO USE. Just make yourself happy with moving cursor :).
40
+ Use buttons instead: 4 buttons are "START", "STOP", "MODE1", "MODE2".
41
+
42
+ ### Starting capture
43
+
44
+ Press "START" button and "State" turns into "running"
45
+
46
+ ### Stop capture
47
+
48
+ Press "STOP", "MODE1" and "MODE2" buttons in an order. Check that "stop count" is now 3.
49
+ Then press "STOP" button again will turn off capturing. The "State" will turn into "stop".
50
+
51
+ ### collecting captured data
52
+
53
+ Captured data (pcapng files) are stored in /cap directory
54
+
55
+ ## Development
56
+
57
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec tochka` to use the gem in this directory, ignoring other installed copies of this gem.
58
+
59
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/enukane/tochka.
64
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tochka"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/exe/tochka-miniui ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tochka"
4
+ require "optparse"
5
+
6
+ opt = OptionParser.new
7
+ OPTS=Tochka::TochkaMiniUI.default_options
8
+
9
+ opt.on('-f', "--font [FONT_PATH]", "font to use (default: #{Tochka::TochkaMiniUI.default_options[:font_path]})") {|v|
10
+ OPTS[:font_path] = v
11
+ }
12
+
13
+ opt.on('-l', "--log-file [LOG_FILE=STDOUT]",
14
+ "log output file (accepts 'STDOUT', 'STDERR')") {|v|
15
+ OPTS[:log_file] = v
16
+ }
17
+
18
+ (class<<self;self;end).module_eval do
19
+ define_method(:usage) do |msg|
20
+ puts opt.to_s
21
+ puts "error: #{msg}" if msg
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ begin
27
+ res = opt.parse(ARGV)
28
+ if res.length != 0
29
+ usage nil
30
+ end
31
+ rescue
32
+ usage $!.to_s
33
+ end
34
+
35
+ $log = Log.new(:output => OPTS[:log_file])
36
+ Tochka::TochkaMiniUI.new(OPTS[:font_path]).run
data/exe/tochkad ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tochka"
4
+ require "optparse"
5
+
6
+ opt = OptionParser.new
7
+ OPTS=Tochka::Daemon.default_options
8
+
9
+ opt.on('-i', "--interface [IFNAME=#{Tochka::Daemon::DEFAULT_IFNAME}]",
10
+ "interface to capture") {|v|
11
+ OPTS[:ifname] = v || Tochka::Daemon::DEFAULT_IFNAME
12
+ }
13
+
14
+ opt.on('-c', "--cap-dir [CAP_PATH=#{Tochka::Daemon::DEFAULT_CAP_PATH}]",
15
+ "capture directory") {|v|
16
+ OPTS[:cap_path] = v || TOchka::Daemon::DEFAULT_CAP_PATH
17
+ }
18
+
19
+ opt.on('-l', "--log-file [LOG_FILE=STDOUT]",
20
+ "log output file (accepts 'STDOUT', 'STDERR')") {|v|
21
+ OPTS[:log_file] = v
22
+ }
23
+
24
+ (class<<self;self;end).module_eval do
25
+ define_method(:usage) do |msg|
26
+ puts opt.to_s
27
+ puts "error: #{msg}" if msg
28
+ exit 1
29
+ end
30
+ end
31
+
32
+ begin
33
+ rest = opt.parse(ARGV)
34
+ if rest.length != 0
35
+ usage nil
36
+ end
37
+ rescue
38
+ usage $!.to_s
39
+ end
40
+
41
+ # check root priviledge
42
+
43
+ $log = Log.new(:output => OPTS[:log_file])
44
+ Tochka::Daemon.new(OPTS[:ifname], OPTS[:cap_path]).run
data/ext/tochka-miniui ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+
3
+ ### BEGIN INIT INFO
4
+ # Provides: tochka-mini
5
+ # Required-Start: $remote_fs $syslog
6
+ # Required-Stop: $remote_fs $syslog
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: Put a short description of the service here
10
+ # Description: Put a long description of the service here
11
+ ### END INIT INFO
12
+
13
+ # Change the next 3 lines to suit where you install your script and what you want to call it
14
+ DIR=/usr/local/bin/
15
+ DAEMON=$DIR/tochka-miniui
16
+ DAEMON_NAME=tochka-miniui
17
+
18
+ # Add any command line options for your daemon here
19
+ DAEMON_OPTS="-l /tmp/hoge"
20
+
21
+ # This next line determines what user the script runs as.
22
+ # Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
23
+ DAEMON_USER=root
24
+
25
+ # The process ID of the script when it runs is stored here:
26
+ PIDFILE=/var/run/$DAEMON_NAME.pid
27
+
28
+ . /lib/lsb/init-functions
29
+
30
+ do_start () {
31
+ log_daemon_msg "Starting system $DAEMON_NAME daemon"
32
+ start-stop-daemon --start --background --pidfile $PIDFILE --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
33
+ log_end_msg $?
34
+ }
35
+ do_stop () {
36
+ log_daemon_msg "Stopping system $DAEMON_NAME daemon"
37
+ start-stop-daemon --stop --pidfile $PIDFILE --retry 10
38
+ log_end_msg $?
39
+ }
40
+
41
+ case "$1" in
42
+
43
+ start|stop)
44
+ do_${1}
45
+ ;;
46
+
47
+ restart|reload|force-reload)
48
+ do_stop
49
+ do_start
50
+ ;;
51
+
52
+ status)
53
+ status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
54
+ ;;
55
+
56
+ *)
57
+ echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
58
+ exit 1
59
+ ;;
60
+
61
+ esac
62
+ exit 0
data/ext/tochkad ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+
3
+ ### BEGIN INIT INFO
4
+ # Provides: tochkad
5
+ # Required-Start: $remote_fs $syslog
6
+ # Required-Stop: $remote_fs $syslog
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: Put a short description of the service here
10
+ # Description: Put a long description of the service here
11
+ ### END INIT INFO
12
+
13
+ # Change the next 3 lines to suit where you install your script and what you want to call it
14
+ DIR=/usr/local/bin/
15
+ DAEMON=$DIR/tochkad
16
+ DAEMON_NAME=tochkad
17
+
18
+ # Add any command line options for your daemon here
19
+ DAEMON_OPTS=""
20
+
21
+ # This next line determines what user the script runs as.
22
+ # Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
23
+ DAEMON_USER=root
24
+
25
+ # The process ID of the script when it runs is stored here:
26
+ PIDFILE=/var/run/$DAEMON_NAME.pid
27
+
28
+ . /lib/lsb/init-functions
29
+
30
+ do_start () {
31
+ log_daemon_msg "Starting system $DAEMON_NAME daemon"
32
+ start-stop-daemon --start --background --pidfile $PIDFILE --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
33
+ log_end_msg $?
34
+ }
35
+ do_stop () {
36
+ log_daemon_msg "Stopping system $DAEMON_NAME daemon"
37
+ start-stop-daemon --stop --pidfile $PIDFILE --retry 10
38
+ log_end_msg $?
39
+ }
40
+
41
+ case "$1" in
42
+
43
+ start|stop)
44
+ do_${1}
45
+ ;;
46
+
47
+ restart|reload|force-reload)
48
+ do_stop
49
+ do_start
50
+ ;;
51
+
52
+ status)
53
+ status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
54
+ ;;
55
+
56
+ *)
57
+ echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
58
+ exit 1
59
+ ;;
60
+
61
+ esac
62
+ exit 0
@@ -0,0 +1,116 @@
1
+ module Tochka
2
+ require "json"
3
+ require "socket"
4
+ require "tochka/log"
5
+
6
+ class Agent
7
+ attr_reader :state, :file_name, :file_size, :duration, :current_channel, :frame_count, :channel_walk, :utilization, :utilization_channel
8
+ SOCKPATH="/var/run/captured.sock"
9
+
10
+ CMD_GET_STATUS="get_status"
11
+ CMD_START_CAPTURE="start_capture"
12
+ CMD_STOP_CAPTURE="stop_capture"
13
+
14
+ STATE_INIT="init"
15
+ STATE_RUNNING="running"
16
+ STATE_STOP="stop"
17
+ STATE_UNKNOWN="unknown"
18
+
19
+ def initialize
20
+ @state = STATE_INIT
21
+ @file_name = "<None>"
22
+ @file_size = 0
23
+ @duration = 0
24
+ @current_channel = 0
25
+ @channel_walk = 0
26
+ @frame_count = 0
27
+ @utilization = 0
28
+ @utilization_channel = 0
29
+ end
30
+
31
+ def get_status
32
+ resp = do_rpc(get_msg(CMD_GET_STATUS))
33
+ if resp["state"] != nil
34
+ update_state(resp)
35
+ return resp
36
+ end
37
+
38
+ # not responded?
39
+ @state = STATE_UNKNOWN
40
+ return {}
41
+ rescue => e
42
+ $log.err("agent detected unknown error in get_status (#{e})")
43
+ return {}
44
+ end
45
+
46
+ def start_capture
47
+ $log.info("requesting start_capture")
48
+ resp = do_rpc(get_msg(CMD_START_CAPTURE))
49
+ resp = get_status()
50
+ if resp["state"] == STATE_RUNNING
51
+ update_state(resp)
52
+ return true
53
+ end
54
+
55
+ # not responded or failed
56
+ @state = STATE_UNKNOWN
57
+ return false
58
+ rescue => e
59
+ $log.err("agent detected unknown error in start_capture (#{e})")
60
+ return false
61
+ end
62
+
63
+ def stop_capture
64
+ $log.info("requesting stop_capture")
65
+ resp = do_rpc(get_msg(CMD_STOP_CAPTURE))
66
+ resp = get_status()
67
+ if resp["state"] == STATE_STOP
68
+ update_state(resp)
69
+ return true
70
+ end
71
+
72
+ return false
73
+ rescue => e
74
+ $log.err("agent detected unknown error in stop_capture (#{e})")
75
+ return false
76
+ end
77
+
78
+ private
79
+ def get_msg type=CMD_GET_STATUS
80
+ JSON.dump(
81
+ {"command"=> type}
82
+ )
83
+ end
84
+
85
+ def do_rpc req_json_msg
86
+ data = {}
87
+ UNIXSocket.open(SOCKPATH) do |sock|
88
+ sock.write(req_json_msg+"\n")
89
+ data = sock.gets
90
+ end
91
+ return JSON.parse(data)
92
+ rescue Errno::EPIPE => e
93
+ $log.err("RPC failed in do_rpc (EPIPE)")
94
+ return {}
95
+ rescue JSON::ParserError => e0
96
+ $log.err("RPC failed in do_rpc (JSON parser error)")
97
+ return {}
98
+ rescue Errno::ENOENT => e1
99
+ $log.err("RPC failed in do_rpc (no sock file, #{e1})")
100
+ return {}
101
+ end
102
+
103
+ def update_state msg
104
+ @state = msg["state"]
105
+ @file_name = msg["file_name"]
106
+ @file_size = msg["file_size"]
107
+ @duration = msg["duration"]
108
+ @current_channel = msg["current_channel"]
109
+ @channel_walk = msg["channel_walk"]
110
+ @frame_count = msg["frame_count"]
111
+ @utilization = msg["utilization"]
112
+ @utilization_channel = msg["utilization_channel"]
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,109 @@
1
+ module Tochka
2
+ class Athsurvey
3
+ FREQ2CHAN = {
4
+ 0 => 0, # why radiotap.channel.freq can be 0?
5
+ # 2.4GHz
6
+ 2412 => 1,
7
+ 2417 => 2,
8
+ 2422 => 3,
9
+ 2427 => 4,
10
+ 2432 => 5,
11
+ 2437 => 6,
12
+ 2442 => 7,
13
+ 2447 => 8,
14
+ 2452 => 9,
15
+ 2457 => 10,
16
+ 2462 => 11,
17
+ 2467 => 12,
18
+ 2472 => 13,
19
+ 2484 => 14,
20
+
21
+ # japan client only
22
+ 5170 => 34,
23
+ 5190 => 38,
24
+ 5210 => 42,
25
+ 5230 => 46,
26
+
27
+ # W52
28
+ 5180 => 36,
29
+ 5200 => 40,
30
+ 5220 => 44,
31
+ 5240 => 48,
32
+
33
+ # W53
34
+ 5260 => 52,
35
+ 5280 => 56,
36
+ 5300 => 60,
37
+ 5320 => 64,
38
+
39
+ # W56
40
+ 5500 => 100,
41
+ 5520 => 104,
42
+ 5540 => 108,
43
+ 5560 => 112,
44
+ 5580 => 116,
45
+ 5600 => 120,
46
+ 5620 => 124,
47
+ 5640 => 128,
48
+ 5660 => 132,
49
+ 5680 => 136,
50
+ 5700 => 140,
51
+ 5745 => 149,
52
+ 5765 => 153,
53
+ 5785 => 157,
54
+ 5805 => 161,
55
+ 5825 => 165,
56
+
57
+
58
+ # 802.11j
59
+ 4920 => 184,
60
+ 4940 => 188,
61
+ 4960 => 192,
62
+ 4980 => 194,
63
+ }
64
+
65
+ REG_FREQ=/^\s*frequency:\s+(\d+) /
66
+ REG_ACTIVE=/^\s*channel active time:\s+(\d+) (|m)s$/
67
+ REG_BUSY=/^\s*channel busy time:\s+(\d+) (|m)s$/
68
+
69
+ def initialize ifname
70
+ @ifname = ifname
71
+ end
72
+
73
+ def current_data
74
+ str = get_survey_dump()
75
+ active = 0
76
+ busy = 0
77
+ channel = 0
78
+
79
+ str.split("\n").map{|line| line.strip}.each do |line|
80
+ case line
81
+ when REG_FREQ
82
+ channel = FREQ2CHAN[$1.to_i]
83
+ when REG_ACTIVE
84
+ active = $1.to_i
85
+ active *= 1000 if $2 != "m"
86
+ when REG_BUSY
87
+ busy = $1.to_i
88
+ busy *= 1000 if $2 != "m"
89
+ end
90
+ end
91
+ return [0, 0, 0, 0] if active == 0
92
+
93
+ return [channel, active, busy, fto2f(busy.to_f * 100 / active.to_f) ]
94
+ end
95
+
96
+ def get_survey_dump
97
+ return `iw #{@ifname} survey dump | grep -A 4 "in use"`
98
+ end
99
+
100
+ def fto2f f
101
+ return (f * 100).to_i.to_f / 100
102
+ end
103
+ end
104
+ end
105
+
106
+ if __FILE__ == $0
107
+ aths = Tochka::Athsurvey.new("wlan0")
108
+ p aths.current_data
109
+ end
@@ -0,0 +1,39 @@
1
+ module Tochka
2
+ require "socket"
3
+
4
+ class Channel
5
+ def initialize recv_handler, sock_data
6
+ end
7
+
8
+ def start
9
+ end
10
+
11
+ def stop
12
+ end
13
+ end
14
+
15
+ class UnixSocketChannel < Channel
16
+ SOCKPATH="/var/run/captured.sock"
17
+
18
+ def initialize recv_handler, sock_path=SOCKPATH
19
+ @recv_handler = recv_handler
20
+ @sock_path = sock_path || SOCKPATH
21
+ @th = nil
22
+ end
23
+
24
+ def start
25
+ @th = Thread.new do
26
+ Socket.unix_server_loop(@sock_path) do |sock, addr|
27
+ data = sock.gets
28
+ resp = @recv_handler.call(data)
29
+ sock.write(resp+"\n")
30
+ end
31
+ end
32
+ end
33
+
34
+ def stop
35
+ @th.kill
36
+ end
37
+ end
38
+
39
+ end