DDC-Concordance

 view release on metacpan or  search on metacpan

ddc-tee.perl  view on Meta::CPAN

  die(@_) if ($^S);
  error(@_);
  die(@_);
};

$SIG{$_} = \&die_gracefully
  foreach (qw(INT TERM KILL HUP));
sub die_gracefully {
  my $sig = shift;
  die("terminating on signal $sig");
}

##======================================================================
## utils

our %default_host = (peer=>'127.0.0.1', 'local'=>'0.0.0.0');

## \%connect = parseAddr($addr, $PEER_OR_LOCAL, %opts)
sub parseAddr {
  my $addr = shift;
  my $type = shift || "Peer";
  my %connect = (Domain=>'INET', UserAddr=>$addr, @_);
  if ($addr =~ m{^/} || $addr =~ s{^unix:(?://)?}{}) {
    $connect{Domain}  = 'UNIX';
    $connect{$type} = $addr;
  } else {
    $addr =~ s{^(?:inet|tcp):(?://)?}{};
    my ($host,$port) = split(':',$addr,2);
    ($port,$host) = ($host,$port) if (!$port);
    $host ||= $default_host{lc($type)};
    @connect{"${type}Addr","${type}Port"} = ($host,$port);
  }
  return \%connect;
}


## $str = addrstr($addr, $PEER_OR_LOCAL)
## $str = addrstr(\%addr,$PEER_OR_LOCAL)
## $str = addrstr($dcli, $PEER_OR_LOCAL)
## $str = addrstr($sock, $PEER_OR_LOCAL)
sub addrstr {
  my ($addr,$prefix) = @_;
  $prefix ||= 'Peer';
  return (UNIVERSAL::isa($addr,'DDC::Client')
          ? $addr->addrStr(undef,$prefix)
          : DDC::Client->addrStr($addr,$prefix));
}

## $bool = write_pidfile($pid => $pidfile)
sub write_pidfile {
  my ($pid,$pidfile) = @_;
  return if (!defined($pidfile));
  open(my $fh, ">$pidfile")
    or die("$prog: open failed for $pidfile: $!");
  print $fh $pid, "\n";
  close($fh)
    or die("$prog: close failed for $pidfile: $!");
}

##======================================================================
## callbacks


## undef = cb_client($cli_sock)
sub cb_client {
  my $csock = shift;
  my $cli   = DDC::Client->new( sock=>$csock, encoding=>undef );
  my $req   = $cli->readData();

  ##-- spawn clients
  for (my $bi=1; $bi <= $#b_clients; ++$bi) {
    threads->new(\&cb_client_channel, undef, $req, $b_clients[$bi])->detach();
  }
  cb_client_channel($cli, $req, $b_clients[0]) if (@b_clients);
}

## undef = cb_client_channel($cli_or_undef, $req, $backend_cli)
sub cb_client_channel {
  my ($cli,$req,$bcli) = @_;
  #$prog .= "#".threads->tid();

  if ($cli) {
    ##-- primary back-end: 2-way communications REQUEST<->BCLI
    trace("wrap ", addrstr($cli->{sock}), " <-> ", addrstr($bcli), "\n");
    my $rsp = $bcli->requestNC($req);
    while (defined($rsp) && $cli->{sock}->connected) {
      $cli->send($rsp);
      $req = $rsp = undef;
      eval { $req = $cli->readData(); };
      $@ = '';
      last if (!defined($req));
      $rsp = $bcli->requestNC($req);
    }
    $cli->close();
  }
  if (!$cli) {
    ##-- secondary back-end: 1-way communications REQUEST->BCLI
    trace("forward -> ", addrstr($bcli), "\n");
    $bcli->requestNC($req);
  }
  $bcli->close();
}

##======================================================================
## MAIN

##-- setup logging
if ($verbose !~ /^[0-9]+$/) {
  if (exists($verbose{lc($verbose)})) {
    $verbose = $verbose{lc($verbose)};
  } else {
    warn("$prog: unknown verbosity level '$verbose' - using 'info'");
    $verbose = $verbose{info};
  }
}
if ($log_syslog) {
  openlog($prog, "pid", LOG_DAEMON)
    or die("$prog: failed to open connection to syslog: $!");
  setlogmask( LOG_UPTO(vprio($verbose)) );
}



( run in 1.610 second using v1.01-cache-2.11-cpan-140bd7fdf52 )