# Proxy of ruby-debug-ide for remote debugging # Version:: 0.1 # Author:: Rikiya Ayukawa (mailto:dbc.ginriki@gmail.com) # Copyright:: Copyright (c) 2010 # License:: Distributes under the MIT License: http://mbed.org/license/mit require 'logger' require 'socket' require 'rexml/document' require 'optparse' include REXML $logger = Logger.new(STDOUT) RDB_PORT = 1234 PORT = 7000 def replace(path) return path.gsub(Regexp.new("^#{$config['rdbprefix']}"), $config["ideprefix"]) end def replace_cmdpath(cmdpath, cmd = "b") case cmd when "b" tmp = cmdpath.gsub("b #{$config['ideprefix']}", "b #{$config['rdbprefix']}") tmp.gsub!("\\", File::SEPARATOR) return tmp end end def xml_filter(xml) doc = Document.new(xml) root = doc.root XPath.each(doc, "//suspended|//breakpoint|//frames/frame") do |elem| if elem.attributes["file"] file = elem.attributes["file"] elem.attributes["file"] = file.gsub($config["rdbprefix"], $config["ideprefix"]) end end XPath.each(doc, "//breakpointAdded") do |elem| if elem.attributes["location"] file = elem.attributes["location"] elem.attributes["location"] = file.gsub($config["rdbprefix"], $config["ideprefix"]) end end return doc.to_s end def read_xmlend(io) recv_xml = "" loop do # FIXME: I expect IO.select return array which include [io] # in case that io buffer remains, # but that of JRuby causes timeout and returns nil. # rl = IO.select([io], nil, nil, 3) # raise "Timeout: incomplete xml= #{recv_xml}" unless rl s = io.gets(">") raise "EOF: incomplete xml= #{recv_xml}" unless s recv_xml += s begin Document.new(recv_xml) return recv_xml rescue ParseException end end end def get_config config = {} config["rdb_port"] = RDB_PORT config["port"] = PORT config["rdbprefix"] = "/" config["ideprefix"] = "C:/" opts = OptionParser.new opts.on("-t "){|v| args = v.split(":") config["rdb_host"] = args[0] config["rdb_port"] = args[1].to_i if args[1] } opts.on("-p "){|v| config["port"] = v.to_i } opts.on("--rdbprefix "){|v| config["rdbprefix"] = v } opts.on("--ideprefix "){|v| config["ideprefix"] = v } opts.on("-d"){|v| config["debug"] = true } opts.parse(ARGV) raise "rdb_host must be specified." unless config["rdb_host"] return config end def usage $stderr.puts("Usage: #{$0} -t [-p listen_port] [--rdbprefix prefix] [--ideprefix prefix] [-d]") $stderr.puts("") $stderr.puts("Example: #{$0} -t localhost --rdbprefix \"/home/user/script\" --ideprefix \"C:\\\\win_script\" -d") $stderr.puts("") end def main begin $config = get_config rescue => ex usage raise ex end if $config["debug"] $logger.level = Logger::DEBUG else $logger.level = Logger::INFO end $logger.info("proxy will replace #{$config['rdbprefix']} with #{$config['ideprefix']}") $logger.info("proxy listens on 0.0.0.0:#{$config['port']}") ide_proxy = TCPServer.open($config["port"]) ide = ide_proxy.accept $logger.info("proxy connects to #{$config['rdb_host']}:#{$config['rdb_port']}") rdb = TCPSocket.open($config["rdb_host"], $config["rdb_port"]) $logger.info("debug start") eof_flag = false until eof_flag rl = IO.select([ide, rdb], nil, nil, 3) next unless rl rl.first.each do |io| if io == ide if io.eof? eof_flag = true else cmd = io.gets $logger.debug("(ide -> proxy) #{cmd}") cmd = replace_cmdpath(cmd) $logger.debug("(proxy -> rdb) #{cmd}") rdb.write(cmd) end elsif io == rdb if io.eof? eof_flag = true else recv_xml = read_xmlend(rdb) $logger.debug("(rdb -> proxy) #{recv_xml}") send_xml = xml_filter(recv_xml) $logger.debug("(proxy -> ide) #{send_xml}") ide.write(send_xml) end end end end rdb.close ide.close ide_proxy.close end main