basic TCP connection support for ConnectorService
[scpubgit/Tak.git] / lib / Tak / ConnectorService.pm
index 15e39bf..3bcf64e 100644 (file)
@@ -1,6 +1,8 @@
 package Tak::ConnectorService;
 
 use IPC::Open2;
+use IO::Socket::UNIX;
+use IO::Socket::INET; # Sucks to be v6, see comment where used
 use IO::All;
 use Tak::Router;
 use Tak::Client;
@@ -20,13 +22,15 @@ sub handle_create {
   die [ mistake => "No target supplied to create" ] unless $on;
   my $log_level = $args{log_level}||'info';
   my ($kid_in, $kid_out, $kid_pid) = $self->_open($on, $log_level);
-  $kid_in->print($Tak::STDIONode::DATA, "__END__\n") unless $on eq '-';
-  # Need to get a handshake to indicate STDIOSetup has finished
-  # messing around with file descriptors, otherwise we can severely
-  # confuse things by sending before the dup.
-  my $up = <$kid_out>;
-  die [ failure => "Garbled response from child: $up" ]
-    unless $up eq "Ssyshere\n";
+  if ($kid_pid) {
+    $kid_in->print($Tak::STDIONode::DATA, "__END__\n") unless $on eq '-';
+    # Need to get a handshake to indicate STDIOSetup has finished
+    # messing around with file descriptors, otherwise we can severely
+    # confuse things by sending before the dup.
+    my $up = <$kid_out>;
+    die [ failure => "Garbled response from child: $up" ]
+      unless $up eq "Ssyshere\n";
+  }
   my $connection = Tak::ConnectionService->new(
     read_fh => $kid_out, write_fh => $kid_in,
     listening_service => Tak::Router->new
@@ -49,6 +53,20 @@ sub _open {
     my $kid_pid = IPC::Open2::open2(my $kid_out, my $kid_in, 'tak-stdio-node', '-', @args)
       or die "Couldn't open2 child: $!";
     return ($kid_in, $kid_out, $kid_pid);
+  } elsif ($on =~ /^\.?\//) { # ./foo or /foo
+    my $sock = IO::Socket::UNIX->new($on)
+      or die "Couldn't open unix domain socket ${on}: $!";
+    return ($sock, $sock, undef);
+  } elsif ($on =~ /:/) { # foo:80 we hope
+    # IO::Socket::IP is a better answer. But can pull in XS deps.
+    # Well, more strictly it pulls in Socket::GetAddrInfo, which can
+    # actually work without its XS implementation (just doesn't handle v6)
+    # and I've not properly pondered how to make things like fatpacking
+    # Just Fucking Work in such a circumstance. First person to need IPv6
+    # and be reading this comment, please start a conversation about it.
+    my $sock = IO::Socket::INET->new(PeerAddr => $on)
+      or die "Couldn't open TCP socket ${on}: $!";
+    return ($sock, $sock, undef);
   }
   my $ssh = $self->ssh->{$on} ||= Net::OpenSSH->new($on);
   $ssh->error and