jicksta-adhearsion 0.7.999

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.
Files changed (107) hide show
  1. data/CHANGELOG +6 -0
  2. data/EVENTS +11 -0
  3. data/LICENSE +456 -0
  4. data/README.txt +5 -0
  5. data/Rakefile +120 -0
  6. data/adhearsion.gemspec +146 -0
  7. data/app_generators/ahn/USAGE +5 -0
  8. data/app_generators/ahn/ahn_generator.rb +87 -0
  9. data/app_generators/ahn/templates/.ahnrc +34 -0
  10. data/app_generators/ahn/templates/README +8 -0
  11. data/app_generators/ahn/templates/Rakefile +23 -0
  12. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  13. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  14. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  15. data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
  16. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  17. data/app_generators/ahn/templates/components/restful_rpc/README.markdown +11 -0
  18. data/app_generators/ahn/templates/components/restful_rpc/config.yml +34 -0
  19. data/app_generators/ahn/templates/components/restful_rpc/example-client.rb +48 -0
  20. data/app_generators/ahn/templates/components/restful_rpc/restful_rpc.rb +87 -0
  21. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +56 -0
  22. data/app_generators/ahn/templates/config/startup.rb +53 -0
  23. data/app_generators/ahn/templates/dialplan.rb +3 -0
  24. data/app_generators/ahn/templates/events.rb +32 -0
  25. data/bin/ahn +28 -0
  26. data/bin/ahnctl +68 -0
  27. data/bin/jahn +42 -0
  28. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  29. data/lib/adhearsion/cli.rb +223 -0
  30. data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
  31. data/lib/adhearsion/component_manager.rb +208 -0
  32. data/lib/adhearsion/events_support.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +9 -0
  34. data/lib/adhearsion/foundation/blank_slate.rb +5 -0
  35. data/lib/adhearsion/foundation/custom_daemonizer.rb +45 -0
  36. data/lib/adhearsion/foundation/event_socket.rb +203 -0
  37. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  38. data/lib/adhearsion/foundation/global.rb +1 -0
  39. data/lib/adhearsion/foundation/metaprogramming.rb +17 -0
  40. data/lib/adhearsion/foundation/numeric.rb +13 -0
  41. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  42. data/lib/adhearsion/foundation/relationship_properties.rb +42 -0
  43. data/lib/adhearsion/foundation/string.rb +26 -0
  44. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  45. data/lib/adhearsion/foundation/thread_safety.rb +7 -0
  46. data/lib/adhearsion/host_definitions.rb +67 -0
  47. data/lib/adhearsion/initializer/asterisk.rb +81 -0
  48. data/lib/adhearsion/initializer/configuration.rb +254 -0
  49. data/lib/adhearsion/initializer/database.rb +49 -0
  50. data/lib/adhearsion/initializer/drb.rb +31 -0
  51. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  52. data/lib/adhearsion/initializer/rails.rb +40 -0
  53. data/lib/adhearsion/initializer.rb +373 -0
  54. data/lib/adhearsion/logging.rb +92 -0
  55. data/lib/adhearsion/tasks/database.rb +5 -0
  56. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  57. data/lib/adhearsion/tasks/generating.rb +20 -0
  58. data/lib/adhearsion/tasks/lint.rb +4 -0
  59. data/lib/adhearsion/tasks/testing.rb +37 -0
  60. data/lib/adhearsion/tasks.rb +16 -0
  61. data/lib/adhearsion/version.rb +9 -0
  62. data/lib/adhearsion/voip/asterisk/agi_server.rb +81 -0
  63. data/lib/adhearsion/voip/asterisk/commands.rb +1284 -0
  64. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  65. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  66. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  67. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  68. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  69. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
  70. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
  71. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  72. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  73. data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
  74. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  75. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  76. data/lib/adhearsion/voip/asterisk.rb +4 -0
  77. data/lib/adhearsion/voip/call.rb +440 -0
  78. data/lib/adhearsion/voip/call_routing.rb +64 -0
  79. data/lib/adhearsion/voip/commands.rb +9 -0
  80. data/lib/adhearsion/voip/constants.rb +39 -0
  81. data/lib/adhearsion/voip/conveniences.rb +18 -0
  82. data/lib/adhearsion/voip/dial_plan.rb +218 -0
  83. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  84. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  85. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  86. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  87. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +71 -0
  88. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  89. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  90. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  91. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  92. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  93. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  94. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  95. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  96. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  97. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  98. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  99. data/lib/adhearsion.rb +37 -0
  100. data/lib/theatre/README.markdown +64 -0
  101. data/lib/theatre/callback_definition_loader.rb +84 -0
  102. data/lib/theatre/guid.rb +23 -0
  103. data/lib/theatre/invocation.rb +121 -0
  104. data/lib/theatre/namespace_manager.rb +153 -0
  105. data/lib/theatre/version.rb +2 -0
  106. data/lib/theatre.rb +151 -0
  107. metadata +177 -0
@@ -0,0 +1,26 @@
1
+ class String
2
+
3
+ def unindent
4
+ gsub(/^\s*/,'')
5
+ end
6
+
7
+ def unindent!
8
+ gsub!(/^\s*/,'')
9
+ end
10
+
11
+ def self.random_char
12
+ case random_digit = rand(62)
13
+ when 0...10 : random_digit.to_s
14
+ when 10...36 : (random_digit + 55).chr
15
+ when 36...62 : (random_digit + 61).chr
16
+ end
17
+ end
18
+
19
+ def self.random(length_of_string=8)
20
+ Array.new(length_of_string) { random_char }.join
21
+ end
22
+
23
+ def nameify() downcase.gsub(/[^\w]/, '') end
24
+ def nameify!() replace nameify end
25
+
26
+ end
@@ -0,0 +1,96 @@
1
+ ##
2
+ # Implementation of a Thread-safe Hash. Works by delegating methods to a Hash behind-the-scenes after obtaining an exclusive # lock. Use exactly as you would a normal Hash.
3
+ #
4
+ class SynchronizedHash
5
+
6
+ def self.atomically_delegate(method_name)
7
+ class_eval(<<-RUBY, __FILE__, __LINE__)
8
+ def #{method_name}(*args, &block)
9
+ @lock.synchronize do
10
+ @delegate.send(#{method_name.inspect}, *args, &block)
11
+ end
12
+ end
13
+ RUBY
14
+ end
15
+
16
+ # Hash-related methods
17
+
18
+ atomically_delegate :[]
19
+ atomically_delegate :[]=
20
+ atomically_delegate :all?
21
+ atomically_delegate :any?
22
+ atomically_delegate :clear
23
+ atomically_delegate :collect
24
+ atomically_delegate :default
25
+ atomically_delegate :default=
26
+ atomically_delegate :delete
27
+ atomically_delegate :delete_if
28
+ atomically_delegate :detect
29
+ atomically_delegate :each
30
+ atomically_delegate :each_key
31
+ atomically_delegate :each_pair
32
+ atomically_delegate :each_value
33
+ atomically_delegate :each_with_index
34
+ atomically_delegate :empty?
35
+ atomically_delegate :entries
36
+ atomically_delegate :fetch
37
+ atomically_delegate :find
38
+ atomically_delegate :find_all
39
+ atomically_delegate :grep
40
+ atomically_delegate :has_key?
41
+ atomically_delegate :has_value?
42
+ atomically_delegate :include?
43
+ atomically_delegate :index
44
+ atomically_delegate :indexes
45
+ atomically_delegate :indices
46
+ atomically_delegate :inject
47
+ atomically_delegate :invert
48
+ atomically_delegate :key?
49
+ atomically_delegate :keys
50
+ atomically_delegate :length
51
+ atomically_delegate :map
52
+ atomically_delegate :max
53
+ atomically_delegate :member?
54
+ atomically_delegate :merge
55
+ atomically_delegate :merge!
56
+ atomically_delegate :min
57
+ atomically_delegate :partition
58
+ atomically_delegate :rehash
59
+ atomically_delegate :reject
60
+ atomically_delegate :reject!
61
+ atomically_delegate :replace
62
+ atomically_delegate :select
63
+ atomically_delegate :shift
64
+ atomically_delegate :size
65
+ atomically_delegate :sort
66
+ atomically_delegate :sort_by
67
+ atomically_delegate :store
68
+ atomically_delegate :to_hash
69
+ atomically_delegate :update
70
+ atomically_delegate :value?
71
+ atomically_delegate :values
72
+ atomically_delegate :values_at
73
+ atomically_delegate :zip
74
+
75
+ # Object-related methods
76
+
77
+ atomically_delegate :inspect
78
+ atomically_delegate :to_s
79
+ atomically_delegate :marshal_dump
80
+
81
+ def initialize(*args, &block)
82
+ @delegate = Hash.new(*args, &block)
83
+ @lock = Mutex.new
84
+ end
85
+
86
+ ##
87
+ # If you need to do many operations atomically (a la transaction), you can call this method and access the yielded Hash
88
+ # which can be safely modified for the duration of your block.
89
+ #
90
+ # @yield [Hash] the Hash on which you can safely operate during your block.
91
+ #
92
+ def with_lock(&block)
93
+ @lock.synchronize { yield @delegate }
94
+ end
95
+
96
+ end
@@ -0,0 +1,7 @@
1
+ require 'thread'
2
+ class Object
3
+ def synchronize(&block)
4
+ @mutex ||= Mutex.new
5
+ @mutex.synchronize &block
6
+ end
7
+ end
@@ -0,0 +1,67 @@
1
+ require 'yaml'
2
+
3
+ module Adhearsion
4
+
5
+ ##
6
+ # This class isn't yet tied into Adhearsion.
7
+ #
8
+ class HostDefinition
9
+
10
+ SUPPORTED_KEYS = [:host, :username, :password, :key, :name]
11
+
12
+ cattr_reader :definitions
13
+ @@definitions ||= []
14
+
15
+ class << self
16
+ def import_from_data_structure(local_definitions)
17
+ case local_definitions
18
+ when Array
19
+ local_definitions.each do |definition|
20
+ raise HostDefinitionException, "Unrecognized definition: #{definition}" unless definition.is_a?(Hash)
21
+ end
22
+ local_definitions.map { |definition| new definition }
23
+ when Hash
24
+ local_definitions.map do |(name,definition)|
25
+ new definition.merge(:name => name)
26
+ end
27
+ else
28
+ raise HostDefinitionException, "Unrecognized definition #{local_definitions}"
29
+ end
30
+ end
31
+
32
+ def import_from_yaml(yaml_string)
33
+ import_from_data_structure YAML.load(yaml_string)
34
+ end
35
+
36
+ def import_from_yaml_file(file)
37
+ import_from_yaml YAML.load_file(file)
38
+ end
39
+
40
+ def clear_definitions!
41
+ definitions.clear
42
+ end
43
+ end
44
+
45
+ attr_reader :name, :host, :username, :password, :key
46
+ def initialize(hash)
47
+ @host, @username, @password, @key, @name = hash.values_at(*SUPPORTED_KEYS)
48
+ @name ||= new_guid
49
+
50
+ unrecognized_keys = hash.keys - SUPPORTED_KEYS
51
+ raise HostDefinitionException, "Unrecognized key(s): #{unrecognized_keys.map(&:inspect).to_sentence}" if unrecognized_keys.any?
52
+ raise HostDefinitionException, "You must supply a password or key!" if username && !(password || key)
53
+ raise HostDefinitionException, "You must supply a username!" unless username
54
+ raise HostDefinitionException, 'You cannot supply both a password and key!' if password && key
55
+ raise HostDefinitionException, 'You must supply a host!' unless host
56
+
57
+ self.class.definitions << self
58
+ end
59
+
60
+ class HostDefinitionException < Exception
61
+
62
+ end
63
+
64
+ end
65
+
66
+
67
+ end
@@ -0,0 +1,81 @@
1
+ require 'adhearsion/voip/asterisk'
2
+ module Adhearsion
3
+ class Initializer
4
+
5
+ class AsteriskInitializer
6
+
7
+ cattr_accessor :config, :agi_server, :ami_client
8
+ class << self
9
+
10
+ def start
11
+ self.config = AHN_CONFIG.asterisk
12
+ self.agi_server = initialize_agi
13
+ self.ami_client = VoIP::Asterisk.manager_interface = initialize_ami if config.ami_enabled?
14
+ join_server_thread_after_initialized
15
+ end
16
+
17
+ def stop
18
+ agi_server.stop
19
+ ami_client.disconnect! if ami_client
20
+ end
21
+
22
+ private
23
+
24
+ def initialize_agi
25
+ VoIP::Asterisk::AGI::Server.new :host => config.listening_host,
26
+ :port => config.listening_port
27
+ end
28
+
29
+ def initialize_ami
30
+ options = ami_options
31
+ start_ami_after_initialized
32
+ returning VoIP::Asterisk::Manager::ManagerInterface.new(options) do
33
+ class << VoIP::Asterisk
34
+ if respond_to?(:manager_interface)
35
+ ahn_log.warn "Asterisk.manager_interface already initialized?"
36
+ else
37
+ def manager_interface
38
+ # ahn_log.ami.warn "Warning! This Asterisk.manager_interface() notation is for Adhearsion version 0.8.0 only. Subsequent versions of Adhearsion will use a feature called SuperManager. Migrating to use SuperManager will be very simple. See http://docs.adhearsion.com/AMI for more information."
39
+ Adhearsion::Initializer::AsteriskInitializer.ami_client
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ def ami_options
47
+ %w(host port username password events).inject({}) do |options, property|
48
+ options[property.to_sym] = config.ami.send property
49
+ options
50
+ end
51
+ end
52
+
53
+ def join_server_thread_after_initialized
54
+ Events.register_callback(:after_initialized) do
55
+ begin
56
+ agi_server.start
57
+ rescue => e
58
+ ahn_log.fatal "Failed to start AGI server! #{e.inspect}"
59
+ abort
60
+ end
61
+ end
62
+ IMPORTANT_THREADS << agi_server
63
+ end
64
+
65
+ def start_ami_after_initialized
66
+ Events.register_callback(:after_initialized) do
67
+ begin
68
+ self.ami_client.connect!
69
+ rescue Errno::ECONNREFUSED
70
+ ahn_log.ami.error "Connection refused when connecting to AMI! Please check your configuration."
71
+ rescue => e
72
+ ahn_log.ami.error "Error connecting to AMI! #{e.inspect}"
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,254 @@
1
+ module Adhearsion
2
+ class Configuration
3
+ module ConfigurationEntryPoint
4
+ def add_configuration_for(name)
5
+ configuration_class_name = "#{name}Configuration"
6
+ lowercased_name = name.to_s.underscore
7
+
8
+ class_eval(<<-EVAL, __FILE__, __LINE__)
9
+ def enable_#{lowercased_name}(configuration_options = {})
10
+ @#{lowercased_name}_configuration = #{configuration_class_name}.new(configuration_options)
11
+ end
12
+
13
+ def #{lowercased_name}
14
+ @#{lowercased_name}_configuration
15
+ end
16
+
17
+ def #{lowercased_name}_enabled?
18
+ !#{lowercased_name}.nil?
19
+ end
20
+ EVAL
21
+ end
22
+ end
23
+ extend ConfigurationEntryPoint
24
+
25
+ class << self
26
+ def configure(&block)
27
+ if Adhearsion.const_defined?(:AHN_CONFIG)
28
+ yield AHN_CONFIG if block_given?
29
+ else
30
+ Adhearsion.const_set(:AHN_CONFIG, new(&block))
31
+ end
32
+ end
33
+ end
34
+
35
+ attr_accessor :automatically_answer_incoming_calls
36
+ attr_accessor :end_call_on_hangup
37
+ attr_accessor :end_call_on_error
38
+
39
+ def initialize
40
+ @automatically_answer_incoming_calls = true
41
+ @end_call_on_hangup = true
42
+ @end_call_on_error = true
43
+ yield self if block_given?
44
+ end
45
+
46
+ def ahnrc
47
+ @ahnrc
48
+ end
49
+
50
+ ##
51
+ # Load the contents of an .ahnrc file into this Configuration.
52
+ #
53
+ # @param [String, Hash] ahnrc String of YAML .ahnrc data or a Hash of the pre-loaded YAML data structure
54
+ #
55
+ def ahnrc=(new_ahnrc)
56
+ case new_ahnrc
57
+ when Hash
58
+ @raw_ahnrc = new_ahnrc.to_yaml.freeze
59
+ @ahnrc = new_ahnrc.clone.freeze
60
+ when String
61
+ @raw_ahnrc = new_ahnrc.clone.freeze
62
+ @ahnrc = YAML.load(new_ahnrc).freeze
63
+ end
64
+ end
65
+
66
+ def logging(options)
67
+ Adhearsion::Logging.logging_level = options[:level]
68
+ end
69
+
70
+ ##
71
+ # Adhearsion's .ahnrc file is used to define paths to certain parts of the framework. For example, the name dialplan.rb
72
+ # is actually specified in .ahnrc. This file can actually be just a filename, a filename with a glob (.e.g "*.rb"), an
73
+ # Array of filenames or even an Array of globs.
74
+ #
75
+ # @param [String,Array] String segments which convey the nesting of Hash keys through .ahnrc
76
+ # @raise [RuntimeError] If ahnrc has not been set yet with #ahnrc=()
77
+ # @raise [NameError] If the path through the ahnrc is invalid
78
+ #
79
+ def files_from_setting(*path_through_config)
80
+ raise RuntimeError, "No ahnrc has been set yet!" unless @ahnrc
81
+ queried_nested_setting = path_through_config.flatten.inject(@ahnrc) do |hash,key_name|
82
+ if hash.kind_of?(Hash) && hash.has_key?(key_name)
83
+ hash[key_name]
84
+ else
85
+ raise NameError, "Paths #{path_through_config.inspect} not found in .ahnrc!"
86
+ end
87
+ end
88
+ raise NameError, "Paths #{path_through_config.inspect} not found in .ahnrc!" unless queried_nested_setting
89
+ queried_nested_setting = Array queried_nested_setting
90
+ queried_nested_setting.map { |filename| files_from_glob(filename) }.flatten.uniq
91
+ end
92
+
93
+ private
94
+
95
+ def files_from_glob(glob)
96
+ Dir.glob "#{AHN_ROOT}/#{glob}"
97
+ end
98
+
99
+ class AbstractConfiguration
100
+ extend ConfigurationEntryPoint
101
+
102
+ class << self
103
+ private
104
+ def abstract_method!
105
+ raise "Must be implemented in subclasses"
106
+ end
107
+ end
108
+
109
+ def initialize(overrides = {})
110
+ overrides.each_pair do |attribute, value|
111
+ send("#{attribute}=", value)
112
+ end
113
+ end
114
+ end
115
+
116
+ # Abstract superclass for AsteriskConfiguration and FreeSwitchConfiguration.
117
+ class TelephonyPlatformConfiguration < AbstractConfiguration
118
+ attr_accessor :listening_port
119
+ attr_accessor :listening_host
120
+
121
+ class << self
122
+ def default_listening_port
123
+ abstract_method!
124
+ end
125
+
126
+ def default_listening_host
127
+ '0.0.0.0'
128
+ end
129
+ end
130
+
131
+ def initialize(overrides = {})
132
+ @listening_port = self.class.default_listening_port
133
+ @listening_host = self.class.default_listening_host
134
+ super
135
+ end
136
+ end
137
+
138
+ class AsteriskConfiguration < TelephonyPlatformConfiguration
139
+ class << self
140
+ attr_accessor :speech_engine
141
+
142
+ def default_listening_port
143
+ 4573
144
+ end
145
+ end
146
+
147
+ class AMIConfiguration < AbstractConfiguration
148
+ attr_accessor :port, :username, :password, :events, :host
149
+
150
+ class << self
151
+ def default_port
152
+ 5038
153
+ end
154
+
155
+ def default_events
156
+ false
157
+ end
158
+
159
+ def default_host
160
+ 'localhost'
161
+ end
162
+ end
163
+
164
+ def initialize(overrides = {})
165
+ self.host = self.class.default_host
166
+ self.port = self.class.default_port
167
+ self.events = self.class.default_events
168
+ super
169
+ end
170
+ end
171
+ add_configuration_for :AMI
172
+ end
173
+ add_configuration_for :Asterisk
174
+
175
+ class FreeswitchConfiguration < TelephonyPlatformConfiguration
176
+ class << self
177
+ def default_listening_port
178
+ 4572
179
+ end
180
+ end
181
+ end
182
+ add_configuration_for :Freeswitch
183
+
184
+ class DatabaseConfiguration < AbstractConfiguration
185
+ attr_accessor :connection_options, :orm
186
+ def initialize(options)
187
+ @orm = options.delete(:orm) || :active_record # TODO: ORM is a misnomer
188
+ @connection_options = options
189
+ end
190
+ end
191
+ add_configuration_for :Database
192
+
193
+ class DrbConfiguration < AbstractConfiguration
194
+ attr_accessor :port
195
+ attr_accessor :host
196
+ attr_accessor :acl
197
+
198
+ # ACL = Access Control List
199
+
200
+ class << self
201
+ def default_port
202
+ 9050
203
+ end
204
+
205
+ def default_host
206
+ 'localhost'
207
+ end
208
+ end
209
+
210
+ def initialize(overrides = {})
211
+ self.port = overrides[:port] || self.class.default_port
212
+ self.host = overrides[:host] || self.class.default_host
213
+ self.acl = overrides[:raw_acl]
214
+
215
+ unless acl
216
+ self.acl = []
217
+ overrides[ :deny].to_a.each { |ip| acl << 'deny' << ip }
218
+ overrides[:allow].to_a.each { |ip| acl << 'allow' << ip }
219
+ acl.concat %w[allow 127.0.0.1] if acl.empty?
220
+ end
221
+ end
222
+ end
223
+ add_configuration_for :Drb
224
+
225
+ class RailsConfiguration < AbstractConfiguration
226
+
227
+ SUPPORTED_RAILS_ENVIRONMENTS = [:development, :test, :production]
228
+
229
+ attr_accessor :rails_root, :environment
230
+ def initialize(options)
231
+ path_to_rails, environment = check_options options
232
+ @rails_root = File.expand_path(path_to_rails)
233
+ @environment = environment.to_sym
234
+ raise ArgumentError, "Unrecognized environment type #@environment. Supported: " +
235
+ SUPPORTED_RAILS_ENVIRONMENTS.to_sentence unless SUPPORTED_RAILS_ENVIRONMENTS.include?(@environment)
236
+ end
237
+
238
+ private
239
+
240
+ def check_options(options)
241
+ options = options.clone
242
+ path = options.delete :path
243
+ env = options.delete :env
244
+ raise ArgumentError, "Unrecognied argument(s) #{options.keys.to_sentence} in Rails initializer!" unless options.size.zero?
245
+ raise ArgumentError, "Must supply an :env argument to the Rails initializer!" unless env
246
+ raise ArgumentError, "Must supply an :path argument to the Rails initializer!" unless path
247
+ [path, env]
248
+ end
249
+
250
+ end
251
+ add_configuration_for :Rails
252
+
253
+ end
254
+ end
@@ -0,0 +1,49 @@
1
+ # TODO: Have all of the initializer modules required and then traverse the subclasses, asking them if they're enabled. If they are enabled, then they should do their initialization stuff. Is this really necessary to develop this entirely new system when the components system exists?
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+
6
+ class DatabaseInitializer
7
+
8
+ class << self
9
+
10
+ def start
11
+ require_dependencies
12
+ require_models
13
+ @@config = Adhearsion::AHN_CONFIG.database
14
+ ActiveRecord::Base.allow_concurrency = true
15
+ establish_connection
16
+ create_call_hook_for_connection_cleanup
17
+ end
18
+
19
+ def stop
20
+ ActiveRecord::Base.remove_connection
21
+ end
22
+
23
+ private
24
+
25
+ def create_call_hook_for_connection_cleanup
26
+ Events.register_callback([:asterisk, :before_call]) do
27
+ ActiveRecord::Base.verify_active_connections!
28
+ end
29
+ end
30
+
31
+ def require_dependencies
32
+ require 'active_record'
33
+ end
34
+
35
+ def require_models
36
+ AHN_CONFIG.files_from_setting("paths", "models").each do |model|
37
+ load model
38
+ end
39
+ end
40
+
41
+ def establish_connection
42
+ ActiveRecord::Base.establish_connection @@config.connection_options
43
+ end
44
+
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ require 'drb'
2
+ require 'drb/acl'
3
+ require 'thread'
4
+
5
+ module Adhearsion
6
+ class Initializer
7
+
8
+ class DrbInitializer
9
+
10
+ class << self
11
+
12
+ def start
13
+ config = Adhearsion::AHN_CONFIG.drb
14
+ DRb.install_acl ACL.new(config.acl) if config.acl
15
+
16
+ drb_door = Object.new
17
+ Components.component_manager.extend_object_with(drb_door, :rpc)
18
+
19
+ DRb.start_service "druby://#{config.host}:#{config.port}", drb_door
20
+
21
+ ahn_log "Starting DRb on #{config.host}:#{config.port}"
22
+ end
23
+
24
+ def stop
25
+ DRb.stop_service
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ # THIS FREESWITCH LIBRARY HASN'T BEEN INTEGRATED INTO THE REFACTORED 0.8.0 YET.
2
+ # WHAT EXISTS HERE IS OLD, MUST BE CHANGED, AND DOES NOT EVEN GET LOADED AT THE MOMENT.
3
+ require "adhearsion/voip/freeswitch/oes_server"
4
+ require "adhearsion/voip/freeswitch/event_handler"
5
+ require "adhearsion/voip/freeswitch/inbound_connection_manager"
6
+ require "adhearsion/voip/dsl/dialplan/control_passing_exception"
7
+
8
+ oes_enabled = Adhearsion::Configuration.core.voip.freeswitch.oes && Adhearsion::Configuration.core.voip.freeswitch.oes.port
9
+
10
+
11
+ if oes_enabled
12
+
13
+ port = Adhearsion::Configuration.core.voip.freeswitch.oes.port
14
+ host = Adhearsion::Configuration.core.voip.freeswitch.oes.host
15
+
16
+ server = Adhearsion::VoIP::FreeSwitch::OesServer.new port, host
17
+
18
+ Events.register_callback(:after_initialized) { server.start }
19
+ Events.register_callback(:shutdown) { server.stop }
20
+ IMPORTANT_THREADS << server
21
+
22
+ end
@@ -0,0 +1,40 @@
1
+ require 'adhearsion/voip/asterisk'
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+ class RailsInitializer
6
+
7
+ cattr_accessor :rails_root, :config, :environment
8
+ class << self
9
+
10
+ def start
11
+ ahn_config = Adhearsion::AHN_CONFIG
12
+ self.config = ahn_config.rails
13
+ self.rails_root = config.rails_root
14
+ self.environment = config.environment
15
+ raise "You cannot enable the database and Rails at the same time!" if ahn_config.database_enabled?
16
+ raise "Error loading Rails environment in #{rails_root.inspect}. " +
17
+ "It's not a directory!" unless File.directory?(rails_root)
18
+ load_rails
19
+ if defined? ActiveRecord
20
+ ActiveRecord::Base.allow_concurrency = true
21
+ Events.register_callback([:asterisk, :before_call]) do
22
+ ActiveRecord::Base.verify_active_connections!
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def load_rails
30
+ environment_file = File.expand_path(rails_root + "/config/environment.rb")
31
+ raise "There is no config/environment.rb file!" unless File.exists?(environment_file)
32
+ ENV['RAILS_ENV'] = environment.to_s
33
+ require environment_file
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
40
+ end