136 lines
2.6 KiB
Ruby
136 lines
2.6 KiB
Ruby
require 'singleton'
|
|
require 'rex'
|
|
require 'rex/service'
|
|
|
|
module Rex
|
|
|
|
###
|
|
#
|
|
# This class manages service allocation and interaction. This class can be
|
|
# used to start HTTP servers and manage them and all that stuff. Yup.
|
|
#
|
|
###
|
|
class ServiceManager < Hash
|
|
|
|
#
|
|
# This class is a singleton.
|
|
#
|
|
include Singleton
|
|
|
|
#
|
|
# Calls the instance method to start a service.
|
|
#
|
|
def self.start(klass, *args)
|
|
self.instance.start(klass, *args)
|
|
end
|
|
|
|
#
|
|
# Calls the instance method to stop a service.
|
|
#
|
|
def self.stop(klass, *args)
|
|
self.instance.stop(klass, *args)
|
|
end
|
|
|
|
def self.stop_by_alias(als)
|
|
self.instance.stop_by_alias(als)
|
|
end
|
|
|
|
def self.stop_service(service)
|
|
self.instance.stop_service(service)
|
|
end
|
|
|
|
#
|
|
# Starts a service and assigns it a unique name in the service hash.
|
|
#
|
|
def start(klass, *args)
|
|
# Get the hardcore alias.
|
|
hals = hardcore_alias(klass, *args)
|
|
|
|
# Has a service already been constructed for this guy? If so, increment
|
|
# its reference count like it aint no thang.
|
|
if (inst = self[hals])
|
|
inst.ref
|
|
return inst
|
|
end
|
|
|
|
inst = klass.new(*args)
|
|
als = inst.alias
|
|
|
|
# Find an alias that isn't taken.
|
|
if (self[als])
|
|
cnt = 1
|
|
cnt += 1 while (self[als + " #{cnt}"])
|
|
als = inst.alias + " #{cnt}"
|
|
end
|
|
|
|
# Extend the instance as a service.
|
|
inst.extend(Rex::Service)
|
|
|
|
# Re-aliases the instance.
|
|
inst.alias = als
|
|
|
|
# Fire up the engines. If an error occurs an exception will be
|
|
# raised.
|
|
inst.start
|
|
|
|
# Alias associate and initialize reference counting
|
|
self[als] = self[hals] = inst.refinit
|
|
|
|
# Pass the caller a reference
|
|
inst.ref
|
|
|
|
inst
|
|
end
|
|
|
|
#
|
|
# Stop a service using a given klass and arguments. These should mirror
|
|
# what was originally passed to start exactly. If the reference count of
|
|
# the service drops to zero the service will be destroyed.
|
|
#
|
|
def stop(klass, *args)
|
|
stop_service(hals[hardcore_alias(klass, *args)])
|
|
end
|
|
|
|
#
|
|
# Stops a service using the provided alias
|
|
#
|
|
def stop_by_alias(als)
|
|
stop_service(self[als])
|
|
end
|
|
|
|
#
|
|
# Stops a service instance.
|
|
#
|
|
def stop_service(inst)
|
|
# Stop the service and be done wif it, but only if the number of
|
|
# references has dropped to zero
|
|
if (inst)
|
|
# Since the instance may have multiple aliases, scan through
|
|
# all the pairs for matching stuff.
|
|
self.each_pair { |cals, cinst|
|
|
self.delete(cals) if (inst == cinst)
|
|
}
|
|
|
|
# Lose the list-held reference to the instance
|
|
inst.deref
|
|
|
|
return true
|
|
end
|
|
|
|
# Return false if the service isn't there
|
|
return false
|
|
end
|
|
|
|
protected
|
|
|
|
#
|
|
# Returns the alias for a given service instance.
|
|
#
|
|
def hardcore_alias(klass, *args)
|
|
"__#{klass.name}#{args.to_s}"
|
|
end
|
|
|
|
end
|
|
|
|
end
|