Project

General

Profile

Download (2.91 KB) Statistics
| Branch: | Tag: | Revision:
#--
# 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 'cyborghood/cyborg/interface'
require 'cyborghood/cyborg/conversation'
require 'cyborghood/cyborg/botnet_dsl'
require 'set'

module CyborgHood
# default interface if not overridden
# a mere "BotClient" would then always have a default basic interface
class EmptyInterface
include CyborgServerInterface
include CyborgServerRootInterfaceAddon
end

module BotNetClientUNIXSocket
def identifier_prefix
"unix_socket"
end

def setup
super
@pending_conversation_close = Set.new
end

def peer_socket(peer)
File.join(Config::RUN_DIR, peer.downcase + ".sock")
end

def contact_peer(peer, &block)
if @comm_list.has_key? peer
block.call @comm_list[peer]
else
callback = proc do |conversation|
block.call conversation
@pending_conversation_close << conversation.peer_id
end
begin
EventMachine.connect_unix_domain(peer_socket(peer), Conversation, self, block)
rescue
block.call false
end
end
end
end

module BotNet
attr_reader :interface

def self.included(base)
case Config.instance.botnet.connection_type
when 'unix_socket'
return base.class_eval("include BotNetClientUNIXSocket")
else
raise CyberError.new(:unrecoverable, "config", "Unknown botnet connection type")
end
end

def setup
super
@comm_list = {}
end

# used to quit properly and later to reuse communication channels
def register_communication(peer, conversation)
@comm_list[peer] = conversation
end

def unregister_communication(peer)
@comm_list.delete(peer)
@pending_conversation_close.delete(peer)
end

def ask_to_stop
@comm_list.values.each {|conv| conv.bye }
super
end

def interface
EmptyInterface.instance
end

protected

def process_system_notification(msg)
if msg[:topic] == 'CONVERSATION IDLE'
peer = @comm_list[msg[:peer]]
return if peer.nil?

peer.bye
else
super
end
end

def ready_to_stop?
@comm_list.empty? and super
end
end
end
(1-1/8)