marvin 0.8.0.0 → 0.8.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/marvin CHANGED
@@ -3,8 +3,9 @@ require 'rubygems'
3
3
  require File.join(File.dirname(__FILE__), "..", "lib", "marvin")
4
4
 
5
5
  Marvin::Application.processing(ARGV) do |a|
6
-
7
- a.banner = "Marvin v#{Marvin::VERSION} - An IRC Library for Ruby"
6
+ version = Marvin.version
7
+ version << "p#{Marvin::VERSION[3]}" if Marvin::VERSION[3] != 0
8
+ a.banner = "Marvin v#{version} - An IRC Library for Ruby"
8
9
 
9
10
  a.generator!
10
11
 
@@ -5,19 +5,14 @@ require 'perennial'
5
5
  module Marvin
6
6
  include Perennial
7
7
 
8
- VERSION = [0, 8, 0, 0]
8
+ VERSION = [0, 8, 0, 1]
9
9
 
10
- # Misc.
11
- #autoload :Util, 'marvin/util'
12
10
  # Client
13
- #autoload :AbstractClient, 'marvin/abstract_client'
14
- #autoload :IRC, 'marvin/irc'
15
11
  autoload :TestClient, 'marvin/test_client'
16
12
  # Console of DOOM.
17
13
  autoload :Console, 'marvin/console'
18
14
  # Distributed
19
15
  autoload :Distributed, 'marvin/distributed'
20
- autoload :Status, 'marvin/status'
21
16
  # Handler
22
17
  autoload :Base, 'marvin/base'
23
18
  autoload :CommandHandler, 'marvin/command_handler'
@@ -25,7 +20,6 @@ module Marvin
25
20
  autoload :CoreCommands, 'marvin/core_commands'
26
21
  autoload :MiddleMan, 'marvin/middle_man'
27
22
  # These should be namespaced under IRC
28
- #autoload :AbstractParser, 'marvin/abstract_parser'
29
23
  autoload :Parsers, 'marvin/parsers'
30
24
 
31
25
 
@@ -57,10 +57,7 @@ module Marvin
57
57
  end
58
58
 
59
59
  def process_development
60
- if @@development
61
- Marvin::Reloading.reload!
62
- setup_handlers
63
- end
60
+ Marvin::Reloading.reload! if @@development
64
61
  end
65
62
 
66
63
  def dispatch(*args)
@@ -76,9 +76,11 @@ module Marvin
76
76
  before = dispatcher.handlers
77
77
  register!(dispatcher)
78
78
  after = dispatcher.handlers
79
- (after - before).each { |h| h.handle(:reloaded, {}) }
79
+ (after - before).each do |h|
80
+ h.client = dispatcher
81
+ h.handle(:reloaded, {})
82
+ end
80
83
  end
81
-
82
84
  end
83
85
 
84
86
  end
@@ -8,7 +8,6 @@ module Marvin
8
8
 
9
9
  @@exposed_method_mapping = Hash.new { |h,k| h[k] = [] }
10
10
  @@method_descriptions = Hash.new { |h,k| h[k] = {} }
11
- @@registered_classes = Set.new
12
11
 
13
12
  class << self
14
13
 
@@ -48,6 +47,12 @@ module Marvin
48
47
  "#{command_prefix}#{method}"
49
48
  end
50
49
 
50
+ def reloading!
51
+ super
52
+ @@exposed_method_mapping.delete(self)
53
+ @@method_descriptions.delete(self)
54
+ end
55
+
51
56
  end
52
57
 
53
58
  on_event :incoming_message, :check_for_commands
@@ -26,13 +26,22 @@ module Marvin
26
26
  @host_with_port
27
27
  end
28
28
 
29
- def method_missing(name, *args)
29
+ def method_missing(name, *args, &blk)
30
30
  logger.debug "Proxying #{name}(#{args.inspect[1..-2]}) to #{@host_with_port}"
31
+ cb = nil
32
+ if blk.present?
33
+ cb = proc do |_, options|
34
+ if options.is_a?(Hash)
35
+ value = options.delete("return-value")
36
+ blk.call(value)
37
+ end
38
+ end
39
+ end
31
40
  @connection.send_message(:action, {
32
41
  "action" => name.to_s,
33
42
  "arguments" => args,
34
43
  "client-host" => @host_with_port
35
- })
44
+ }, &cb)
36
45
  end
37
46
 
38
47
  end
@@ -43,6 +52,7 @@ module Marvin
43
52
  register_handler_method :authentication_failed
44
53
  register_handler_method :authenticated
45
54
  register_handler_method :unauthorized
55
+ register_handler_method :welcome
46
56
 
47
57
  cattr_accessor :stopping
48
58
  self.stopping = false
@@ -60,20 +70,13 @@ module Marvin
60
70
  def post_init
61
71
  super
62
72
  logger.info "Connected to distributed server"
63
- if should_use_tls?
64
- logger.info "Attempting to initialize tls"
65
- start_tls
66
- else
67
- process_authentication
68
- end
69
73
  end
70
74
 
71
- def ssl_handshake_completed
72
- logger.info "tls handshake completed"
73
- process_authentication if should_use_tls?
75
+ def post_connect
76
+ logger.info "Connection started; processing authentication"
77
+ process_authentication
74
78
  end
75
79
 
76
-
77
80
  def unbind
78
81
  if self.stopping
79
82
  logger.info "Stopping distributed client"
@@ -91,6 +94,15 @@ module Marvin
91
94
  end
92
95
  end
93
96
 
97
+ def handle_welcome(options = {})
98
+ if should_use_ssl? && !ssl_enabled?
99
+ request_ssl!
100
+ else
101
+ @connected = true
102
+ post_connect
103
+ end
104
+ end
105
+
94
106
  def handle_event(options = {})
95
107
  event = options["event-name"]
96
108
  client_host = options["client-host"]
@@ -142,34 +154,9 @@ module Marvin
142
154
  end
143
155
  end
144
156
 
145
- protected
146
-
147
- def options_for_callback(blk)
148
- return {} if blk.blank?
149
- cb_id = "callback-#{seld.object_id}-#{Time.now.to_f}"
150
- count = 0
151
- count += 1 while @callbacks.has_key?(Digest::SHA256.hexdigest("#{cb_id}-#{count}"))
152
- final_id = Digest::SHA256.hexdigest("#{cb_id}-#{count}")
153
- @callbacks[final_id] = blk
154
- {"callback-id" => final_id}
155
- end
156
-
157
- def process_callback(hash)
158
- if hash.is_a?(Hash) && hash.has_key?("callback-id")
159
- callback = @callbacks.delete(hash["callback-id"])
160
- callback.call(self, hash)
161
- end
162
- end
163
-
164
- def host_with_port
165
- @host_with_port ||= begin
166
- port, ip = Socket.unpack_sockaddr_in(get_peername)
167
- "#{ip}:#{port}"
168
- end
169
- end
170
-
171
- def should_use_tls?
172
- @using_tls ||= configuration.encrypted?
157
+ def request_ssl!
158
+ logger.info "Requesting SSL for Distributed Client"
159
+ send_message(:enable_ssl) unless ssl_enabled?
173
160
  end
174
161
 
175
162
  end
@@ -2,7 +2,6 @@ module Marvin
2
2
  module Distributed
3
3
  class Handler < Marvin::Base
4
4
 
5
-
6
5
  EVENT_WHITELIST = [:incoming_message, :incoming_action]
7
6
  QUEUE_PROCESSING_SPACING = 3
8
7
 
@@ -32,11 +32,19 @@ module Marvin
32
32
  send_data "#{payload}\n"
33
33
  end
34
34
 
35
+ def send_message_reply(name, arguments = {})
36
+ arguments["callback-id"] = @callback_id if @callback_id.present?
37
+ send_message(name, arguments)
38
+ end
39
+
35
40
  def handle_response(response)
36
- logger.debug "Handling response in distributed protocol (response => #{response.inspect})"
41
+ logger.debug "Handling response in distributed protocol (response: #{response.inspect})"
37
42
  return unless response.is_a?(Hash) && response.has_key?("message")
38
43
  options = response["options"] || {}
44
+ @callback_id = response.delete("callback-id")
45
+ process_callback(options)
39
46
  process_response_message(response["message"], options)
47
+ @callback_id = nil
40
48
  end
41
49
 
42
50
  def host_with_port
@@ -46,11 +54,52 @@ module Marvin
46
54
  end
47
55
  end
48
56
 
57
+ def handle_enable_ssl(opts = {})
58
+ send_message_reply(:enabled_ssl)
59
+ enable_ssl
60
+ end
61
+
62
+ def handle_enabled_ssl(opts = {})
63
+ enable_ssl
64
+ end
65
+
66
+ def handle_noop(opts = {})
67
+ # DO NOTHING.
68
+ logger.debug "no-op"
69
+ end
70
+
71
+ # After the connection is made and / or ssl is enabled.
72
+ def post_connect
73
+ end
74
+
75
+ def ssl_handshake_completed
76
+ logger.debug "SSL Handshake completed"
77
+ if !connected?
78
+ @connected = true
79
+ post_connect
80
+ end
81
+ end
82
+
49
83
  protected
50
84
 
85
+ def should_use_ssl?
86
+ @should_use_ssl ||= configuration.ssl?
87
+ end
88
+
89
+ def ssl_enabled?
90
+ instance_variable_defined?(:@ssl_enabled) && @ssl_enabled
91
+ end
92
+
93
+ def enable_ssl
94
+ return if ssl_enabled?
95
+ logger.debug "Enabling SSL"
96
+ start_tls
97
+ @ssl_enabled = true
98
+ end
99
+
51
100
  def options_for_callback(blk)
52
101
  return {} if blk.blank?
53
- cb_id = "callback-#{seld.object_id}-#{Time.now.to_f}"
102
+ cb_id = "callback-#{self.object_id}-#{Time.now.to_f}"
54
103
  count = 0
55
104
  count += 1 while @callbacks.has_key?(Digest::SHA256.hexdigest("#{cb_id}-#{count}"))
56
105
  final_id = Digest::SHA256.hexdigest("#{cb_id}-#{count}")
@@ -63,7 +112,7 @@ module Marvin
63
112
  @callbacks ||= {}
64
113
  if hash.is_a?(Hash) && hash.has_key?("callback-id")
65
114
  callback = @callbacks.delete(hash["callback-id"])
66
- callback.call(self, hash)
115
+ callback.call(self, hash) if callback.present?
67
116
  end
68
117
  end
69
118
 
@@ -83,6 +132,15 @@ module Marvin
83
132
  self.handler_methods[name] = method
84
133
  end
85
134
 
135
+ # Default Handlers
136
+ register_handler_method :enable_ssl
137
+ register_handler_method :enabled_ssl
138
+ register_handler_method :noop
139
+
140
+ def connected?
141
+ instance_variable_defined?(:@connected) && @connected
142
+ end
143
+
86
144
  end
87
145
  end
88
146
  end
@@ -16,7 +16,7 @@ module Marvin
16
16
  self.free_connections = []
17
17
  self.action_whitelist = [:nick, :pong, :action, :msg, :quit, :part, :join, :command]
18
18
 
19
- attr_accessor :processing, :configuration, :using_tls
19
+ attr_accessor :processing, :configuration
20
20
 
21
21
  def initialize(*args)
22
22
  @configuration = args.last.is_a?(Marvin::Nash) ? args.pop : Marvin::nash.new
@@ -24,18 +24,20 @@ module Marvin
24
24
  end
25
25
 
26
26
  def post_init
27
- super
28
27
  @callbacks = {}
29
28
  logger.info "Got distributed client connection with #{self.host_with_port}"
30
- if should_use_tls?
31
- start_tls
29
+ if should_use_ssl?
30
+ handle_enable_ssl
32
31
  else
33
- complete_processing
32
+ @connected = true
33
+ post_connect
34
34
  end
35
35
  end
36
36
 
37
- def ssl_handshake_completed
38
- complete_processing if should_use_tls?
37
+ def post_connect
38
+ logger.debug "Remote client available, welcoming"
39
+ send_message(:welcome)
40
+ complete_processing
39
41
  end
40
42
 
41
43
  def unbind
@@ -84,14 +86,17 @@ module Marvin
84
86
  def handle_action(options = {})
85
87
  return if fails_auth!
86
88
  logger.debug "Handling action from on #{self.host_with_port}"
87
- server = lookup_client_for(options["client-host"])
89
+ target = lookup_client_for(options["client-host"])
88
90
  action = options["action"]
89
91
  arguments = [*options["arguments"]]
90
- return if server.blank? || action.blank?
92
+ return if target.blank? || action.blank?
91
93
  begin
92
94
  a = action.to_sym
93
- if self.action_whitelist.include?(a)
94
- server.send(a, *arguments) if server.respond_to?(a)
95
+ if self.action_whitelist.include?(a) && target.respond_to?(a)
96
+ res = target.send(a, *arguments)
97
+ if @callback_id.present? && res.respond_to?(:to_json)
98
+ send_message_reply(:noop, {"return-value" => res.to_json})
99
+ end
95
100
  else
96
101
  logger.warn "Client attempted invalid action #{a.inspect}"
97
102
  end
@@ -123,10 +128,6 @@ module Marvin
123
128
  @authenticated ||= false
124
129
  end
125
130
 
126
- def should_use_tls?
127
- @using_tls ||= configuration.encrypted?
128
- end
129
-
130
131
  def fails_auth!
131
132
  if requires_auth?
132
133
  logger.debug "Authentication missing for distributed client"
@@ -103,8 +103,10 @@ module Marvin::IRC
103
103
  EventMachine.kqueue
104
104
  EventMachine.epoll
105
105
  EventMachine.run do
106
- connections.each_pair do |server, configuration|
107
- connect(configuration.merge(:server => server.to_s))
106
+ unless connections.data == false
107
+ connections.each_pair do |server, configuration|
108
+ connect(configuration.merge(:server => server.to_s))
109
+ end
108
110
  end
109
111
  Marvin::Distributed::Server.start if Marvin::Distributed::Handler.registered?
110
112
  @@stopped = false
@@ -21,20 +21,23 @@ module Marvin
21
21
  end
22
22
  end
23
23
 
24
- on_event :client_connected do
25
- @server = self.client.host_with_port
26
- @nick = self.client.nickname
27
- setup_logging
28
- end
24
+ on_event :client_connected, :presetup_logging
25
+ on_event :client_connected, :setup_logging
26
+ on_event :reloaded, :presetup_logging
27
+ on_event :reloaded, :setup_logging
29
28
 
30
- on_event :client_disconnected do
31
- teardown_logging
32
- end
29
+ on_event :client_disconnected, :teardown_logging
30
+ on_event :reloaded, :teardown_logging
33
31
 
34
32
  on_event :outgoing_nick do
35
33
  @nick = options.new_nick
36
34
  end
37
35
 
36
+ def presetup_logging
37
+ @server = self.client.host_with_port
38
+ @nick = self.client.nickname
39
+ end
40
+
38
41
  # Called when the client connects, over ride it to
39
42
  # do any of your specific setup.
40
43
  def setup_logging
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marvin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0.0
4
+ version: 0.8.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darcy Laycock
@@ -10,27 +10,27 @@ bindir: bin
10
10
  cert_chain: []
11
11
 
12
12
  date: 2009-09-25 00:00:00 +08:00
13
- default_executable:
13
+ default_executable: marvin
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: Sutto-perennial
16
+ name: perennial
17
17
  type: :runtime
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.2.4.6
23
+ version: 1.0.0.0
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
- name: eventmachine-eventmachine
26
+ name: eventmachine
27
27
  type: :runtime
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.12.9
33
+ version: 0.12.8
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: json
@@ -42,10 +42,16 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  version: "0"
44
44
  version:
45
- description:
45
+ description: |-
46
+ Marvin is a library (also usable in framework / application form) that
47
+ makes it simple and fast to build applications around IRC. With an emphasis
48
+ on making common tasks (e.g. replies, bots using method call style syntax
49
+ and the like) easy, whilst still making it possible to do more complex thing
50
+ (1 connection, N worker processes, Multiple servers, etc) it aims to make
51
+ working with IRC in an evented fashion fun and easy for all rubyists.
46
52
  email: sutto@sutto.net
47
- executables: []
48
-
53
+ executables:
54
+ - marvin
49
55
  extensions: []
50
56
 
51
57
  extra_rdoc_files: []
@@ -131,6 +137,6 @@ rubyforge_project:
131
137
  rubygems_version: 1.3.2
132
138
  signing_key:
133
139
  specification_version: 3
134
- summary: Evented IRC Library of Doom
140
+ summary: Evented IRC Library for Ruby, built on EventMachine and Perennial.
135
141
  test_files: []
136
142