# Adhearsion, open source technology integrator # Copyright (C) 2006,2007 Jay Phillips # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA require 'drb' require 'drb/acl' require 'thread' module DRbServerManager def self.start config = CONFIG['drb'] || {} permissions = [] # For greater control over the ACL if config['raw_acl'] permissions = config['raw_acl'].flatten else [config['deny']].flatten.each { |ip| permissions << "deny" << ip } [config['allow']].flatten.each { |ip| permissions << "allow" << ip } end # Load the Access Control List DRb.install_acl ACL.new(permissions) host = config['host'] || 'localhost' port = config['port'] || 9050 DRb.start_service "druby://#{host}:#{port}", DRbDoor.new info "Started DRb server on #{DRb.uri}." info "DRb Server Access Control List:" 0.step permissions.length-1, 2 do |i| info " #{permissions[i].upcase} #{permissions[i+1]}" end $HUTDOWN.hook { DRbServerManager.stop } end def self.stop DRb.stop_service end end # == Using Distributed Ruby (DRb) in Adhearsion # # A DRb server works by offering a single object to other Ruby instances # who wish to use it over TCP. The DRbDoor class is designed to provide # remote access to the Adhearsion's internals, such as the +PBX+ object, # helpers' methods, etc. # # == Usage example # # Below is an example DRb client which accesses Adhearsion's internals. # # require 'drb' # DRb.start_service # Adhearsion = DRbObject.new nil, 'druby://localhost:9050' # p Adhearsion.PBX.sip_users # p Adhearsion.weather 'Dallas, Texas' # # Notice the subtle differences above in the two remote DRb procedure calls. # When calling a method on the DRbDoor (called Adhearsion in the example), the # target method is inspected to see whether the name meets the Ruby's constant # syntax: capitalized first letter. The example PBX method actually returns # the equivalent of Module.const_get(:PBX). When calling a traditionally-formatted # method (no first capital letter), the return value of that method is evaluated. class DRbDoor instance_methods.each { |m| undef_method m unless m =~ /^(__|((private|protected)_methods|to_s|class)$)/ } @@door = Object.new class << @@door def metaclass() class << self; self; end; end def meta_eval(&block) metaclass.instance_eval(&block) end end def method_missing name, *args, &block # Check whether it's a constant if (?A..?Z).include? name.to_s[0] then Module.const_get name else @@door.meta_eval { __send__ name, *args, &block } end end def cli(&block) self.instance_eval(&block) end end