plamoni / SiriProxy

A (tampering) proxy server for Apple's Siri
GNU General Public License v3.0
2.12k stars 343 forks source link

siriproxy plugin initialization #485

Open elvisimprsntr opened 11 years ago

elvisimprsntr commented 11 years ago

Beginning with SP 0.4.2 (with the new plugin_init), I have observed a problem where code in the initialization section gets run upon start of siriproxy server, not just upon a siri connection. Perhaps it has always been this way, but it was presenting a challenge with one of my plugins which I was implementing auto discovery. I was able to work around the issue by making all initialization class variables and removed them from the initialization section. I tried to use the new plugin_init, but it seems to make initialization more difficult to understand and manage. Perhaps I did not fully grasp how to use the new plugin_init method. Not sure if anyone else has observed or has similar problems.

require 'dnssd' require 'socket' require 'httparty' require 'yaml'

class SiriProxy::Plugin::RedEye < SiriProxy::Plugin

class Rest include HTTParty format :xml end

Initialization

@@reIP = Hash.new DNSSD.browse '_tf_redeye._tcp.' do |reply| puts "[Info - Redeye] Bonjour discovery: " + reply.name
addr = Socket.getaddrinfo(reply.name + ".local.", nil, Socket::AF_INET) @@reIP[reply.name] = addr[0][2] end

begin @@Default = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reDefault.yml"))) @@stationID = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reStation.yml"))) rescue puts "[Warning - RedEye] Error reading reDefault.yml and/or reStation.yml file." end

begin @@reSel = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reSel.yml"))) @@redeyeIP = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reRedeye.yml"))) @@roomID = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reRoom.yml"))) @@deviceID = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reDevice.yml"))) @@activityID = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reActivity.yml"))) @@commandID = YAML.load(File.read(File.expand_path(File.dirname( FILE ) + "/reCommand.yml"))) @@cmdURL = @@redeyeIP[@@reSel["redeye"]] + @@roomID[@@reSel["redeye"]][@@reSel["room"]] + @@deviceID[@@reSel["room"]][@@reSel["device"]] rescue @@reSel = @@Default @@redeyeIP = Hash.new @@roomID = Hash.new { |h,k| h[k] = Hash.new } @@deviceID = Hash.new { |h,k| h[k] = Hash.new } @@activityID = Hash.new { |h,k| h[k] = Hash.new } @@commandID = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)})) puts "[Warning - RedEye] Plugin not initialized. Say RedEye Initialize." end

def initialize(config)

Unfortunately, anything put here gets run during SiriProxy >= 0.4.2 startup.

end

plamoni commented 11 years ago

This was on purpose. Previously, there were two options for when you run your code: When there's a match with a listener or when the plugin gets loaded. The former happens when the plugin will be used, while the latter happens no matter what the user connected for. So anything "heavy" that has to happen in there happens all the time and not until the user connects.

With 0.4.2, initialization code now gets run when the server starts up, so heavy lifting can happen then (and objects can be persisted). For instance, you could maintain a connection to a service. If you want to do per-message connections to a service, those should be done in the listeners.

Essentially, you couldn't run code only once from a plugin before. Now you can. Sorry if it broke something, but I think this is a better approach to initialization code and allows for options that weren't there before.

I could probably add a method for getting called each time the plugin is loaded. But I'm a bit worried it might get abused and cause slowness in other plugins. I'll consider it.

elvisimprsntr commented 11 years ago

A couple of the problems I encountered were:

  1. Outside of initialize, you cannot call other methods. it will result in a "undefined variable" For example:

    rescue @@reSel = @@Default @@redeyeIP = Hash.new @@roomID = Hash.new { |h,k| h[k] = Hash.new } @@deviceID = Hash.new { |h,k| h[k] = Hash.new } @@activityID = Hash.new { |h,k| h[k] = Hash.new } @@commandID = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)})) init_redeyes # this results in undefined variable. end

  2. I can call methods inside initialize, but if I perform an if check on a variable/hash to perform other steps first, any call outside of the if check actually gets executed first. Example:

    def initialize(config) if @@redeyeIP.nil? init_redeyes end init_url # this actually gets run before the init_redeyes end

Not sure if it's a Ruby thing or something else, but stripping everything outside of initialize and making them class variables was the only way I could make work. Compared to getting Bonjour auto discovery working, getting initialization working was much more difficult.