abalone 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1de9af9802ec0b416470cec7b62a3cd7b3dfa053
4
- data.tar.gz: ea85d95749bb862e9b3f1edd9e69fe4cc73781f7
3
+ metadata.gz: 565875b71d7b4f783f558c97f5e4f0b3695f7428
4
+ data.tar.gz: cb3a9ed9725aee44626bb591602355a3e95a65fc
5
5
  SHA512:
6
- metadata.gz: d7d724d615b6e25db425b2d8aaaae18521053dce1c4bfbaee14b1fa6f7b26670ea603d6920e4408e15168103abd364bdd4c1b09c9a072e581bf422350bef5ce3
7
- data.tar.gz: d3b76310ff77bb549dea12f1e333d8e390d19ef9e98faef383e8ae7cac3ba3b5400278dad667a7363435828adddd586b3aad5e85f7c001a257375a143084dc7a
6
+ metadata.gz: d31db1d05ed62bdfdfe4884c4e5e9e6e1b0bbf45ef837b3363af363d7cd9aea617ca0fd45b379d5afd9bbe4928d0452f8b2619d60e335c5cdfdb5dfe334455a7
7
+ data.tar.gz: 1100692ff4a162c5daa2800bdd077cc6d481e9792235b0101e24bc8670d0fccd5957df785689d83b39956608477c0ee367fc49ffda32a17309887ca86c625992
data/README.md CHANGED
@@ -5,6 +5,8 @@ A simple Sinatra & hterm based web terminal.
5
5
 
6
6
  1. [Overview](#overview)
7
7
  1. [Configuration](#configuration)
8
+ 1. [SSH](#configuring-ssh)
9
+ 1. [Custom Login Command](#configuring-a-custom-command)
8
10
  1. [Limitations](#limitations)
9
11
 
10
12
  ## Overview
@@ -24,7 +26,22 @@ It supports three methods for providing a shell:
24
26
 
25
27
  Abalone defaults to loading configuration from `/etc/abalone/config.yaml`. You
26
28
  can pass the path to another config file at the command line. In that file, you
27
- can set one of `:command` or `:ssh`.
29
+ can set several options:
30
+
31
+ * `:port`
32
+ * Which port to run the server on.
33
+ * Default value: `9000`
34
+ * `:bind`
35
+ * The hostname or IP address of the interface to listen on.
36
+ * Default value: `0.0.0.0` (listen to all interfaces.)
37
+ * `:logfile`
38
+ * The path of a file to log to.
39
+ * Default value: Log only to `STDERR`. If you pass `-l` at the command line
40
+ with no filename, it will log to `/var/log/abalone`.
41
+ * One of [`:command`](#configuring-a-custom-command) or [`:ssh`](#configuring-ssh), exclusive.
42
+ * The login method to use. Abalone can use `login`, SSH, or a custom command
43
+ to start a shell. See configuration instructions below.
44
+ * Default value: uses the `login` binary, with no configuration possible.
28
45
 
29
46
  ### Configuring SSH
30
47
 
@@ -6,11 +6,10 @@ require 'abalone'
6
6
  require 'yaml'
7
7
 
8
8
  defaults = {
9
- :port => 9000,
10
- :host => '0.0.0.0',
11
- :bind => '0.0.0.0',
9
+ :port => 9000,
10
+ :bind => '0.0.0.0',
11
+ :logfile => $stderr,
12
12
  }
13
- logfile = $stderr
14
13
  loglevel = Logger::WARN
15
14
  configfile = '/etc/abalone/config.yaml'
16
15
  options = {}
@@ -29,7 +28,7 @@ optparse = OptionParser.new { |opts|
29
28
  end
30
29
 
31
30
  opts.on("-l [LOGFILE]", "--logfile [LOGFILE]", "Path to logfile. Defaults to no logging, or /var/log/abalone if no filename is passed.") do |arg|
32
- logfile = arg || '/var/log/abalone'
31
+ options[:logfile] = arg || defaults[:logfile] || '/var/log/abalone'
33
32
  end
34
33
 
35
34
  opts.on("-p PORT", "--port PORT", "Port to listen on. Defaults to 9000.") do |arg|
@@ -47,13 +46,13 @@ optparse = OptionParser.new { |opts|
47
46
  }
48
47
  optparse.parse!
49
48
 
50
- logger = Logger.new(logfile)
51
- logger.level = loglevel
52
- options[:logger] = logger
53
-
54
49
  config = YAML.load_file(configfile) rescue {}
55
50
  options = defaults.merge(config.merge(options))
56
51
 
52
+ logger = Logger.new(options[:logfile])
53
+ logger.level = loglevel
54
+ options[:logger] = logger
55
+
57
56
  if options[:params].class == Hash
58
57
  options[:params].each do |param, data|
59
58
  next if data.nil?
@@ -74,7 +73,7 @@ end
74
73
  raise 'Specify only one of a login command or SSH settings' if options.include? :command and options.include? :ssh
75
74
 
76
75
  if options.include? :command
77
- raise ":params must be an Array or Hash, not #{options[:params].class}" unless [Array, Hash].include? options[:params].class
76
+ raise ":params must be an Array or Hash, not #{options[:params].class}" unless [Array, Hash, NilClass].include? options[:params].class
78
77
  raise ":command should be a String or an Array, not a #{options[:command].class}." unless [Array, String].include? options[:command].class
79
78
  end
80
79
 
@@ -9,8 +9,8 @@ require 'io/console'
9
9
  class Abalone < Sinatra::Base
10
10
  set :logging, true
11
11
  set :strict, true
12
- set :public_folder, 'public'
13
- set :views, 'views'
12
+ set :public_folder, "#{settings.root}/../public"
13
+ set :views, "#{settings.root}/../views"
14
14
 
15
15
  before {
16
16
  env["rack.logger"] = settings.logger if settings.logger
@@ -46,19 +46,26 @@ class Abalone < Sinatra::Base
46
46
  # there must be some form of event driven pty interaction, EM or some gem maybe?
47
47
  reader.sync = true
48
48
  @term = Thread.new do
49
+ carry = []
49
50
  loop do
50
51
  begin
51
52
  PTY.check(@pid, true)
52
- data = reader.read_nonblock(512) # we read non-blocking to stream data as quickly as we can
53
+ output = reader.read_nonblock(512).unpack('c*') # we read non-blocking to stream data as quickly as we can
54
+ index = output.rindex { |x| x < 128 } # find the last low bit
55
+ carry = output[index...-11] # save the any remaining high bits and partial chars for next go-round
56
+ data = (carry + output[0..index]).pack('c*').force_encoding('UTF-8') # and pack the rest back into a string to send
57
+
58
+ ws.send(data)
59
+
53
60
  rescue IO::WaitReadable
54
61
  IO.select([reader])
55
62
  retry
56
63
  rescue PTY::ChildExited => e
57
- puts "Terminal has exited!"
58
- ws.send({'event' => 'logout'}.to_json)
64
+ warn('Terminal has exited!')
65
+ ws.close_connection
66
+
59
67
  Thread.exit
60
68
  end
61
- ws.send({'event' => 'output', 'data' => data}.to_json)
62
69
  sleep(0.05)
63
70
  end
64
71
  end
@@ -66,7 +73,7 @@ class Abalone < Sinatra::Base
66
73
  end
67
74
 
68
75
  ws.onclose do
69
- warn("websocket closed")
76
+ warn('websocket closed')
70
77
  stop_term()
71
78
  end
72
79
 
@@ -91,9 +98,10 @@ class Abalone < Sinatra::Base
91
98
  warn("Unrecognized message: #{message.inspect}")
92
99
  end
93
100
  rescue Errno::EIO => e
94
- puts "Terminal has died!"
101
+ puts "Remote terminal closed."
95
102
  puts e.message
96
- ws.send({'event' => 'logout'}.to_json)
103
+ stop_term()
104
+
97
105
  end
98
106
 
99
107
  end
@@ -108,7 +116,7 @@ class Abalone < Sinatra::Base
108
116
  helpers do
109
117
  def stop_term()
110
118
  Process.kill('TERM', @pid) rescue nil
111
- @term.join
119
+ @term.join rescue nil
112
120
  end
113
121
 
114
122
  def sanitized(params)
@@ -36,7 +36,7 @@
36
36
  </style>
37
37
  </head>
38
38
 
39
- <body onload="connect(boogers);">
39
+ <body onload="connect();">
40
40
  <div id="overlay"><input type="button" onclick="javascript:connect();" value="reconnect" /></div>
41
41
  <div id="terminal"></div>
42
42
  </body>
@@ -59,29 +59,11 @@ function disconnected() {
59
59
  }
60
60
 
61
61
  function messageHandler(data) {
62
- message = JSON.parse(data);
63
-
64
- switch(message['event']) {
65
- case 'output':
66
- if (!term) {
67
- buf += message['data'];
68
- return;
69
- }
70
- term.io.writeUTF16(message['data']);
71
- break;
72
-
73
- case 'logout':
74
- console.log("user logout");
75
- disconnected();
76
- break;
77
-
78
- case 'disconnect':
79
- disconnected();
80
- break;
81
-
82
- default:
83
-
62
+ if (!term) {
63
+ buf += data;
64
+ return;
84
65
  }
66
+ term.io.writeUTF16(data);
85
67
  }
86
68
 
87
69
  /* borrowed from https://github.com/krishnasrinivas/wetty */
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abalone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Ford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-31 00:00:00.000000000 Z
11
+ date: 2016-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra