addrs: {
lan: "[fe80::1234%igb0]:5400"
internet: alice.com:3389
+ proxied: "|ssh remote.host nncp-daemon -inetd"
}
calls: [
{
@anchor{CfgAddrs}
@item addrs
Dictionary containing known network addresses of the node. Each key is
-human-readable name of the link/address. Values are @verb{|addr:port|}
-pairs pointing to @ref{nncp-daemon}'s listening instance. May be omitted
-if either no direct connection exists, or @ref{nncp-call} is used with
+human-readable name of the address. For direct TCP connections use
+@verb{|host:port|} format, pointing to @ref{nncp-daemon}'s listening
+instance. Also you can pipe connection through the external command
+using @verb{#|some command#} format. @code{/bin/sh -c "some command"}
+will start and its stdin/stdout used as a connection. May be omitted if
+either no direct connection exists, or @ref{nncp-call} is used with
forced address specifying.
@anchor{CfgXxRate}
You can specify what packets your want to download, by specifying
@option{-pkts} option with comma-separated list of packets identifiers.
+Each @option{NODE} can contain several uniquely identified
+@option{ADDR}esses in @ref{CfgAddrs, configuration} file. If you do
+not specify the exact one, then all will be tried until the first
+success. Optionally you can force @option{FORCEADDR} address usage,
+instead of addresses taken from configuration file. You can specify both
+@verb{|host:port|} and @verb{#|some command#} formats.
+
+Pay attention that this command runs integrity check for each completely
+received packet in the background. This can be time consuming.
+Connection could be lost during that check and remote node won't be
+notified that file is done. But after successful integrity check that
+file is renamed from @file{.part} one and when you rerun
+@command{nncp-call} again, remote node will receive completion
+notification.
+
@node nncp-caller
@section nncp-caller
Otherwise all nodes with specified @emph{calls} configuration
field will be called.
-@option{-onlinedeadline} overrides @ref{CfgOnlineDeadline,
-@emph{onlinedeadline}} configuration option.
-
-Each @option{NODE} can contain several uniquely identified
-@option{ADDR}esses in @ref{CfgAddrs, configuration} file. If you do
-not specify the exact one, then all will be tried until the first
-success. Optionally you can force @option{FORCEADDR} address usage,
-instead of addresses taken from configuration file.
-
-Pay attention that this command runs integrity check for each completely
-received packet in the background. This can be time consuming.
-Connection could be lost during that check and remote node won't be
-notified that file is done. But after successful integrity check that
-file is renamed from @file{.part} one and when you rerun
-@command{nncp-call} again, remote node will receive completion
-notification.
+Look @ref{nncp-call} for more information.
@node nncp-cfgenc
@section nncp-cfgenc
@code{Zstandard}, так как оно значительно быстрее и эффективнее, не
смотря на то, что версия библиотеки ещё не проверена временем.
+@item
+Возможность соединяться с удалёнными нодами не только по TCP, но и через
+pipe вызов сторонней команды.
+
@item
@command{nncp-cfgnew} генерирует конфигурационный файл с множеством
комментариев. Можно использовать @option{-nocomments} опцию для старого
@code{Zstandard}, due to its speed and efficiency, despite library
version is not mature enough.
+@item
+Ability to call remote nodes via pipe call of external command, not only
+through TCP.
+
@item
@command{nncp-cfgnew} generates configuration file with many
comments. @option{-nocomments} option can be used for an old
for _, addr := range addrs {
sds := SDS{"node": node.Id, "addr": addr}
ctx.LogD("call", sds, "dialing")
- conn, err := net.Dial("tcp", addr)
+ var conn ConnDeadlined
+ var err error
+ if addr[0] == '|' {
+ conn, err = NewPipeConn(addr[1:])
+ } else {
+ conn, err = net.Dial("tcp", addr)
+ }
if err != nil {
ctx.LogD("call", SdsAdd(sds, SDS{"err": err}), "dialing")
continue
w *os.File
}
-func (ic *InetdConn) Read(p []byte) (n int, err error) {
- return ic.r.Read(p)
+func (c InetdConn) Read(p []byte) (n int, err error) {
+ return c.r.Read(p)
}
-func (ic *InetdConn) Write(p []byte) (n int, err error) {
- return ic.w.Write(p)
+func (c InetdConn) Write(p []byte) (n int, err error) {
+ return c.w.Write(p)
}
-func (ic *InetdConn) SetReadDeadline(t time.Time) error {
- return ic.r.SetReadDeadline(t)
+func (c InetdConn) SetReadDeadline(t time.Time) error {
+ return c.r.SetReadDeadline(t)
}
-func (ic *InetdConn) SetWriteDeadline(t time.Time) error {
- return ic.w.SetWriteDeadline(t)
+func (c InetdConn) SetWriteDeadline(t time.Time) error {
+ return c.w.SetWriteDeadline(t)
+}
+
+func (c InetdConn) Close() error {
+ return c.w.Close()
}
func performSP(ctx *nncp.Ctx, conn nncp.ConnDeadlined, nice uint8) {
--- /dev/null
+/*
+NNCP -- Node to Node copy, utilities for store-and-forward data exchange
+Copyright (C) 2016-2019 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package nncp
+
+import (
+ "os"
+ "os/exec"
+ "time"
+)
+
+type PipeConn struct {
+ cmd *exec.Cmd
+ r *os.File
+ w *os.File
+}
+
+func NewPipeConn(command string) (ConnDeadlined, error) {
+ cmd := exec.Command("/bin/sh", "-c", command)
+ stdinR, stdinW, err := os.Pipe()
+ if err != nil {
+ return nil, err
+ }
+ cmd.Stdin = stdinR
+ stdoutR, stdoutW, err := os.Pipe()
+ if err != nil {
+ return nil, err
+ }
+ cmd.Stdout = stdoutW
+ err = cmd.Start()
+ if err != nil {
+ return nil, err
+ }
+ return &PipeConn{cmd, stdoutR, stdinW}, nil
+}
+
+func (c PipeConn) Read(p []byte) (n int, err error) {
+ return c.r.Read(p)
+}
+
+func (c PipeConn) Write(p []byte) (n int, err error) {
+ return c.w.Write(p)
+}
+
+func (c PipeConn) SetReadDeadline(t time.Time) error {
+ return c.r.SetReadDeadline(t)
+}
+
+func (c PipeConn) SetWriteDeadline(t time.Time) error {
+ return c.w.SetWriteDeadline(t)
+}
+
+func (c PipeConn) Close() (err error) {
+ err = c.w.Close()
+ go c.cmd.Wait()
+ time.AfterFunc(time.Duration(10*time.Second), func() { c.cmd.Process.Kill() })
+ return
+}
}
type ConnDeadlined interface {
- io.ReadWriter
+ io.ReadWriteCloser
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
}