rsence 2.0.0.6.pre → 2.0.0.7.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL.rdoc +39 -25
- data/VERSION +1 -1
- data/conf/default_conf.yaml +0 -3
- data/lib/conf/default.rb +59 -60
- data/lib/daemon/daemon.rb +269 -280
- data/lib/http/broker.rb +47 -14
- data/lib/http/rackup.rb +4 -0
- data/lib/http/request.rb +47 -49
- data/lib/http/response.rb +47 -45
- data/lib/plugins/gui_plugin.rb +22 -21
- data/lib/plugins/guiparser.rb +95 -94
- data/lib/plugins/plugin.rb +300 -295
- data/lib/plugins/plugin_plugins.rb +64 -40
- data/lib/plugins/plugin_sqlite_db.rb +63 -63
- data/lib/plugins/plugin_util.rb +95 -104
- data/lib/plugins/pluginmanager.rb +373 -414
- data/lib/plugins/plugins.rb +11 -4
- data/lib/plugins/servlet.rb +10 -9
- data/lib/session/msg.rb +249 -248
- data/lib/session/sessionmanager.rb +364 -373
- data/lib/session/sessionstorage.rb +265 -272
- data/lib/transporter/transporter.rb +164 -169
- data/lib/util/gzstring.rb +2 -0
- data/lib/values/hvalue.rb +224 -224
- data/lib/values/valuemanager.rb +98 -98
- data/plugins/index_html/index_html.rb +1 -32
- metadata +4 -4
data/INSTALL.rdoc
CHANGED
@@ -7,6 +7,7 @@ If you already have a working ruby environment and know what to do, the easiest
|
|
7
7
|
|
8
8
|
gem install rsence --pre
|
9
9
|
|
10
|
+
|
10
11
|
Otherwise, follow these instructions:
|
11
12
|
|
12
13
|
|
@@ -30,7 +31,6 @@ This step applies only to Mac OS X 10.4 Tiger and 10.5 Leopard
|
|
30
31
|
|
31
32
|
sudo port install ruby +thread_hooks
|
32
33
|
sudo port install rb-rubygems
|
33
|
-
sudo port install sqlite3-ruby
|
34
34
|
|
35
35
|
==== 1.1.2 Mac OS X 10.6
|
36
36
|
|
@@ -47,35 +47,49 @@ This step applies only to Debian, Ubuntu and similar Linux distributions.
|
|
47
47
|
|
48
48
|
* Install these packages:
|
49
49
|
|
50
|
-
sudo apt-get install build-essential ruby-full
|
50
|
+
sudo apt-get install build-essential ruby-full rubygems rake
|
51
51
|
|
52
52
|
|
53
53
|
=== 1.3. Microsoft Windows
|
54
54
|
|
55
|
-
|
56
|
-
Windows compatibility
|
57
|
-
|
58
|
-
Install ruby 1.8.7:
|
59
|
-
* Download
|
60
|
-
*
|
61
|
-
*
|
62
|
-
|
63
|
-
|
64
|
-
* Download
|
65
|
-
*
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
*
|
70
|
-
|
71
|
-
|
72
|
-
|
55
|
+
RSence works just fine on Windows too, with a few limitations.
|
56
|
+
Windows compatibility has been officially tested on Windows XP SP3 and Windows 7 (64 bit).
|
57
|
+
|
58
|
+
==== 1.3.1. Install ruby 1.8.7:
|
59
|
+
* Download Ruby 1.8.7-p249 (RC2) from http://rubyinstaller.org/download.html
|
60
|
+
* Run the downloaded exe to install ruby
|
61
|
+
* In the installation and destination prompt, check these options:
|
62
|
+
* [x] Add Ruby executables to your PATH
|
63
|
+
* [x] Associate .rb and .rbw files with this Ruby installation
|
64
|
+
* Download and Install the Development Kit from http://rubyinstaller.org/download.html
|
65
|
+
* Extract the included directories into the directory where you installed ruby.
|
66
|
+
* It's C:\ruby by default.
|
67
|
+
|
68
|
+
==== 1.3.2. Install RSence
|
69
|
+
* In the command prompt, run:
|
70
|
+
gem update --system
|
71
|
+
gem install rsence --pre
|
72
|
+
rsence help
|
73
|
+
|
74
|
+
==== 1.3.3. Create RSence environment
|
75
|
+
|
76
|
+
This assumes you have \my_projects directory.
|
77
|
+
Also, the 'my_project' project directory is just for illustration purposes.
|
78
|
+
Use something else instead of those.
|
79
|
+
|
80
|
+
* In the command prompt, run:
|
81
|
+
cd \my_projects
|
82
|
+
rsence initenv my_project
|
83
|
+
* Answer the quetions
|
84
|
+
* In the command prompt, run:
|
85
|
+
rsence run my_project
|
86
|
+
* Open your web browser in the address as configured.
|
87
|
+
* If the address is 0.0.0.0, ether 127.0.0.1 instead.
|
88
|
+
|
89
|
+
==== 1.3.4. Windows limitations
|
90
|
+
If you install the sqlite dll and the sqlite3-ruby gem, you'll gain persistent sessions and the "Warning: Session database is not available. Can't use persistent sessions" message will disappear when starting up rsence. It's not, however depended on in the default install, because it's not strictly required and makes the first installation much easier.
|
91
|
+
Backgrounding is not yet implemented, because POSIX signals are not fully implemented in windows and backgrounding requires some windows service hooks.
|
73
92
|
|
74
|
-
NOTICE:
|
75
|
-
* Configure http with either *mongrel* or *webrick*
|
76
|
-
* Ensure the session database string doesn't include the "C:" -part (when using sqlite)
|
77
|
-
* Only the *run* (foreground) mode is supported; no start, stop, restart etc commands because backgrounding isn't possible on Windows unless configured as a Service
|
78
|
-
* Prefix all commands with ruby
|
79
93
|
|
80
94
|
=== 1.99. Other UNIX / Linux systems:
|
81
95
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.0.
|
1
|
+
2.0.0.7.pre
|
data/conf/default_conf.yaml
CHANGED
data/lib/conf/default.rb
CHANGED
@@ -13,8 +13,16 @@ require 'rack'
|
|
13
13
|
require 'yaml'
|
14
14
|
|
15
15
|
if RUBY_VERSION.to_f >= 1.9
|
16
|
-
#
|
17
|
-
#
|
16
|
+
# --
|
17
|
+
# Ruby 1.9 encoding defaults.
|
18
|
+
# This is clearly not enough but a good start for fixing the encoding madness.
|
19
|
+
# ++
|
20
|
+
Encoding.default_external = Encoding::BINARY
|
21
|
+
Encoding.default_internal = Encoding::BINARY
|
22
|
+
# --
|
23
|
+
# Ruby 1.9 doesn't have String#each anymore.
|
24
|
+
# This is a backwards-compatible work-around.
|
25
|
+
# ++
|
18
26
|
class String
|
19
27
|
def each
|
20
28
|
self.split($/).each { |e| yield e }
|
@@ -22,15 +30,10 @@ if RUBY_VERSION.to_f >= 1.9
|
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
25
|
-
#
|
26
|
-
LIB_PATHS = []
|
27
|
-
PIDPATH = File.join(SERVER_PATH,'var','run')
|
28
|
-
LOGPATH = File.join(SERVER_PATH,'var','log')
|
29
|
-
def load_legacy( local_config_file_path )
|
30
|
-
require local_config_file_path[0..-4]
|
31
|
-
end
|
32
|
-
|
33
|
+
# Configuration handles config files and such.
|
33
34
|
class Configuration
|
35
|
+
|
36
|
+
# Method for combining two arrays
|
34
37
|
def array_merge( target, source )
|
35
38
|
source.each do |item|
|
36
39
|
unless target.include?(item)
|
@@ -48,6 +51,8 @@ class Configuration
|
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
54
|
+
|
55
|
+
# Method for combining two hashes.
|
51
56
|
def hash_merge( target, source )
|
52
57
|
source.each do |key,item|
|
53
58
|
if not target.has_key?key or target[key] != item
|
@@ -63,60 +68,57 @@ class Configuration
|
|
63
68
|
end
|
64
69
|
end
|
65
70
|
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
wizard_conf_file = File.join( Dir.pwd, 'conf', 'local_conf.yaml' )
|
71
|
-
else
|
72
|
-
wizard_conf_file = File.join( SERVER_PATH, 'conf', 'local_conf.yaml' )
|
73
|
-
end
|
74
|
-
wizard_config_data = ConfigWizard.new(config).run( wizard_conf_file )
|
75
|
-
config.merge!( wizard_config_data )
|
76
|
-
end
|
71
|
+
|
72
|
+
# The args structure comes from RSence::ARGVParser
|
73
|
+
# The dont_expand_path is for special cases, when
|
74
|
+
# Configuration is used without running RSence.
|
77
75
|
def initialize( args, dont_expand_path=false )
|
76
|
+
|
78
77
|
## Paths for log and pid files
|
79
78
|
pidpath = File.join( args[:env_path], 'run' )
|
80
79
|
logpath = File.join( args[:env_path], 'log' )
|
81
80
|
|
81
|
+
# The default configuration path, this one is distributed with the system.
|
82
82
|
yaml_conf_path = File.join( SERVER_PATH, 'conf', 'default_conf.yaml' )
|
83
83
|
|
84
|
+
# Parses the default configuration from yaml first.
|
85
|
+
# This is used as the basis for overriding the defaults in various other config files.
|
86
|
+
config = YAML.load( File.read( yaml_conf_path ) )
|
87
|
+
|
88
|
+
# The default strings for various messages, this one is distributed with the system.
|
84
89
|
yaml_strings_path = File.join( SERVER_PATH, 'conf', 'default_strings.yaml' )
|
85
90
|
strings = YAML.load( File.read( yaml_strings_path ) )
|
86
91
|
|
87
|
-
|
88
|
-
config = YAML.load( File.read( yaml_conf_path ) )
|
92
|
+
# Transporter-specific strings are set.
|
89
93
|
config[:transporter_conf][:messages] = strings[:messages][:transporter]
|
90
94
|
|
95
|
+
# Makes the distribution 'js' directory containing the client core the
|
96
|
+
# first client package source directory.
|
91
97
|
config[:client_pkg][:src_dirs].unshift( File.join( SERVER_PATH, 'js' ) )
|
92
98
|
|
99
|
+
# The distributed standard plugins are in this directory.
|
93
100
|
default_plugins_path = File.join( SERVER_PATH, 'plugins' )
|
94
101
|
unless config[:plugin_paths].include? default_plugins_path
|
95
102
|
config[:plugin_paths].push( default_plugins_path )
|
96
103
|
end
|
97
104
|
|
98
|
-
|
99
|
-
lib_paths = [
|
100
|
-
## already included in launch.rb; override this one in local config, if needed
|
101
|
-
#File.join( SERVER_PATH, 'lib' )
|
102
|
-
]
|
105
|
+
# Paths to add to $LOAD_PATH after all configuration files are read.
|
106
|
+
lib_paths = []
|
103
107
|
|
104
|
-
|
108
|
+
# List of configuration files to look for.
|
105
109
|
local_config_file_paths = [
|
106
110
|
File.join(SERVER_PATH,'conf','local_conf.yaml'),
|
107
111
|
'/etc/rsence/config.yaml',
|
108
112
|
File.expand_path('~/.rsence/config.yaml'),
|
109
|
-
File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.yaml' )
|
110
|
-
# File.join( Dir.pwd, 'conf', 'local_conf.yaml' ),
|
111
|
-
File.join(SERVER_PATH,'conf','local_conf.rb'),
|
112
|
-
# File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.rb' ),
|
113
|
-
# File.join( Dir.pwd, 'conf', 'local_conf.rb' )
|
113
|
+
File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.yaml' )
|
114
114
|
]
|
115
115
|
|
116
|
+
# Add the additional config files optionally specified in ARGVParser
|
116
117
|
args[:conf_files].each do |conf_file|
|
117
118
|
local_config_file_paths.push( conf_file )
|
118
119
|
end
|
119
120
|
|
121
|
+
# Loads the configuration files
|
120
122
|
local_config_file_paths.each do |local_config_file_path|
|
121
123
|
if File.exists? local_config_file_path and File.file? local_config_file_path
|
122
124
|
if local_config_file_path.end_with? '.yaml'
|
@@ -127,29 +129,24 @@ class Configuration
|
|
127
129
|
next
|
128
130
|
end
|
129
131
|
hash_merge( config, local_conf )
|
130
|
-
elsif local_config_file_path.end_with? '.rb'
|
131
|
-
warn "WARNING: '.rb' configuration files are deprecated!"
|
132
|
-
# Legacy work-arounds
|
133
|
-
prev_pidpath = PIDPATH
|
134
|
-
prev_logpath = LOGPATH
|
135
|
-
# /Legacy work-arounds
|
136
|
-
load_legacy( local_config_file_path )
|
137
|
-
# Legacy work-arounds
|
138
|
-
pidpath = PIDPATH if PIDPATH != prev_pidpath
|
139
|
-
logpath = LOGPATH if LOGPATH != prev_logpath
|
140
|
-
# /Legacy work-arounds
|
141
132
|
else
|
142
|
-
warn "Only Yaml
|
133
|
+
warn "Only Yaml configuration files are supported."
|
143
134
|
end
|
144
135
|
end
|
145
136
|
end
|
146
137
|
|
138
|
+
# Adds the plugins directory of the environment
|
139
|
+
# to the configuration automatically
|
147
140
|
env_plugins_path = File.expand_path( 'plugins', args[:env_path] )
|
148
141
|
unless config[:plugin_paths].include? env_plugins_path
|
149
142
|
config[:plugin_paths].push( env_plugins_path )
|
150
143
|
end
|
144
|
+
|
145
|
+
# At this point, configuration files are read and ready.
|
146
|
+
|
151
147
|
puts "plugin paths: #{config[:plugin_paths].inspect}" if args[:debug]
|
152
148
|
|
149
|
+
# Override configuration options with command-line-options.
|
153
150
|
config[:trace] = true if args[:trace_js]
|
154
151
|
config[:debug_mode] = true if args[:debug]
|
155
152
|
config[:http_server][:latency] = args[:latency]
|
@@ -158,23 +155,26 @@ class Configuration
|
|
158
155
|
config[:http_server][:rack_require] = args[:server] if args[:server]
|
159
156
|
config[:session_conf][:reset_sessions] = true if args[:reset_ses]
|
160
157
|
|
158
|
+
config[:client_pkg][:no_obfuscation] = true if args[:client_pkg_no_obfuscation]
|
159
|
+
config[:client_pkg][:no_whitespace_removal] = true if args[:client_pkg_no_whitespace_removal]
|
160
|
+
|
161
|
+
# Sets the default pid and log paths used by the HTTPDaemon
|
161
162
|
config[:daemon][:pid_fn] = File.join(pidpath, "rsence.pid") unless config[:daemon].has_key?(:pid_fn)
|
162
163
|
config[:daemon][:log_fn] = File.join(logpath, "rsence") unless config[:daemon].has_key?(:log_fn)
|
163
164
|
|
165
|
+
# Check database path for sqlite databases.
|
164
166
|
if config[:database][:ses_db].start_with?('sqlite://') and not dont_expand_path
|
165
167
|
db_url = File.expand_path( config[:database][:ses_db].split('sqlite://')[1], args[:env_path] )
|
166
168
|
config[:database][:ses_db] = "sqlite://#{db_url}"
|
167
169
|
end
|
168
170
|
|
169
|
-
|
171
|
+
# Sets the various standard url prefixes:
|
170
172
|
[ ## POST-requests
|
171
173
|
# broker_key # default_uri
|
172
174
|
# The default responder for transporter requests.
|
173
175
|
[ :x, File.join(config[:base_url],'x') ],
|
174
176
|
# The default responder for cookie-enabled "handshake" transporter requests
|
175
177
|
[ :hello, File.join(config[:base_url],'hello') ],
|
176
|
-
# The default responder for SOAP -requests
|
177
|
-
[ :soap, File.join(config[:base_url],'SOAP') ],
|
178
178
|
# The default responder for file uploads
|
179
179
|
[ :u, File.join(config[:base_url],'U') ],
|
180
180
|
|
@@ -199,30 +199,29 @@ class Configuration
|
|
199
199
|
config[:broker_urls][broker_key] = default_uri
|
200
200
|
end
|
201
201
|
end
|
202
|
-
|
203
|
-
|
204
|
-
|
202
|
+
|
203
|
+
if RUBY_VERSION.to_f >= 1.9
|
204
|
+
# The encodings mess up compression when using ruby1.9
|
205
|
+
warn "Disabling gzip support for ruby 1.9" if args[:debug]
|
206
|
+
config[:no_gzip] = true
|
207
|
+
end
|
208
|
+
|
205
209
|
# The default address of the index_html plugin
|
206
210
|
unless config[:index_html].has_key?(:respond_address)
|
207
211
|
config[:index_html][:respond_address] = File.join(config[:base_url])
|
208
212
|
end
|
209
213
|
|
210
|
-
config[:client_pkg][:no_obfuscation] = true if args[:client_pkg_no_obfuscation]
|
211
|
-
config[:client_pkg][:no_whitespace_removal] = true if args[:client_pkg_no_whitespace_removal]
|
212
|
-
|
213
214
|
## Uses the lib paths as search paths
|
215
|
+
lib_paths.merge( config[:lib_paths] ) if config.has_key?(:lib_paths)
|
214
216
|
lib_paths.each do |lib_path|
|
215
217
|
$LOAD_PATH << lib_path
|
216
218
|
end
|
217
219
|
|
218
|
-
## Legacy:
|
219
|
-
LIB_PATHS.each do |lib_path|
|
220
|
-
$LOAD_PATH << lib_path
|
221
|
-
end
|
222
|
-
|
223
220
|
@config = config
|
224
221
|
end
|
222
|
+
|
225
223
|
attr_reader :config
|
224
|
+
|
226
225
|
end
|
227
226
|
|
228
227
|
|
data/lib/daemon/daemon.rb
CHANGED
@@ -10,29 +10,6 @@
|
|
10
10
|
|
11
11
|
# Use rubygems to load rack
|
12
12
|
require 'rubygems'
|
13
|
-
require 'rack'
|
14
|
-
|
15
|
-
# Loads the selected web-server (default is 'thin')
|
16
|
-
require RSence.config[:http_server][:rack_require]
|
17
|
-
|
18
|
-
# Methods that return rack the selected handler
|
19
|
-
def rack_webrick_handler; Rack::Handler::WEBrick; end
|
20
|
-
def rack_ebb_handler; Rack::Handler::Ebb; end
|
21
|
-
def rack_thin_handler; Rack::Handler::Thin; end
|
22
|
-
def rack_mongrel_handler; Rack::Handler::Mongrel; end
|
23
|
-
def rack_unicorn_handler; Rack::Handler::Unicorn; end
|
24
|
-
def rack_rainbows_handler; Rack::Handler::Rainbows; end
|
25
|
-
|
26
|
-
# Selects the handler for Rack
|
27
|
-
RSence.config[:http_server][:rack_handler] = self.method({
|
28
|
-
'fuzed' => :rack_fuzed_handler,
|
29
|
-
'webrick' => :rack_webrick_handler,
|
30
|
-
'ebb' => :rack_ebb_handler,
|
31
|
-
'thin' => :rack_thin_handler,
|
32
|
-
'mongrel' => :rack_mongrel_handler,
|
33
|
-
'unicorn' => :rack_unicorn_handler,
|
34
|
-
'rainbows' => :rack_rainbows_handler
|
35
|
-
}[RSence.config[:http_server][:rack_require]]).call
|
36
13
|
|
37
14
|
# Transporter is the top-level handler for calls coming from the javascript COMM.Transporter.
|
38
15
|
require 'transporter/transporter'
|
@@ -42,327 +19,339 @@ require 'http/broker'
|
|
42
19
|
|
43
20
|
|
44
21
|
module ::RSence
|
22
|
+
|
23
|
+
@@launch_pid = Process.pid
|
24
|
+
|
25
|
+
# Returns the pid of the process when starting up.
|
26
|
+
# PID is different for the forked child process(es)
|
27
|
+
def self.launch_pid
|
28
|
+
return @@launch_pid
|
29
|
+
end
|
45
30
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
# the name of the pid file.
|
57
|
-
def self.write_pid( daemon, pid )
|
58
|
-
File.open( daemon.pid_fn, 'w' ) do |pidfile|
|
59
|
-
pidfile.write( pid )
|
31
|
+
# The Controller module handles the damonizing
|
32
|
+
# operations of the process referred to as +daemon+
|
33
|
+
module Daemon
|
34
|
+
|
35
|
+
# Writes the process id to disk, the pid_fn method of the daemon contains
|
36
|
+
# the name of the pid file.
|
37
|
+
def self.write_pid( daemon, pid )
|
38
|
+
File.open( daemon.pid_fn, 'w' ) do |pidfile|
|
39
|
+
pidfile.write( pid )
|
40
|
+
end
|
60
41
|
end
|
61
|
-
end
|
62
42
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
43
|
+
# Reads the process id from disk, the pid_fn method of the daemon contains
|
44
|
+
# the name of the pid file. Returns nil on errors.
|
45
|
+
def self.read_pid( daemon )
|
46
|
+
File.read( daemon.pid_fn ).to_i rescue nil
|
47
|
+
end
|
68
48
|
|
69
|
-
|
70
|
-
|
71
|
-
|
49
|
+
def self.responds?( daemon )
|
50
|
+
wait_signal_response( daemon, 'USR2' )
|
51
|
+
end
|
72
52
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
53
|
+
# Reads the pid file and calls the process.
|
54
|
+
# Returns true if the process responds, false otherwise (no process)
|
55
|
+
def self.status( daemon )
|
56
|
+
pid = read_pid( daemon )
|
57
|
+
return nil if not pid
|
58
|
+
return responds?( daemon )
|
59
|
+
end
|
80
60
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
61
|
+
# Redirects standard input and errors to the log files
|
62
|
+
def self.start_logging( daemon )
|
63
|
+
outpath = "#{daemon.log_fn}.stdout"
|
64
|
+
errpath = "#{daemon.log_fn}.stderr"
|
65
|
+
STDOUT.reopen( outpath, (File.exist?( outpath ) ? 'a' : 'w') )
|
66
|
+
STDOUT.sync = true
|
67
|
+
STDERR.reopen( errpath, (File.exist?( errpath ) ? 'a' : 'w') )
|
68
|
+
STDERR.sync = true
|
69
|
+
end
|
90
70
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
71
|
+
# Writes a signal response file containing the pid.
|
72
|
+
def self.write_signal_response( daemon, signal )
|
73
|
+
pid = Process.pid.to_s
|
74
|
+
pid_fn = daemon.pid_fn
|
75
|
+
RSence::SIGComm.write_signal_response( pid, pid_fn, signal )
|
76
|
+
end
|
96
77
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
78
|
+
# Removes a signal response file.
|
79
|
+
def self.delete_signal_response( daemon, signal )
|
80
|
+
pid_fn = daemon.pid_fn
|
81
|
+
RSence::SIGComm.delete_signal_response( pid_fn )
|
82
|
+
end
|
101
83
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
84
|
+
# Waits for a signal response.
|
85
|
+
def self.wait_signal_response( daemon, signal, timeout = 10,
|
86
|
+
debug_pre = false, debug_suf = false, sleep_secs = 0.2 )
|
87
|
+
pid = read_pid( daemon )
|
88
|
+
pid_fn = daemon.pid_fn
|
89
|
+
return RSence::SIGComm.wait_signal_response( pid, pid_fn, signal, timeout, debug_pre, debug_suf, sleep_secs )
|
90
|
+
end
|
108
91
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
92
|
+
# Signal trapping for windows.
|
93
|
+
# The only supported POSIX signal trappable seems to be INT (CTRL-C).
|
94
|
+
def self.trap_windows_signals( daemon )
|
95
|
+
['INT'].each do | signal |
|
96
|
+
Signal.trap( signal ) do
|
97
|
+
puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
|
98
|
+
daemon.usr1
|
99
|
+
daemon.stop
|
100
|
+
puts "Shutdown complete."
|
101
|
+
exit
|
102
|
+
end
|
117
103
|
end
|
118
104
|
end
|
119
|
-
end
|
120
105
|
|
121
|
-
|
122
|
-
|
106
|
+
# Traps common POSIX signals
|
107
|
+
def self.trap_signals( daemon )
|
123
108
|
|
124
|
-
|
125
|
-
|
126
|
-
daemon.usr1
|
127
|
-
write_signal_response( daemon, 'USR1' )
|
128
|
-
end
|
129
|
-
Signal.trap('USR2') do
|
130
|
-
daemon.usr2
|
131
|
-
write_signal_response( daemon, 'USR2' )
|
132
|
-
end
|
133
|
-
['INT', 'TERM', 'KILL'].each do | signal |
|
134
|
-
Signal.trap( signal ) do
|
135
|
-
puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
|
109
|
+
# Triggered with 'kill -USR1 `cat rsence.pid`'
|
110
|
+
Signal.trap( 'USR1' ) do
|
136
111
|
daemon.usr1
|
112
|
+
write_signal_response( daemon, 'USR1' )
|
113
|
+
end
|
114
|
+
Signal.trap('USR2') do
|
115
|
+
daemon.usr2
|
116
|
+
write_signal_response( daemon, 'USR2' )
|
117
|
+
end
|
118
|
+
['INT', 'TERM', 'KILL'].each do | signal |
|
119
|
+
Signal.trap( signal ) do
|
120
|
+
puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
|
121
|
+
daemon.usr1
|
122
|
+
daemon.stop
|
123
|
+
delete_stale_pids( daemon )
|
124
|
+
write_signal_response( daemon, signal )
|
125
|
+
puts "Shutdown complete."
|
126
|
+
exit
|
127
|
+
end
|
128
|
+
end
|
129
|
+
Signal.trap('HUP') do
|
137
130
|
daemon.stop
|
138
|
-
|
139
|
-
write_signal_response( daemon, signal )
|
140
|
-
puts "Shutdown complete."
|
141
|
-
exit
|
131
|
+
daemon.start
|
142
132
|
end
|
143
133
|
end
|
144
|
-
Signal.trap('HUP') do
|
145
|
-
daemon.stop
|
146
|
-
daemon.start
|
147
|
-
end
|
148
|
-
end
|
149
134
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
135
|
+
# Removes all pid files that were left around if a process died unexpectedly.
|
136
|
+
def self.delete_stale_pids( daemon )
|
137
|
+
( pid_fn_path, pid_fn_name ) = File.split( daemon.pid_fn )
|
138
|
+
Dir.entries( pid_fn_path ).each do | item_fn |
|
139
|
+
item_path = File.join( pid_fn_path, item_fn )
|
140
|
+
if item_fn.start_with?( pid_fn_name ) and File.file?( item_path )
|
141
|
+
puts "Stale pid file (#{item_fn}), removing.." if RSence.args[:verbose]
|
142
|
+
File.delete( item_path )
|
143
|
+
end
|
157
144
|
end
|
158
145
|
end
|
159
|
-
end
|
160
146
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
147
|
+
# Creates pid file and traps signal.
|
148
|
+
def self.init_pid( daemon )
|
149
|
+
if RSence.pid_support?
|
150
|
+
is_running = status( daemon )
|
151
|
+
if is_running
|
152
|
+
puts "RSence is already running."
|
153
|
+
puts "Stop the existing process first: see 'rsence help stop'"
|
154
|
+
if RSence.launch_pid != Process.pid
|
155
|
+
Process.kill( 'INT', RSence.launch_pid )
|
156
|
+
end
|
157
|
+
exit
|
158
|
+
elsif not is_running
|
159
|
+
delete_stale_pids( daemon )
|
169
160
|
end
|
170
|
-
|
171
|
-
|
172
|
-
|
161
|
+
trap_signals( daemon )
|
162
|
+
pid = Process.pid
|
163
|
+
write_pid( daemon, pid )
|
164
|
+
return pid
|
165
|
+
else
|
166
|
+
trap_windows_signals( daemon )
|
167
|
+
return false
|
173
168
|
end
|
174
|
-
trap_signals( daemon )
|
175
|
-
pid = Process.pid
|
176
|
-
write_pid( daemon, pid )
|
177
|
-
return pid
|
178
|
-
else
|
179
|
-
trap_windows_signals( daemon )
|
180
|
-
return false
|
181
169
|
end
|
182
|
-
end
|
183
170
|
|
184
|
-
|
185
|
-
|
186
|
-
daemon.run
|
187
|
-
exit
|
188
|
-
end
|
189
|
-
|
190
|
-
def self.start( daemon )
|
191
|
-
fork do
|
192
|
-
exit if fork
|
171
|
+
# Inits the pid, signals and then starts the server in the foreground
|
172
|
+
def self.run( daemon )
|
193
173
|
init_pid( daemon )
|
194
|
-
daemon.
|
195
|
-
end
|
196
|
-
Signal.trap('INT') do
|
197
|
-
puts "RSence startup failed. Please inspect the log and/or run in debug mode."
|
174
|
+
daemon.run
|
198
175
|
exit
|
199
176
|
end
|
200
|
-
|
201
|
-
|
202
|
-
|
177
|
+
|
178
|
+
# Inits the pid, signals and then starts the daemon in
|
179
|
+
# the background and waits until the daemon sends the TERM signal.
|
180
|
+
def self.start( daemon )
|
181
|
+
fork do
|
182
|
+
exit if fork
|
183
|
+
init_pid( daemon )
|
184
|
+
daemon.start
|
185
|
+
end
|
186
|
+
Signal.trap('INT') do
|
187
|
+
puts "RSence startup failed. Please inspect the log and/or run in debug mode."
|
188
|
+
exit
|
189
|
+
end
|
190
|
+
Signal.trap('TERM') do
|
191
|
+
puts "RSence is online at http://#{daemon.addr}:#{daemon.port}/"
|
192
|
+
exit
|
193
|
+
end
|
194
|
+
sleep 1 while true
|
203
195
|
end
|
204
|
-
sleep 1 while true
|
205
|
-
end
|
206
196
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
197
|
+
# Sends the USR1 signal to the process, which in turn
|
198
|
+
# calls the save method of the daemon.
|
199
|
+
def self.save( daemon )
|
200
|
+
status_ = status( daemon )
|
201
|
+
if status_
|
202
|
+
if wait_signal_response( daemon, 'USR1', 10, 'saving.', 'saved', 0.3 )
|
203
|
+
puts "Session data saved."
|
204
|
+
else
|
205
|
+
puts "Warning: saving timed out! Session data not saved."
|
206
|
+
end
|
207
|
+
elsif status_ == false
|
208
|
+
puts "Warning, no such process (#{pid}) running: unable to save."
|
209
|
+
elsif status_ == nil
|
210
|
+
puts "No pid file: unable to save."
|
214
211
|
else
|
215
|
-
|
212
|
+
throw "Unexpected process status: #{status_.inspect}"
|
216
213
|
end
|
217
|
-
elsif status_ == false
|
218
|
-
puts "Warning, no such process (#{pid}) running: unable to save."
|
219
|
-
elsif status_ == nil
|
220
|
-
puts "No pid file: unable to save."
|
221
|
-
else
|
222
|
-
throw "Unexpected process status: #{status_.inspect}"
|
223
214
|
end
|
224
|
-
end
|
225
215
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
216
|
+
# Sends the TERM signal to the process, which in turn
|
217
|
+
# calls the stop method of the daemon
|
218
|
+
def self.stop( daemon )#,is_restart=false)
|
219
|
+
status_ = status( daemon )
|
220
|
+
if status_
|
221
|
+
if wait_signal_response( daemon, 'TERM', 10, 'killing.', 'killed', 0.3 )
|
222
|
+
puts "RSence is terminated now."
|
223
|
+
else
|
224
|
+
puts "Warning: termination timed out!"
|
225
|
+
puts "RSence might still be running, please ensure manually."
|
226
|
+
end
|
227
|
+
elsif status_ == false
|
228
|
+
puts "Warning, no such process (#{read_pid(daemon)}) running."
|
229
|
+
elsif status_ == nil
|
230
|
+
puts "Warning, no pid file (process not running)."
|
233
231
|
else
|
234
|
-
|
235
|
-
puts "RSence might still be running, please ensure manually."
|
232
|
+
throw "Unexpected process status: #{status_.inspect}"
|
236
233
|
end
|
237
|
-
elsif status_ == false
|
238
|
-
puts "Warning, no such process (#{read_pid(daemon)}) running."
|
239
|
-
elsif status_ == nil
|
240
|
-
puts "Warning, no pid file (process not running)."
|
241
|
-
else
|
242
|
-
throw "Unexpected process status: #{status_.inspect}"
|
243
234
|
end
|
244
|
-
end
|
245
235
|
|
246
|
-
|
247
|
-
|
236
|
+
# Main entry point called from the daemon process passing +self+ as +daemon+.
|
237
|
+
def self.daemonize( daemon )
|
248
238
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
239
|
+
# Uses the command-line tool command to decide what to do.
|
240
|
+
case RSence.cmd
|
241
|
+
when :run
|
242
|
+
run( daemon )
|
243
|
+
when :start
|
244
|
+
start( daemon )
|
245
|
+
when :stop
|
246
|
+
stop( daemon )
|
247
|
+
when :restart
|
248
|
+
stop( daemon )
|
249
|
+
start( daemon )
|
250
|
+
when :save
|
251
|
+
save( daemon )
|
252
|
+
end
|
262
253
|
end
|
263
|
-
end
|
264
254
|
|
265
|
-
end
|
255
|
+
end
|
266
256
|
|
267
|
-
# Simple process control, constructed here and called from Daemon::Controller
|
268
|
-
class HTTPDaemon
|
257
|
+
# Simple process control, constructed here and called from Daemon::Controller
|
258
|
+
class HTTPDaemon
|
269
259
|
|
270
|
-
|
271
|
-
|
272
|
-
puts "Press CTRL-C to terminate."
|
260
|
+
# RSence top-level run handler. Almost identical to start.
|
261
|
+
def run
|
273
262
|
|
274
|
-
|
263
|
+
puts "Starting as a foreground process." if RSence.args[:verbose]
|
264
|
+
puts "Press CTRL-C to terminate."
|
275
265
|
|
276
|
-
|
266
|
+
@transporter = Transporter.new
|
277
267
|
|
278
|
-
|
279
|
-
Daemon.start_logging( self )
|
280
|
-
end
|
268
|
+
conf = RSence.config[:http_server]
|
281
269
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
conf[:rack_handler],
|
286
|
-
conf[:bind_address],
|
287
|
-
conf[:port]
|
288
|
-
)
|
270
|
+
unless RSence.args[:log_fg]
|
271
|
+
Daemon.start_logging( self )
|
272
|
+
end
|
289
273
|
|
290
|
-
|
274
|
+
# This is the main http handler instance:
|
275
|
+
@broker = Broker.start(
|
276
|
+
@transporter,
|
277
|
+
conf
|
278
|
+
)
|
279
|
+
|
280
|
+
end
|
291
281
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
282
|
+
# Returns the pid file path.
|
283
|
+
def pid_fn
|
284
|
+
RSence.config[:daemon][:pid_fn]
|
285
|
+
end
|
296
286
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
287
|
+
# Returns the log path.
|
288
|
+
def log_fn
|
289
|
+
RSence.config[:daemon][:log_fn]
|
290
|
+
end
|
301
291
|
|
302
|
-
|
303
|
-
|
304
|
-
|
292
|
+
# Returns the configured bind address
|
293
|
+
def addr
|
294
|
+
RSence.config[:http_server][:bind_address]
|
295
|
+
end
|
305
296
|
|
306
|
-
|
307
|
-
|
308
|
-
|
297
|
+
# Returns the configured port.
|
298
|
+
def port
|
299
|
+
RSence.config[:http_server][:port]
|
300
|
+
end
|
309
301
|
|
310
|
-
|
311
|
-
|
302
|
+
# Called by Controller#start, contains RSence-specific operations
|
303
|
+
def start
|
312
304
|
|
313
|
-
|
305
|
+
@transporter = Transporter.new
|
314
306
|
|
315
|
-
|
307
|
+
conf = RSence.config[:http_server]
|
316
308
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
309
|
+
unless RSence.args[:log_fg]
|
310
|
+
Daemon.start_logging( self )
|
311
|
+
STDIN.reopen( "/dev/null" )
|
312
|
+
end
|
321
313
|
|
322
|
-
|
314
|
+
Process.setsid
|
323
315
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
)
|
331
|
-
yield @broker
|
316
|
+
# This is the main http handler instance:
|
317
|
+
@broker = Broker.start(
|
318
|
+
@transporter,
|
319
|
+
conf
|
320
|
+
)
|
321
|
+
yield @broker
|
332
322
|
|
333
|
-
|
323
|
+
end
|
334
324
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
325
|
+
# Called by Controller#stop, contains RSence-specific operations
|
326
|
+
def stop
|
327
|
+
@transporter.shutdown
|
328
|
+
end
|
339
329
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
330
|
+
# Called on USR1 signals (save data)
|
331
|
+
def usr1
|
332
|
+
save
|
333
|
+
end
|
344
334
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
335
|
+
# Save state
|
336
|
+
def save
|
337
|
+
puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- Saving state..."
|
338
|
+
transporter_state = @transporter.online?
|
339
|
+
@transporter.online = false
|
340
|
+
@transporter.plugins.delegate(:flush)
|
341
|
+
@transporter.sessions.store_sessions
|
342
|
+
@transporter.online = transporter_state
|
343
|
+
puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- State saved."
|
344
|
+
end
|
355
345
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
346
|
+
# Called on USR2 signals ("Alive?")
|
347
|
+
def usr2
|
348
|
+
puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- RSence version #{RSence.version} is running."
|
349
|
+
end
|
360
350
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
351
|
+
# Main entry point, daemonizes itself using Controller.
|
352
|
+
def daemonize!
|
353
|
+
Daemon.daemonize( self )
|
354
|
+
end
|
365
355
|
|
366
|
-
end
|
367
|
-
|
356
|
+
end
|
368
357
|
end
|