diff --git a/bin/passageway b/bin/passageway index be04113..f87655d 100755 --- a/bin/passageway +++ b/bin/passageway @@ -1,5 +1,6 @@ #!/usr/bin/env ruby # Copyright (c) 2010 Jeff Lindsay +# Copyright (c) 2013 R. Tyler Croy # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -24,16 +25,16 @@ require 'rubygems' require 'optparse' -require 'localtunnel' +require 'passageway' key = nil options = OptionParser.new do |o| - o.banner = - "Usage: localtunnel [options] \n\n" + + o.banner = + "Usage: passageway [options] \n\n" + "The file .localtunnel_callback, if it exists in the current working directory,\n"+ "will be executed with the tunnel endpoint as the first argument once the \n" + "tunnel is started\n\n" - + o.on("-k", "--key FILE", "upload a public key for authentication") do |k| key = File.exist?(k.to_s) ? File.open(k).read : nil end @@ -47,6 +48,6 @@ unless local_port.to_i.between?(1, 65535) exit end -t = LocalTunnel::Tunnel.new(local_port, key) +t = Passageway::Client.new(local_port, key) t.register_tunnel t.start_tunnel diff --git a/lib/passageway/client.rb b/lib/passageway/client.rb index 57b6b15..2e4ebd1 100644 --- a/lib/passageway/client.rb +++ b/lib/passageway/client.rb @@ -5,68 +5,69 @@ require 'net/http' require 'uri' require 'json' -require 'localtunnel/net_ssh_gateway_patch' +require 'passageway/net_ssh_gateway_patch' -module LocalTunnel; end +module Passageway + class Client -class LocalTunnel::Tunnel + SHELL_HOOK_FILE = "./.localtunnel_callback" - SHELL_HOOK_FILE = "./.localtunnel_callback" + attr_accessor :port, :key, :host - attr_accessor :port, :key, :host - - def initialize(port, key) - @port = port - @key = key - @host = "" - end - - def register_tunnel(key=@key) - url = URI.parse("http://open.localtunnel.com/") - if key - resp = JSON.parse(Net::HTTP.post_form(url, {"key" => key}).body) - else - resp = JSON.parse(Net::HTTP.get(url)) + def initialize(port, key) + @port = port + @key = key + @host = "" end - if resp.has_key? 'error' - puts " [Error] #{resp['error']}" - exit - end - @host = resp['host'].split(':').first - @tunnel = resp - return resp - rescue - puts " [Error] Unable to register tunnel. Perhaps service is down?" - exit - end - def start_tunnel - port = @port - tunnel = @tunnel - gateway = Net::SSH::Gateway.new(@host, tunnel['user'], :auth_methods => %w{ publickey }) - gateway.open_remote(port.to_i, '127.0.0.1', tunnel['through_port'].to_i) do |rp,rh| - puts " " << tunnel['banner'] if tunnel.has_key? 'banner' - if File.exists?(File.expand_path(SHELL_HOOK_FILE)) - system "#{File.expand_path(SHELL_HOOK_FILE)} ""#{tunnel['host']}""" - if !$?.success? - puts " An error occurred executing the callback hook #{SHELL_HOOK_FILE}" - puts " (Make sure it is executable)" - end + def register_tunnel(key=@key) + url = URI.parse("http://open.localtunnel.com/") + if key + resp = JSON.parse(Net::HTTP.post_form(url, {"key" => key}).body) + else + resp = JSON.parse(Net::HTTP.get(url)) end - puts " Port #{port} is now publicly accessible from http://#{tunnel['host']} ..." - begin - sleep 1 while true - rescue Interrupt - gateway.close_remote(rp, rh) + if resp.has_key? 'error' + puts " [Error] #{resp['error']}" exit end + @host = resp['host'].split(':').first + @tunnel = resp + return resp + rescue + puts " [Error] Unable to register tunnel. Perhaps service is down?" + exit + end + + def start_tunnel + port = @port + tunnel = @tunnel + gateway = Net::SSH::Gateway.new(@host, tunnel['user'], :auth_methods => %w{ publickey }) + gateway.open_remote(port.to_i, '127.0.0.1', tunnel['through_port'].to_i) do |rp,rh| + puts " " << tunnel['banner'] if tunnel.has_key? 'banner' + if File.exists?(File.expand_path(SHELL_HOOK_FILE)) + system "#{File.expand_path(SHELL_HOOK_FILE)} ""#{tunnel['host']}""" + if !$?.success? + puts " An error occurred executing the callback hook #{SHELL_HOOK_FILE}" + puts " (Make sure it is executable)" + end + end + puts " Port #{port} is now publicly accessible from http://#{tunnel['host']} ..." + begin + sleep 1 while true + rescue Interrupt + gateway.close_remote(rp, rh) + exit + end + end + rescue Net::SSH::AuthenticationFailed + possible_key = Dir[File.expand_path('~/.ssh/*.pub')].first + puts " Failed to authenticate. If this is your first tunnel, you need to" + puts " upload a public key using the -k option. Try this:\n\n" + puts " localtunnel -k #{possible_key ? possible_key : '~/path/to/key.pub'} #{port}\n\n" + puts " Don't have a key? Check out http://bit.ly/createsshkey" + exit end - rescue Net::SSH::AuthenticationFailed - possible_key = Dir[File.expand_path('~/.ssh/*.pub')].first - puts " Failed to authenticate. If this is your first tunnel, you need to" - puts " upload a public key using the -k option. Try this:\n\n" - puts " localtunnel -k #{possible_key ? possible_key : '~/path/to/key.pub'} #{port}\n\n" - puts " Don't have a key? Check out http://bit.ly/createsshkey" - exit end end + diff --git a/passageway.gemspec b/passageway.gemspec index 8a39844..fff70f5 100644 --- a/passageway.gemspec +++ b/passageway.gemspec @@ -20,4 +20,8 @@ Gem::Specification.new do |spec| spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" + + spec.add_dependency 'json' + spec.add_dependency 'net-ssh' + spec.add_dependency 'net-ssh-gateway' end diff --git a/spec/client_spec.rb b/spec/client_spec.rb new file mode 100644 index 0000000..36663e8 --- /dev/null +++ b/spec/client_spec.rb @@ -0,0 +1,6 @@ +require 'spec_helper' +require 'passageway/client' + +describe Passageway::Client do + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e69de29..a4d30ba 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -0,0 +1,2 @@ +$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') +