Revision ecdabe95
Added by Marc Dequènes over 14 years ago
- ID ecdabe959057281f9350bbcd0735c9639206244f
README | ||
---|---|---|
|
||
Depends:
|
||
--------
|
||
liblog4r-ruby
|
||
libgettext-ruby1.8
|
||
libtmail-ruby1.8
|
||
rails
|
||
libgpgme-ruby
|
||
libactiveldap-ruby
|
||
libxmpp4r-ruby
|
||
libdaemons-ruby
|
||
common:
|
||
- liblog4r-ruby
|
||
- libgettext-ruby1.8
|
||
- libdaemons-ruby
|
||
- libeventmachine-ruby
|
||
- libxmpp4r-ruby (if using XMPP backend)
|
||
Postman:
|
||
- libtmail-ruby1.8
|
||
- rails
|
||
- libgpgme-ruby
|
||
MapMaker:
|
||
Librarian:
|
||
- libactiveldap-ruby
|
||
|
bin/mapmaker | ||
---|---|---|
#!/usr/bin/ruby -Ku
|
||
|
||
#--
|
||
# CyborgHood, a distributed system management software.
|
||
# Copyright (c) 2009-2010 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
# to allow in-place run for test
|
||
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
||
|
||
require 'cyborghood/cyborg'
|
||
|
||
|
||
module CyborgHood
|
||
class Config
|
||
protected
|
||
class MapMakerValidator < CyborgHoodValidator
|
||
def validate_hook_in(value, rule, path, msg_list)
|
||
case rule.name
|
||
when 'MasterZonePattern'
|
||
if value.gsub('#ZONE#', 'test') == value
|
||
msg_list << "pattern is constant"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
module MapMakerHome
|
||
include I18nTranslation
|
||
bindtextdomain("cyborghood_mapmaker", {:path => Config::L10N_DIR, :charset => "UTF-8"})
|
||
|
||
class MapMaker < Cyborg
|
||
end
|
||
end
|
||
end
|
||
|
||
bot = CyborgHood::MapMakerHome::MapMaker.new
|
||
|
||
trap('INT') do
|
||
bot.ask_to_stop
|
||
end
|
||
trap('TERM') do
|
||
bot.ask_to_stop
|
||
end
|
||
|
||
bot.run
|
bin/mapmaker_daemon | ||
---|---|---|
#!/usr/bin/ruby
|
||
|
||
#--
|
||
# CyborgHood, a distributed system management software.
|
||
# Copyright (c) 2009-2010 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
# to allow in-place run for test
|
||
$: << File.join(File.dirname(__FILE__), "..", "lib")
|
||
|
||
require 'daemons'
|
||
require 'cyborghood/base/config_setup'
|
||
|
||
options = {
|
||
:app_name => "CyborgHood_MapMaker",
|
||
:dir_mode => :normal,
|
||
:dir => CyborgHood::Config::RUN_DIR,
|
||
:multiple => false,
|
||
:mode => :exec,
|
||
:monitor => true
|
||
}
|
||
# deactivated: monitor process not stopped when program is asked to stop
|
||
# :backtrace => true,
|
||
Daemons.run(File.join(CyborgHood::Config::BIN_DIR, 'mapmaker'), options)
|
data/cyborghood/default_config/global.yaml | ||
---|---|---|
flags: []
|
||
contact: {}
|
||
i18n: {}
|
||
botnet:
|
||
connection_type: unix_socket
|
||
params: {}
|
||
ldap:
|
||
host: localhost
|
||
port: 389
|
data/cyborghood/default_config/mapmaker.yaml | ||
---|---|---|
---
|
||
dns: {}
|
data/cyborghood/default_config/postman.yaml | ||
---|---|---|
smtp_server: localhost
|
||
smtp_port: 25
|
||
max_drift_time: 3600
|
||
dns: {}
|
data/cyborghood/schema/global.yaml | ||
---|---|---|
type: seq
|
||
sequence:
|
||
- type: str
|
||
"botnet":
|
||
type: map
|
||
mapping:
|
||
"connection_type": {type: str, enum: [unix_socket]}
|
||
"params":
|
||
type: map
|
||
mapping:
|
||
=:
|
||
type: any
|
||
# temporary location
|
||
"ldap":
|
||
type: map
|
data/cyborghood/schema/mapmaker.yaml | ||
---|---|---|
---
|
||
type: map
|
||
mapping:
|
||
"dns":
|
||
type: map
|
||
mapping:
|
||
"master_zone_pattern": {type: str, required: yes, name: MasterZonePattern}
|
data/cyborghood/schema/postman.yaml | ||
---|---|---|
"key_id": {type: str, required: yes}
|
||
"key_passphrase": {type: str, required: yes}
|
||
"max_drift_time": {type: int}
|
||
"dns":
|
||
type: map
|
||
mapping:
|
||
"master_zone_pattern": {type: str, required: yes}
|
lib/cyborghood/base/config.rb | ||
---|---|---|
config = merge_into_default_config(config, spc_config)
|
||
end
|
||
|
||
config['bot_name'] = name
|
||
|
||
# create config object for easier access
|
||
@@config = config.to_ostruct.freeze
|
||
end
|
||
... | ... | |
if name.nil?
|
||
filename = CONFFILE_GLOBAL
|
||
else
|
||
filename = CONFFILE_BOT % name
|
||
filename = CONFFILE_BOT % name.downcase
|
||
end
|
||
filepath = File.join(File.expand_path(CFG_DIR), filename)
|
||
File.read(filepath)
|
||
... | ... | |
when 'global'
|
||
GlobalValidator
|
||
else
|
||
klass_name = type.capitalize + "Validator"
|
||
klass_name = type + "Validator"
|
||
if self.const_defined? klass_name
|
||
self.const_get klass_name
|
||
else
|
||
... | ... | |
# validate config with schema
|
||
parser = Kwalify::Yaml::Parser.new(validator)
|
||
def_data = parser.parse(def_data_raw, :filename => def_name, :untabify => true)
|
||
raise_if_validation_errors("#{type.capitalize} '#{def_name}'", parser.errors)
|
||
raise_if_validation_errors("#{type} '#{def_name}'", parser.errors)
|
||
|
||
def_data
|
||
rescue
|
||
... | ... | |
end
|
||
|
||
def self.load_default_config(type = "global")
|
||
filename = File.join(DATA_DIR, "default_config", type + ".yaml")
|
||
filename = File.join(DATA_DIR, "default_config", type.downcase + ".yaml")
|
||
default_config_raw = File.read(filename)
|
||
default_config = parse(':defaults:', type, default_config_raw, false)
|
||
default_config
|
||
... | ... | |
end
|
||
|
||
def self.load_schema(type = "global")
|
||
schema_file = File.join(DATA_DIR, "schema", type + ".yaml")
|
||
schema_file = File.join(DATA_DIR, "schema", type.downcase + ".yaml")
|
||
schema = YAML.load_file(schema_file)
|
||
|
||
# validate schema
|
lib/cyborghood/cyborg.rb | ||
---|---|---|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
require 'xmpp4r'
|
||
require 'xmpp4r/presence'
|
||
require 'xmpp4r/version/iq/version'
|
||
require 'xmpp4r/version/helper/simpleresponder'
|
||
require 'xmpp4r/caps'
|
||
require 'xmpp4r/discovery'
|
||
#require 'xmpp4r/vcard/helper/vcard'
|
||
require 'xmpp4r/muc/helper/mucbrowser'
|
||
require 'xmpp4r/muc/helper/simplemucclient'
|
||
require 'cyborghood'
|
||
require 'cyborghood/cyborg/server'
|
||
|
||
|
||
module CyborgHood
|
||
class Cyborg
|
||
attr_reader :jid, :room_jid, :chat_jid
|
||
include I18nTranslation
|
||
bindtextdomain("cyborghood", {:path => Config::L10N_DIR, :charset => "UTF-8"})
|
||
|
||
FEATURE_NS = 'http://duckcorp.org/protocol/cyborghood'
|
||
|
||
def initialize()
|
||
def initialize
|
||
# load config
|
||
Config.load(self.human_name.downcase)
|
||
Config.load(self.human_name)
|
||
@config = Config.instance
|
||
|
||
# setup logs
|
||
unless @config.log.nil?
|
||
logger.output_level(@config.log.console_level) unless @config.log.console_level.nil?
|
||
logger.log_to_file(@config.log.file) unless @config.log.file.nil?
|
||
end
|
||
|
||
# prepare
|
||
clear
|
||
@jid = Jabber::JID.new(@config.xmpp.jid)
|
||
@room_jid = Jabber::JID.new(@config.xmpp.muc).bare
|
||
|
||
yield if block_given?
|
||
|
||
logger.info "Bot '#{self.human_name}' loaded"
|
||
end
|
||
|
||
def run
|
||
logger.info "Initializing bot..."
|
||
|
||
begin
|
||
@cl = Jabber::Client.new(@jid)
|
||
@cl.allow_tls = true
|
||
@cl.ssl_capath = @config.xmpp.ssl_capath unless @config.xmpp.ssl_capath.nil?
|
||
reconnect
|
||
rescue Jabber::ServerError => e
|
||
if e.error.type == :cancel and e.error.code == 409
|
||
if @nick_index < 100
|
||
retry
|
||
unless @config.log.path.nil?
|
||
if File.directory? @config.log.path
|
||
logger.log_to_file(File.join(@config.log.path, "ch_#{self.class.human_name}.log"))
|
||
else
|
||
logger.fatal "Cannot connect to CyborgHood HeadQuarters because my Nickname range is full (maybe a security problem)"
|
||
quit(true)
|
||
logger.fatal "Log path does not exist or is not a directory, exiting"
|
||
exit 1
|
||
end
|
||
else
|
||
logger.fatal "Cannot connect to CyborgHood HeadQuarters: " + e.error.text
|
||
quit(true)
|
||
end
|
||
end
|
||
|
||
@cl.on_exception { sleep 5; reconnect }
|
||
|
||
logger.info "Bot ready for work"
|
||
|
||
@run_thread = Thread.new { yield }
|
||
@run_thread.join
|
||
|
||
logger.info "Bot work is finished, going to sleep..."
|
||
quit
|
||
end
|
||
|
||
def ask_to_stop
|
||
@should_stop = true
|
||
@run_thread.wakeup if @run_thread.stop?
|
||
end
|
||
|
||
protected
|
||
|
||
def quit(fatal = false)
|
||
if @cl
|
||
@muc.exit if @muc and @muc.active?
|
||
@cl.close
|
||
end
|
||
clear
|
||
exit 1 if fatal
|
||
end
|
||
|
||
def advertise_presence(available)
|
||
show = (available ? :chat : :dnd)
|
||
@cl.send(Jabber::Presence.new.set_show(show))
|
||
end
|
||
|
||
def advertise_presence_in_room(available)
|
||
show = (available ? :chat : :dnd)
|
||
stanza = Jabber::Presence.new.set_show(show)
|
||
stanza.from = @jid.to_s
|
||
stanza.to = @chat_jid.to_s
|
||
@cl.send(stanza)
|
||
end
|
||
|
||
def discover_features(jid)
|
||
result = discover(jid)
|
||
result.nil? ? [] : result.features
|
||
end
|
||
|
||
def room_members
|
||
@muc.roster.keys.sort
|
||
end
|
||
|
||
def unnormalize_message(msg)
|
||
msg2 = msg.dup
|
||
REXML::DocType::DEFAULT_ENTITIES.each_value do |entity|
|
||
msg2.gsub!("&#{entity.name};", entity.value)
|
||
end
|
||
msg2.gsub!( '&', '&' )
|
||
return msg2
|
||
end
|
||
|
||
private
|
||
|
||
def reconnect
|
||
logger.debug "Connecting to the XMPP server..."
|
||
@cl.connect
|
||
@cl.auth(@config.xmpp.passwd)
|
||
|
||
unless @cl.is_tls?
|
||
logger.fatal "Connection to CyborgHood HeadQuarters is not encrypted; please configure TLS support !"
|
||
quit(true)
|
||
end
|
||
|
||
# initial presence before being ready
|
||
logger.debug "Advertising unavailable status"
|
||
advertise_presence(false)
|
||
|
||
# version
|
||
logger.debug "Starting version responder"
|
||
Jabber::Version::SimpleResponder.new(@cl, PRODUCT, VERSION, "")
|
||
|
||
# advertise discovery info
|
||
logger.debug "Starting capabilities responder"
|
||
Jabber::Caps::Helper.new(@cl,
|
||
[Jabber::Discovery::Identity.new('client', self.human_name, 'bot')],
|
||
[Jabber::Discovery::Feature.new(FEATURE_NS)]
|
||
)
|
||
|
||
# enter MUC room
|
||
knock_at_room_door unless @in_room
|
||
enter_room
|
||
|
||
# presence
|
||
logger.debug "Advertising available status"
|
||
advertise_presence(true)
|
||
end
|
||
|
||
def knock_at_room_door
|
||
end
|
||
|
||
def enter_room
|
||
logger.debug "Discovering room component features"
|
||
unless discover_features(@room_jid).include?(Jabber::MUC::XMUC.new.namespace)
|
||
logger.fatal "CyborgHood HeadQuarters has no MUC support"
|
||
quit(true)
|
||
end
|
||
|
||
logger.debug "Fetching room list"
|
||
@muc_br = Jabber::MUC::MUCBrowser.new(@cl)
|
||
room_list = @muc_br.muc_rooms(@room_jid.domain)
|
||
|
||
@chat_jid = @room_jid.dup
|
||
@chat_jid.resource = generate_available_nick()
|
||
@server = BotServer.build
|
||
|
||
logger.debug "Joining room '#{@room_jid}' as '#{@chat_jid.resource}'..."
|
||
@muc = Jabber::MUC::SimpleMUCClient.new(@cl)
|
||
register_room_callbacks
|
||
@muc.join(@chat_jid)
|
||
|
||
if room_list.keys.include?(@room_jid.to_s)
|
||
on_existing_room()
|
||
else
|
||
on_missing_room()
|
||
end
|
||
|
||
# presence
|
||
logger.debug "Advertising available status in room"
|
||
advertise_presence_in_room(true)
|
||
|
||
@in_room = true
|
||
end
|
||
|
||
def on_missing_room
|
||
logger.fatal "CyborgHood HeadQuarters has no meeting room"
|
||
quit(true)
|
||
end
|
||
|
||
def on_existing_room
|
||
end
|
||
|
||
def register_room_callbacks
|
||
end
|
||
|
||
def discover(jid, node = nil)
|
||
iq = Jabber::Iq.new(:get, jid.domain)
|
||
iq.query = Jabber::Discovery::IqQueryDiscoInfo.new
|
||
iq.query.node = node unless node.nil?
|
||
|
||
result = nil
|
||
@cl.send_with_id(iq) {|reply|
|
||
result = reply.query
|
||
}
|
||
return result
|
||
logger.info "Bot '#{self.human_name}' loaded"
|
||
end
|
||
|
||
def generate_available_nick
|
||
@nick_index += 1
|
||
self.human_name + "-" + @nick_index.to_s.rjust(2, "0")
|
||
def run
|
||
logger.info "Bot starting"
|
||
@server.run
|
||
end
|
||
|
||
def clear
|
||
@cl = nil
|
||
@muc_br = nil
|
||
@muc = nil
|
||
@chat_jid = nil
|
||
@nick_index = 0
|
||
@in_room = false
|
||
@should_stop = false
|
||
def ask_to_stop
|
||
@server.stop
|
||
logger.info "Bot was asked to stop..."
|
||
end
|
||
end
|
||
end
|
lib/cyborghood/cyborg.rb.old | ||
---|---|---|
#--
|
||
# CyborgHood, a distributed system management software.
|
||
# Copyright (c) 2009-2010 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
require 'xmpp4r'
|
||
require 'xmpp4r/presence'
|
||
require 'xmpp4r/version/iq/version'
|
||
require 'xmpp4r/version/helper/simpleresponder'
|
||
require 'xmpp4r/caps'
|
||
require 'xmpp4r/discovery'
|
||
#require 'xmpp4r/vcard/helper/vcard'
|
||
require 'xmpp4r/muc/helper/mucbrowser'
|
||
require 'xmpp4r/muc/helper/simplemucclient'
|
||
|
||
|
||
module CyborgHood
|
||
class Cyborg
|
||
attr_reader :jid, :room_jid, :chat_jid
|
||
|
||
FEATURE_NS = 'http://duckcorp.org/protocol/cyborghood'
|
||
|
||
def initialize()
|
||
# load config
|
||
Config.load(self.human_name.downcase)
|
||
@config = Config.instance
|
||
|
||
# setup logs
|
||
unless @config.log.nil?
|
||
logger.output_level(@config.log.console_level) unless @config.log.console_level.nil?
|
||
logger.log_to_file(@config.log.file) unless @config.log.file.nil?
|
||
end
|
||
|
||
# prepare
|
||
clear
|
||
@jid = Jabber::JID.new(@config.xmpp.jid)
|
||
@room_jid = Jabber::JID.new(@config.xmpp.muc).bare
|
||
|
||
yield if block_given?
|
||
|
||
logger.info "Bot '#{self.human_name}' loaded"
|
||
end
|
||
|
||
def run
|
||
logger.info "Initializing bot..."
|
||
|
||
begin
|
||
@cl = Jabber::Client.new(@jid)
|
||
@cl.allow_tls = true
|
||
@cl.ssl_capath = @config.xmpp.ssl_capath unless @config.xmpp.ssl_capath.nil?
|
||
reconnect
|
||
rescue Jabber::ServerError => e
|
||
if e.error.type == :cancel and e.error.code == 409
|
||
if @nick_index < 100
|
||
retry
|
||
else
|
||
logger.fatal "Cannot connect to CyborgHood HeadQuarters because my Nickname range is full (maybe a security problem)"
|
||
quit(true)
|
||
end
|
||
else
|
||
logger.fatal "Cannot connect to CyborgHood HeadQuarters: " + e.error.text
|
||
quit(true)
|
||
end
|
||
end
|
||
|
||
@cl.on_exception { sleep 5; reconnect }
|
||
|
||
logger.info "Bot ready for work"
|
||
|
||
@run_thread = Thread.new { yield }
|
||
@run_thread.join
|
||
|
||
logger.info "Bot work is finished, going to sleep..."
|
||
quit
|
||
end
|
||
|
||
def ask_to_stop
|
||
@should_stop = true
|
||
@run_thread.wakeup if @run_thread.stop?
|
||
end
|
||
|
||
protected
|
||
|
||
def quit(fatal = false)
|
||
if @cl
|
||
@muc.exit if @muc and @muc.active?
|
||
@cl.close
|
||
end
|
||
clear
|
||
exit 1 if fatal
|
||
end
|
||
|
||
def advertise_presence(available)
|
||
show = (available ? :chat : :dnd)
|
||
@cl.send(Jabber::Presence.new.set_show(show))
|
||
end
|
||
|
||
def advertise_presence_in_room(available)
|
||
show = (available ? :chat : :dnd)
|
||
stanza = Jabber::Presence.new.set_show(show)
|
||
stanza.from = @jid.to_s
|
||
stanza.to = @chat_jid.to_s
|
||
@cl.send(stanza)
|
||
end
|
||
|
||
def discover_features(jid)
|
||
result = discover(jid)
|
||
result.nil? ? [] : result.features
|
||
end
|
||
|
||
def room_members
|
||
@muc.roster.keys.sort
|
||
end
|
||
|
||
def unnormalize_message(msg)
|
||
msg2 = msg.dup
|
||
REXML::DocType::DEFAULT_ENTITIES.each_value do |entity|
|
||
msg2.gsub!("&#{entity.name};", entity.value)
|
||
end
|
||
msg2.gsub!( '&', '&' )
|
||
return msg2
|
||
end
|
||
|
||
private
|
||
|
||
def reconnect
|
||
logger.debug "Connecting to the XMPP server..."
|
||
@cl.connect
|
||
@cl.auth(@config.xmpp.passwd)
|
||
|
||
unless @cl.is_tls?
|
||
logger.fatal "Connection to CyborgHood HeadQuarters is not encrypted; please configure TLS support !"
|
||
quit(true)
|
||
end
|
||
|
||
# initial presence before being ready
|
||
logger.debug "Advertising unavailable status"
|
||
advertise_presence(false)
|
||
|
||
# version
|
||
logger.debug "Starting version responder"
|
||
Jabber::Version::SimpleResponder.new(@cl, PRODUCT, VERSION, "")
|
||
|
||
# advertise discovery info
|
||
logger.debug "Starting capabilities responder"
|
||
Jabber::Caps::Helper.new(@cl,
|
||
[Jabber::Discovery::Identity.new('client', self.human_name, 'bot')],
|
||
[Jabber::Discovery::Feature.new(FEATURE_NS)]
|
||
)
|
||
|
||
# enter MUC room
|
||
knock_at_room_door unless @in_room
|
||
enter_room
|
||
|
||
# presence
|
||
logger.debug "Advertising available status"
|
||
advertise_presence(true)
|
||
end
|
||
|
||
def knock_at_room_door
|
||
end
|
||
|
||
def enter_room
|
||
logger.debug "Discovering room component features"
|
||
unless discover_features(@room_jid).include?(Jabber::MUC::XMUC.new.namespace)
|
||
logger.fatal "CyborgHood HeadQuarters has no MUC support"
|
||
quit(true)
|
||
end
|
||
|
||
logger.debug "Fetching room list"
|
||
@muc_br = Jabber::MUC::MUCBrowser.new(@cl)
|
||
room_list = @muc_br.muc_rooms(@room_jid.domain)
|
||
|
||
@chat_jid = @room_jid.dup
|
||
@chat_jid.resource = generate_available_nick()
|
||
|
||
logger.debug "Joining room '#{@room_jid}' as '#{@chat_jid.resource}'..."
|
||
@muc = Jabber::MUC::SimpleMUCClient.new(@cl)
|
||
register_room_callbacks
|
||
@muc.join(@chat_jid)
|
||
|
||
if room_list.keys.include?(@room_jid.to_s)
|
||
on_existing_room()
|
||
else
|
||
on_missing_room()
|
||
end
|
||
|
||
# presence
|
||
logger.debug "Advertising available status in room"
|
||
advertise_presence_in_room(true)
|
||
|
||
@in_room = true
|
||
end
|
||
|
||
def on_missing_room
|
||
logger.fatal "CyborgHood HeadQuarters has no meeting room"
|
||
quit(true)
|
||
end
|
||
|
||
def on_existing_room
|
||
end
|
||
|
||
def register_room_callbacks
|
||
end
|
||
|
||
def discover(jid, node = nil)
|
||
iq = Jabber::Iq.new(:get, jid.domain)
|
||
iq.query = Jabber::Discovery::IqQueryDiscoInfo.new
|
||
iq.query.node = node unless node.nil?
|
||
|
||
result = nil
|
||
@cl.send_with_id(iq) {|reply|
|
||
result = reply.query
|
||
}
|
||
return result
|
||
end
|
||
|
||
def generate_available_nick
|
||
@nick_index += 1
|
||
self.human_name + "-" + @nick_index.to_s.rjust(2, "0")
|
||
end
|
||
|
||
def clear
|
||
@cl = nil
|
||
@muc_br = nil
|
||
@muc = nil
|
||
@chat_jid = nil
|
||
@nick_index = 0
|
||
@in_room = false
|
||
@should_stop = false
|
||
end
|
||
end
|
||
end
|
lib/cyborghood/cyborg/server.rb | ||
---|---|---|
#--
|
||
# CyborgHood, a distributed system management software.
|
||
# Copyright (c) 2009-2010 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#++
|
||
|
||
require 'eventmachine'
|
||
|
||
|
||
module CyborgHood
|
||
class BotServer
|
||
private_class_method :new
|
||
|
||
def self.build
|
||
case Config.instance.botnet.connection_type
|
||
when 'unix_socket'
|
||
return BotServerUNIXSocket.new
|
||
else
|
||
raise CyberError.new(:unrecoverable, "config", "Unknown botnet connection type")
|
||
end
|
||
end
|
||
|
||
def initialize
|
||
@config = Config.instance
|
||
end
|
||
|
||
def run
|
||
EventMachine.run do
|
||
yield
|
||
end
|
||
end
|
||
|
||
def stop
|
||
EventMachine.stop
|
||
end
|
||
end
|
||
|
||
class BotServerUNIXSocket < BotServer
|
||
public_class_method :new
|
||
|
||
def initialize
|
||
super
|
||
|
||
@socket = File.join(Config::RUN_DIR, @config.bot_name.downcase + ".sock")
|
||
at_exit { remove_socket_file }
|
||
end
|
||
|
||
def run
|
||
super do
|
||
EventMachine.start_unix_domain_server(@socket, ConversationUNIXSocket)
|
||
end
|
||
end
|
||
|
||
private
|
||
|
||
def remove_socket_file
|
||
File.delete(@socket) if @socket && File.exist?(@socket)
|
||
end
|
||
end
|
||
|
||
class Conversation < EventMachine::Protocols::LineAndTextProtocol
|
||
private_class_method :new
|
||
|
||
def initialize(*args)
|
||
super
|
||
|
||
@config = Config.instance
|
||
end
|
||
|
||
def send_line(msg)
|
||
send_data "#{msg}\r\n"
|
||
end
|
||
|
||
def post_init
|
||
logger.debug "New conversation with #{identifier}"
|
||
send_line "220 #{PRODUCT} #{VERSION} - #{@config.bot_name}"
|
||
end
|
||
|
||
def receive_line(data)
|
||
logger.debug "Received [#{identifier}]: #{data}"
|
||
end
|
||
|
||
def receive_error(msg)
|
||
logger.error "Error [#{identifier}]: #{msg}"
|
||
end
|
||
|
||
def unbind
|
||
logger.debug "Conversation finished with #{identifier}"
|
||
end
|
||
end
|
||
|
||
class ConversationUNIXSocket < Conversation
|
||
public_class_method :new
|
||
|
||
def identifier
|
||
"unix_socket/#{@signature}"
|
||
end
|
||
end
|
||
end
|
lib/cyborghood/services/dns.rb | ||
---|---|---|
@content = nil
|
||
|
||
@filename = @config.dns.master_zone_pattern.gsub("#ZONE#", @zone)
|
||
# TODO: should be checked at startup time
|
||
raise CyberError.new(:unrecoverable, "services/dns", "erroneous configuration: pattern is constant") if @filename == @config.dns.master_zone_pattern
|
||
|
||
# ensure we can find the needed programs (should be handled somewhere else)
|
||
ENV['PATH'] = (ENV['PATH'].split(":") + ["/sbin", "/usr/sbin", "/usr/local/sbin"]).uniq.join(":")
|
Also available in: Unified diff
[evol] uncomplete MapMaker bot implementation (global cyborg classes, use of EventMachine with UNIX socket backend, configuration adjustments, ...) (refs #31)