From: Sergey Matveev Date: Thu, 14 Nov 2019 15:13:10 +0000 (+0300) Subject: Ability to dial through pipes X-Git-Tag: v5.0.0^2~2 X-Git-Url: http://www.git.cypherpunks.ru/?a=commitdiff_plain;h=2f826e9b891bcf36cdb77fb5fec27a13f7911261;p=nncp.git Ability to dial through pipes --- diff --git a/doc/cfg.texi b/doc/cfg.texi index 2004073..5a01b7d 100644 --- a/doc/cfg.texi +++ b/doc/cfg.texi @@ -46,6 +46,7 @@ Example @url{https://hjson.org/, Hjson} configuration file: addrs: { lan: "[fe80::1234%igb0]:5400" internet: alice.com:3389 + proxied: "|ssh remote.host nncp-daemon -inetd" } calls: [ { @@ -152,9 +153,12 @@ omitted if direct connection exists and no relaying is required. @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} diff --git a/doc/cmds.texi b/doc/cmds.texi index d539523..4247054 100644 --- a/doc/cmds.texi +++ b/doc/cmds.texi @@ -121,6 +121,21 @@ packets of remote node, without any transmission. 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 @@ -135,22 +150,7 @@ Optional number of @option{NODE}s tells to ignore other ones. 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 diff --git a/doc/news.ru.texi b/doc/news.ru.texi index 7411c8e..2b09a72 100644 --- a/doc/news.ru.texi +++ b/doc/news.ru.texi @@ -16,6 +16,10 @@ YAML заменён на Hjson, из-за его гораздо большей @code{Zstandard}, так как оно значительно быстрее и эффективнее, не смотря на то, что версия библиотеки ещё не проверена временем. +@item +Возможность соединяться с удалёнными нодами не только по TCP, но и через +pipe вызов сторонней команды. + @item @command{nncp-cfgnew} генерирует конфигурационный файл с множеством комментариев. Можно использовать @option{-nocomments} опцию для старого diff --git a/doc/news.texi b/doc/news.texi index f4d7dc4..5cc2e6f 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -18,6 +18,10 @@ not supported. @code{zlib} compression is replaced with @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 diff --git a/src/call.go b/src/call.go index 3f15065..fd57bd1 100644 --- a/src/call.go +++ b/src/call.go @@ -48,7 +48,13 @@ func (ctx *Ctx) CallNode( 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 diff --git a/src/cmd/nncp-daemon/main.go b/src/cmd/nncp-daemon/main.go index 318c3e4..0f7e460 100644 --- a/src/cmd/nncp-daemon/main.go +++ b/src/cmd/nncp-daemon/main.go @@ -43,20 +43,24 @@ type InetdConn struct { 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) { diff --git a/src/pipe.go b/src/pipe.go new file mode 100644 index 0000000..a5d8610 --- /dev/null +++ b/src/pipe.go @@ -0,0 +1,72 @@ +/* +NNCP -- Node to Node copy, utilities for store-and-forward data exchange +Copyright (C) 2016-2019 Sergey Matveev + +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 . +*/ + +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 +} diff --git a/src/sp.go b/src/sp.go index 5590b02..6dd724a 100644 --- a/src/sp.go +++ b/src/sp.go @@ -104,7 +104,7 @@ type FreqWithNice struct { } type ConnDeadlined interface { - io.ReadWriter + io.ReadWriteCloser SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error }