remove peripheral repositories from get_sgn_repos
[sgn-devtools.git] / dev_gateway
blob1a2a5e3a735b1cb7a33ed9d02ff3767ea9ff9498
1 #!/usr/bin/env perl
2 use strict;
3 use warnings;
5 use Pod::Usage;
6 use Getopt::Long;
8 use Memoize;
9 memoize('list_busy_ports');
11 use Socket;
13 #use Smart::Comments;
15 ### process options
16 my $gateway_host = 'sgn-devel.sgn.cornell.edu';
17 my $local_port = 80;
18 my $user = '';
19 my $gateway_port;
20 my @allowed_gateway_ports = 8080..8090;
22 GetOptions( 'port|p=i' => \$local_port,
23 'user|u=s' => \$user,
24 'remote_port|r=i' => \$gateway_port,
26 or pod2usage('invalid options');
28 $gateway_host = shift @ARGV if @ARGV;
29 pod2usage() if @ARGV;
30 $user .= '@' if $user;
32 ### make sure this is a valid hostname before trying the ssh commands
33 # (the error checking on the ssh commands leaves a bit to be desired)
34 validate_hostname( $gateway_host );
36 ### find an available port
37 my $host = "$user$gateway_host";
38 $gateway_port ||= find_available_port( $host, @allowed_gateway_ports );
40 is_port_available( $host, $gateway_port )
41 or die "Remote port $gateway_port already in use, cannot set up gateway.\n";
43 ### open the ssh connection
44 print "Forwarding local port $local_port to http://$gateway_host:$gateway_port\n";
45 print "Press Ctrl-c to close the connection.\n";
46 exec "ssh -N -R $gateway_port:localhost:$local_port '$user$gateway_host'";
49 ############ subroutines
51 sub validate_hostname {
52 my $host = shift;
53 die "Could not resolve hostname $host\n" unless gethostbyname( $host );
56 sub find_available_port {
57 my ( $ssh_host, @acceptable_ports ) = @_;
59 my $busy_ports = list_busy_ports( $ssh_host );
61 die "Failed to connect to $user$gateway_host\n"
62 unless %$busy_ports;
64 for( @acceptable_ports ) {
65 return $_ unless $busy_ports->{$_};
68 die "All remote ports seem to be busy.\n",
69 "Tried ports ".join(', ',@acceptable_ports).".\n";
72 sub list_busy_ports {
73 my ( $ssh_host ) = @_;
75 ### use netstat on the remote host to find ports that are already in use
77 my %busy_ports;
78 open( my $netstat, "ssh '$user$gateway_host' 'netstat -ltunp 2>/dev/null' |" ) or die "$! running ssh\n";
79 while( <$netstat> ) {
80 #no warnings 'uninitialized';
81 my $local = ( split )[3];
82 my ($busy_port) = $local =~ /:(\d+)/
83 or next;
84 $busy_ports{$busy_port} = 1;
87 ### busy_ports: %busy_ports
89 # hash of { port_number => 1 }
90 return \%busy_ports;
93 sub is_port_available {
94 my ( $ssh_host, $port ) = @_;
96 my $busy_ports = list_busy_ports( $ssh_host );
98 return ! $busy_ports->{$port};
101 __END__
103 =head1 NAME
105 dev_gateway - use C<ssh> to make a remote machine act as a gateway to a local port
107 =head1 SYNOPSIS
109 dev_gateway foo.example.com
111 dev_gateway -u bob -p 5432 foo.example.com
113 dev_gateway --user alice --p 3000 foo.example.com
115 =head1 OPTIONS
117 =over 8
119 =item -p --port <num>
121 Port on the local machine to forward. Default 80.
123 =item -u --user <name>
125 Username to connect as. Defaults to current local user.
127 =item -r --remote_port <number>
129 Force the remote port to use. Should usually be in the range 8080 - 8090.
131 =back
133 =cut