]> Cypherpunks.ru repositories - nncp.git/commitdiff
Merge branch 'develop' 3.0
authorSergey Matveev <stargrave@stargrave.org>
Sun, 18 Feb 2018 16:15:59 +0000 (19:15 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 18 Feb 2018 16:15:59 +0000 (19:15 +0300)
76 files changed:
README
README.RU
VERSION
common.mk
doc/about.ru.texi
doc/about.texi
doc/aria2-downloaded.sh [new file with mode: 0755]
doc/call.texi
doc/cfg.texi
doc/chunked.texi
doc/cmds.texi
doc/comparison.ru.texi
doc/comparison.texi
doc/download.texi
doc/index.texi
doc/install.texi
doc/integration.texi
doc/news.ru.texi
doc/news.texi
doc/niceness.texi
doc/pkt.texi
doc/usecases.ru.texi
doc/usecases.texi
doc/warcer.sh [new file with mode: 0755]
doc/wgeter.sh [new file with mode: 0755]
doc/workflow.texi
makedist.sh
ports/nncp/Makefile
ports/nncp/files/nncp.newsyslog.conf.sample [moved from ports/nncp/files/nncp.newsyslog.conf.sample.in with 100% similarity]
ports/nncp/files/pkg-message.in
ports/nncp/pkg-descr
ports/nncp/pkg-plist [new file with mode: 0644]
src/chacha20
src/cypherpunks.ru/balloon
src/cypherpunks.ru/nncp/call.go
src/cypherpunks.ru/nncp/cfg.go
src/cypherpunks.ru/nncp/check.go
src/cypherpunks.ru/nncp/chunked.go
src/cypherpunks.ru/nncp/cmd/nncp-bundle/main.go
src/cypherpunks.ru/nncp/cmd/nncp-call/main.go
src/cypherpunks.ru/nncp/cmd/nncp-caller/main.go
src/cypherpunks.ru/nncp/cmd/nncp-cfgenc/main.go
src/cypherpunks.ru/nncp/cmd/nncp-cfgmin/main.go
src/cypherpunks.ru/nncp/cmd/nncp-cfgnew/main.go
src/cypherpunks.ru/nncp/cmd/nncp-check/main.go
src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go
src/cypherpunks.ru/nncp/cmd/nncp-exec/main.go [moved from src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go with 50% similarity]
src/cypherpunks.ru/nncp/cmd/nncp-file/main.go
src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go
src/cypherpunks.ru/nncp/cmd/nncp-log/main.go
src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go
src/cypherpunks.ru/nncp/cmd/nncp-reass/main.go
src/cypherpunks.ru/nncp/cmd/nncp-rm/main.go
src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go
src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go
src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go
src/cypherpunks.ru/nncp/ctx.go
src/cypherpunks.ru/nncp/eblob.go
src/cypherpunks.ru/nncp/humanizer.go
src/cypherpunks.ru/nncp/jobs.go
src/cypherpunks.ru/nncp/lockdir.go
src/cypherpunks.ru/nncp/log.go
src/cypherpunks.ru/nncp/nncp.go
src/cypherpunks.ru/nncp/node.go
src/cypherpunks.ru/nncp/pkt.go
src/cypherpunks.ru/nncp/pkt_test.go
src/cypherpunks.ru/nncp/sp.go
src/cypherpunks.ru/nncp/tmp.go
src/cypherpunks.ru/nncp/toss.go
src/cypherpunks.ru/nncp/toss_test.go
src/cypherpunks.ru/nncp/tx.go
src/cypherpunks.ru/nncp/tx_test.go
src/github.com/flynn/noise
src/golang.org/x/crypto
src/golang.org/x/net
src/golang.org/x/sys

diff --git a/README b/README
index dab1ca8fb45b7576e91d88b58c9e649dcc020231..58db3ed563e76b28d8ba89dd946fe5c692d206f9 100644 (file)
--- a/README
+++ b/README
@@ -1,13 +1,14 @@
 NNCP (Node to Node copy) is a collection of utilities simplifying
-secure store-and-forward files and mail exchanging.
+secure store-and-forward files, mail and commands exchanging.
 
 This utilities are intended to help build up small size (dozens of
-nodes) ad-hoc friend-to-friend (F2F) statically routed darknet networks
-for fire-and-forget secure reliable files, file requests and Internet
-mail transmission. All packets are integrity checked, end-to-end
-encrypted (E2EE), explicitly authenticated by known participants public
-keys. Onion encryption is applied to relayed packets. Each node acts
-both as a client and server, can use push and poll behaviour model.
+nodes) ad-hoc friend-to-friend (F2F) statically routed darknet
+delay-tolerant networks for fire-and-forget secure reliable files, file
+requests, Internet mail and commands transmission. All packets are
+integrity checked, end-to-end encrypted (E2EE), explicitly authenticated
+by known participants public keys. Onion encryption is applied to
+relayed packets. Each node acts both as a client and server, can use
+push and poll behaviour model.
 
 Out-of-box offline sneakernet/floppynet, dead drops, sequential and
 append-only CD-ROM/tape storages, air-gapped computers support. But
index eccba53fffa5a08560a3c5d81f4b70a79f3d8309..ba9829c499d86fe6c3dff9e2ddd3c25b86d551b1 100644 (file)
--- a/README.RU
+++ b/README.RU
@@ -1,10 +1,10 @@
 NNCP (Node to Node copy) это набор утилит упрощающий безопасный обмен
 файлами и почтой в режиме сохранить-и-переслать.
 
-ЭÑ\82и Ñ\83Ñ\82илиÑ\82Ñ\8b Ð¿Ñ\80едназнаÑ\87енÑ\8b Ð¿Ð¾Ð¼Ð¾Ñ\87Ñ\8c Ñ\81 Ð¿Ð¾Ñ\81Ñ\82Ñ\80оением Ð¾Ð´Ð½Ð¾Ñ\80анговÑ\8bÑ\85 Ñ\81еÑ\82ей
-небольшого размера (дюжины узлов), в режиме друг-к-другу (F2F) со
-статической маршрутизацией для безопасной надёжной передачи файлов,
-запросов на передачу файлов и Интернет почты по принципу
+ЭÑ\82и Ñ\83Ñ\82илиÑ\82Ñ\8b Ð¿Ñ\80едназнаÑ\87енÑ\8b Ð¿Ð¾Ð¼Ð¾Ñ\87Ñ\8c Ñ\81 Ð¿Ð¾Ñ\81Ñ\82Ñ\80оением Ð¾Ð´Ð½Ð¾Ñ\80анговÑ\8bÑ\85 Ñ\83Ñ\81Ñ\82ойÑ\87ивÑ\8bÑ\85 Ðº
+разрывам сетей небольшого размера (дюжины узлов), в режиме друг-к-другу
+(F2F) со статической маршрутизацией для безопасной надёжной передачи
+файлов, запросов на передачу файлов, Интернет почты и команд по принципу
 выстрелил-и-забыл. Все пакеты проверяются на целостность, шифруются по
 принципу точка-точка (E2EE), аутентифицируются известными публичными
 ключами участников. Луковичное (onion) шифрование применяется ко всем
diff --git a/VERSION b/VERSION
index cd5ac039d67e0bdadb17976e4ac39f0ffe6bb6e4..9f55b2ccb5f234fc6b87ada62389a3d73815d0d1 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0
+3.0
index 34d6404a03ac15ac6e14eb6137639e9a148f9403..145e84397c3edbb4a656913382eda6dcc950d392 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -25,10 +25,10 @@ ALL = \
        nncp-cfgnew \
        nncp-check \
        nncp-daemon \
+       nncp-exec \
        nncp-file \
        nncp-freq \
        nncp-log \
-       nncp-mail \
        nncp-pkt \
        nncp-reass \
        nncp-rm \
@@ -62,6 +62,9 @@ nncp-check:
 nncp-daemon:
        GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-daemon
 
+nncp-exec:
+       GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-exec
+
 nncp-file:
        GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-file
 
@@ -71,9 +74,6 @@ nncp-freq:
 nncp-log:
        GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-log
 
-nncp-mail:
-       GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-mail
-
 nncp-pkt:
        GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-pkt
 
@@ -93,7 +93,7 @@ nncp-xfer:
        GOPATH=$(GOPATH) go build -ldflags "$(LDFLAGS)" cypherpunks.ru/nncp/cmd/nncp-xfer
 
 test:
-       GOPATH=$(GOPATH) go test cypherpunks.ru/nncp/...
+       GOPATH=$(GOPATH) go test -failfast cypherpunks.ru/nncp/...
 
 clean:
        rm -f $(ALL)
index 727402c4a3512a6847107263550f1dd21965f4e6..526d37fa62d3786c522652a1312ef7ac32f3f790 100644 (file)
@@ -4,11 +4,12 @@
 NNCP (Node to Node copy) это набор утилит упрощающий безопасный обмен
 файлами и почтой в режиме сохранить-и-переслать.
 
-Эти утилиты предназначены помочь с построением однораговых сетей
+Эти утилиты предназначены помочь с построением однораговых
+@url{https://ru.wikipedia.org/wiki/DTN, устойчивых к разрывам} сетей
 небольшого размера (дюжины узлов), в режиме
 @url{https://ru.wikipedia.org/wiki/Friend-to-friend, друг-к-другу} (F2F)
 со статической маршрутизацией для безопасной надёжной передачи файлов,
-запросов на передачу файлов и Интернет почты по принципу
+запросов на передачу файлов, Интернет почты и команд по принципу
 выстрелил-и-забыл. Все пакеты проверяются на целостность, шифруются по
 принципу @url{https://en.wikipedia.org/wiki/End-to-end_encryption,
 точка-точка}, аутентифицируются известными публичными ключами
index ffe4be082a5411e57eac6e0598d9670de59782e3..4a7ab0560db6d68dff294dfa254d47b7d71953e2 100644 (file)
@@ -6,14 +6,15 @@ See also this page @ref{Об утилитах, on russian}.
 This utilities are intended to help build up small size (dozens of
 nodes) ad-hoc @url{https://en.wikipedia.org/wiki/Friend-to-friend,
 friend-to-friend} (F2F) statically routed
-@url{https://en.wikipedia.org/wiki/Darknet, darknet} networks for
-fire-and-forget secure reliable files, file requests and Internet mail
-transmission. All packets are integrity checked,
-@url{https://en.wikipedia.org/wiki/End-to-end_encryption, end-to-end}
-encrypted, explicitly authenticated by known participants public keys.
-@url{https://en.wikipedia.org/wiki/Onion_routing, Onion encryption} is
-applied to relayed packets. Each node acts both as a client and server,
-can use push and poll behaviour model.
+@url{https://en.wikipedia.org/wiki/Darknet, darknet}
+@url{https://en.wikipedia.org/wiki/Delay-tolerant_networking, delay-tolerant}
+networks for fire-and-forget secure reliable files, file requests,
+Internet mail and commands transmission. All packets are integrity
+checked, @url{https://en.wikipedia.org/wiki/End-to-end_encryption,
+end-to-end} encrypted, explicitly authenticated by known participants
+public keys. @url{https://en.wikipedia.org/wiki/Onion_routing, Onion
+encryption} is applied to relayed packets. Each node acts both as a
+client and server, can use push and poll behaviour model.
 
 Out-of-box offline @url{https://en.wikipedia.org/wiki/Sneakernet,
 sneakernet/floppynet}, @url{https://en.wikipedia.org/wiki/Dead_drop,
diff --git a/doc/aria2-downloaded.sh b/doc/aria2-downloaded.sh
new file mode 100755 (executable)
index 0000000..0a1c776
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+TORRENTS_DIR=/storage/torrents
+REMOTE=stargrave.org
+
+if [ "$2" -eq 0 ]; then
+    # downloaded .torrent/.metalink
+    exit 0
+fi
+
+if [ "$2" -gt 1 ]; then
+    cd "$3"
+    while [ "$(pwd)" != $TORRENTS_DIR ]; do
+        name="$(basename "$(pwd)")"
+        cd ..
+    done
+    tartmp=$(mktemp ./finished.XXXXXX)
+    tar cf $tartmp "$name"
+    nncp-file $tartmp $REMOTE:"$name".tar
+    rm $tartmp
+else
+    nncp-file "$3" $REMOTE:
+fi
index f65a2f824e2d4850554a7fc195e05a72e41edd54..31d8f82ab6aab13cc815904e989f97813a5d0096 100644 (file)
@@ -151,7 +151,7 @@ and a wildcard year field is appended, that is, @verb{|* * * * Mon|}
 internally become @verb{|0 * * * * Mon *|}.
 @item
 Domain for day-of-week field is [0-7] instead of [0-6], 7 being Sunday
-(like 0). This to comply with @url{http://linux.die.net/man/5/crontab}.
+(like 0). This to comply with @url{https://linux.die.net/man/5/crontab}.
 @end itemize
 
 @item nice
index 0420d3959fec7352b25e7695cd1159fec9d3f12a..5be0382bd69628ff5980d37b1abe971d548a36db 100644 (file)
@@ -27,13 +27,15 @@ neigh:
     exchpub: CYVGQ...PSEWQ
     signpub: 2NMVC...CMH5Q
     noisepub: KIBKK...ESM7Q
-    sendmail: [/usr/sbin/sendmail]
+    exec:
+      sendmail: [/usr/sbin/sendmail]
   alice:
     id: XJZBK...65IJQ
     exchpub: MJACJ...FAI6A
     signpub: T4AFC...N2FRQ
     noisepub: UBM5K...VI42A
-    sendmail: ["/bin/sh", "-c", "false"]
+    exec:
+      flag: ["/usr/bin/touch", "-t"]
     incoming: /home/alice/incoming
     onlinedeadline: 1800
     maxonlinetime: 3600
@@ -47,7 +49,10 @@ neigh:
     id: 2IZNP...UYGYA
     exchpub: WFLMZ...B7NHA
     signpub: GTGXG...IE3OA
-    sendmail: [/usr/sbin/sendmail]
+    exec:
+      sendmail: [/usr/sbin/sendmail]
+      warcer: [/path/to/warcer.sh]
+      wgeter: [/path/to/wgeter.sh]
     freq: /home/bob/pub
     freqchunked: 1024
     freqminsize: 2048
@@ -62,9 +67,9 @@ log} file.
 @strong{notify} section contains notification settings for successfully
 tossed file and freq packets. Corresponding @strong{from} and
 @strong{to} fields will be substituted in notification email message.
-@emph{neigh/self/sendmail} will be used as a local mailer. You can omit
-either of those two @emph{from}/@emph{to} sections to omit corresponding
-notifications, or the whole section at once.
+@emph{neigh/self/exec/sendmail} will be used as a local mailer. You can
+omit either of those two @emph{from}/@emph{to} sections to omit
+corresponding notifications, or the whole section at once.
 
 @strong{self} section contains our node's private keypairs.
 @strong{exch*} and @strong{sign*} are used during @ref{Encrypted,
@@ -85,13 +90,25 @@ node has the following fields:
 If present, then node can be online called using @ref{Sync,
 synchronization protocol}. Contains authentication public key.
 
-@anchor{CfgSendmail}
-@item sendmail
-An array containing path to executable and its command line arguments
-that is called for mail sending. If it is empty, then no mail processing
-will be performed from that node. Sendmail command
-@command{["/bin/foo", "bar"]} called the following way:
-@command{NNCP_SENDER=NODEID /bin/foo bar RCPT1 RCPT2 ... < MSG}.
+@anchor{CfgExec}
+@item exec
+Dictionary consisting of handles and corresponding command line
+arguments. In example above there are @command{sendmail} handles,
+@command{warcer}, @command{wgeter} and @command{flag} one. Remote node
+can queue some handle execution with providing additional command line
+arguments and the body fed to command's stdin.
+
+@verb{|sendmail: ["/usr/sbin/sendmail", "-t"]|} handle, when called by
+@verb{|echo hello world | nncp-exec OURNODE sendmail ARG0 ARG1 ARG2|}
+command, will execute:
+
+@verbatim
+echo hello world |
+    NNCP_SELF=OURNODE \
+    NNCP_SENDER=REMOTE \
+    NNCP_NICE=64 \
+    /usr/sbin/sendmail -t ARG0 ARG1 ARG2
+@end verbatim
 
 @anchor{CfgIncoming}
 @item incoming
@@ -111,6 +128,7 @@ freqing. This is the desired chunk size in KiBs.
 If set, then apply @ref{OptMinSize, -minsize} option during file
 transmission.
 
+@anchor{CfgVia}
 @item via
 An array of node identifiers that will be used as a relay to that node.
 For example @verb{|[foo,bar]|} means that packet can reach current node
index 1682cc35ad83a50c576630f621d039fd177fb4d4..4ac50b7a139889e422cce0b9fc68220f2fd73125 100644 (file)
@@ -43,3 +43,13 @@ size and their hash checksums. This is
     variable length array of 32 byte fixed length opaque data @tab
     BLAKE2b-256 checksum of each chunk
 @end multitable
+
+@anchor{ChunkedZFS}
+It is strongly advisable to reassemble incoming chunked files on
+@url{https://en.wikipedia.org/wiki/ZFS, ZFS} dataset with deduplication
+feature enabled. It could be more CPU and memory hungry, but will save
+your disk's IO and free space from pollution (although temporary). But
+pay attention that you chunks must be either equal to, or divisible by
+dataset's @option{recordsize} value for deduplication workability.
+Default ZFS's @option{recordsize} is 128 KiBs, so it is advisable to
+chunk your files on 128, 256, 384, 512, etc KiB blocks.
index 9868443f47a1c46f55717f8fb5a4f9b3cedac4fb..e7090afff73fe4d0d7be71d68bd4937d9602872d 100644 (file)
@@ -18,8 +18,15 @@ Nearly all commands have the following common options:
 @item -nice
     Set desired outgoing packet @ref{Niceness, niceness level}.
     1-255 values are allowed.
+@item -replynice
+    Set desired reply packet @ref{Niceness, niceness level}. Only freq
+    and exec packets look at that niceness level. 1-255 values are
+    allowed.
 @item -node
     Process only single specified node.
+@item -via
+    Override @ref{CfgVia, via} configuration option for destination node.
+    Specified nodes must be separated with comma: @verb{|NODE1,NODE2|}.
 @item -spool
     Override path to spool directory. May be specified by
     @env{NNCPSPOOL} environment variable.
@@ -230,6 +237,39 @@ time to time.
 can handle. @option{-bind} option specifies @option{addr:port} it must
 bind to and listen.
 
+@node nncp-exec
+@section nncp-exec
+
+@verbatim
+% nncp-exec [options] NODE HANDLE [ARG0 ARG1 ...]
+@end verbatim
+
+Send execution command to @option{NODE} for specified @option{HANDLE}.
+Body is read from stdin and compressed. After receiving, remote side
+will execute specified @ref{CfgExec, handle} command with @option{ARG*}
+appended and decompressed body fed to command's stdin.
+
+For example, if remote side has following configuration file for your
+node:
+
+@verbatim
+exec:
+  sendmail: [/usr/sbin/sendmail, "-t"]
+  appender: ["/bin/sh", "-c", "cat >> /append"]
+@end verbatim
+
+then executing @verb{|echo My message | nncp-exec -replynice 123 REMOTE
+sendmail root@localhost|} will lead to executing of:
+
+@verbatim
+echo My message |
+    NNCP_SELF=REMOTE \
+    NNCP_SENDER=OurNodeId \
+    NNCP_NICE=123 \
+    /usr/sbin/sendmail -t root@localhost
+@end verbatim
+
+
 @node nncp-file
 @section nncp-file
 
@@ -260,7 +300,8 @@ If @option{-chunked} is specified, then source file will be split
 @ref{Chunked, on chunks}. @option{INT} is the desired chunk size in
 KiBs. This mode is more CPU hungry. Pay attention that chunk is saved in
 spool directory immediately and it is not deleted if any error occurs.
-@option{-minsize} option is applied per each chunk.
+@option{-minsize} option is applied per each chunk. Do not forget about
+@ref{ChunkedZFS, possible} ZFS deduplication issues.
 
 If @ref{CfgNotify, notification} is enabled on the remote side for
 file transmissions, then it will sent simple letter after successful
@@ -291,19 +332,6 @@ queuing.
 
 Parse @ref{Log, log} file and print out its records in human-readable form.
 
-@node nncp-mail
-@section nncp-mail
-
-@verbatim
-% nncp-mail [options] NODE USER ...
-@end verbatim
-
-Send mail, that is read from stdin, to @option{NODE} and specified
-@option{USER}s. Mail message will be compressed. After receiving, remote
-side will execute specified @ref{CfgSendmail, sendmail} command with
-@option{USER}s appended as a command line argument and feed decompressed
-mail body to that command's stdin.
-
 @node nncp-pkt
 @section nncp-pkt
 
@@ -399,6 +427,8 @@ Checksums:
     3: 0e9e229501bf0ca42d4aa07393d19406d40b179f3922a3986ef12b41019b45a3
 @end verbatim
 
+ Do not forget about @ref{ChunkedZFS, possible} ZFS deduplication issues.
+
 @node nncp-rm
 @section nncp-rm
 
@@ -445,7 +475,14 @@ queues.
 @section nncp-toss
 
 @verbatim
-% nncp-toss [options] [-dryrun] [-cycle INT] [-seen]
+% nncp-toss [options]
+    [-dryrun]
+    [-cycle INT]
+    [-seen]
+    [-nofile]
+    [-nofreq]
+    [-nomail]
+    [-notrns]
 @end verbatim
 
 Perform "tossing" operation on all inbound packets. This is the tool
@@ -465,6 +502,9 @@ successful tossing of @file{XXX} packet. @ref{nncp-xfer} and
 @ref{nncp-bundle} commands skip inbound packets that has been already
 seen, processed and tossed. This is helpful to defeat duplicates.
 
+@option{-nofile}, @option{-nofreq}, @option{-nomail}, @option{-notrns}
+options allow to disable any kind of packet types processing.
+
 @node nncp-xfer
 @section nncp-xfer
 
index 73580ae68279dfd5d79439e2b0de66bc6967e347..5c90671d636f63ea219be645b09b580a579e799b 100644 (file)
@@ -15,7 +15,7 @@
 @item Передача новостей @tab @strong{Да} @tab @strong{Да} @tab Нет @tab Нет
 @item Передача файлов @tab @strong{Да} @tab @strong{Да} @tab @strong{Да} @tab Нет
 @item Разбиение файлов на части @tab Нет @tab @strong{Да} @tab @strong{Да} @tab Нет
-@item Удалённое исполнение команд @tab @strong{Да} @tab Нет @tab Нет @tab Нет
+@item Удалённое исполнение команд @tab @strong{Да} @tab Нет @tab @strong{Да} @tab Нет
 @item Возобновляемое скачивание @tab @strong{Да} @tab @strong{Да} @tab @strong{Да} @tab Нет
 @item Приоритезация пакетов @tab @strong{Да} @tab Нет @tab @strong{Да} @tab Нет
 @item Сжатие почты @tab Нет @tab @strong{Да} @tab @strong{Да} @tab Нет
index e8edddd32e91383cf2fb12f20913d990f662a733..03087c1c73fcf83e81d7a7abc826953d1575a90a 100644 (file)
@@ -14,7 +14,7 @@ FidoNet} Technology Networks) and @url{https://en.wikipedia.org/wiki/SMTP, SMTP}
 @item News transmission @tab @strong{Yes} @tab @strong{Yes} @tab No @tab No
 @item File transmission @tab @strong{Yes} @tab @strong{Yes} @tab @strong{Yes} @tab No
 @item Chunked files @tab No @tab @strong{Yes} @tab @strong{Yes} @tab No
-@item Remote command execution @tab @strong{Yes} @tab No @tab No @tab No
+@item Remote command execution @tab @strong{Yes} @tab No @tab @strong{Yes} @tab No
 @item Resumable downloads @tab @strong{Yes} @tab @strong{Yes} @tab @strong{Yes} @tab No
 @item Packets prioritizing @tab @strong{Yes} @tab No @tab @strong{Yes} @tab No
 @item Mail compression @tab No @tab @strong{Yes} @tab @strong{Yes} @tab No
index 7ee1b99a92dbb040ff36adf654d0f585fa2ab0bb..cecc89b2afa8292558ef25a1ca901a116a437b82 100644 (file)
@@ -23,6 +23,10 @@ Tarballs include all necessary required libraries:
 @multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
 @headitem Version @tab Size @tab Tarball @tab SHA256 checksum
 
+@item @ref{Release 2.0, 2.0} @tab 986 KiB
+@tab @url{download/nncp-2.0.tar.xz, link} @url{download/nncp-2.0.tar.xz.sig, sign}
+@tab @code{BEF31B13 FB25381E A511FB77 067798AB 27409238 BDF5600F E2EADB29 E5E78996}
+
 @item @ref{Release 1.0, 1.0} @tab 987 KiB
 @tab @url{download/nncp-1.0.tar.xz, link} @url{download/nncp-1.0.tar.xz.sig, sign}
 @tab @code{68BF7803 CD25F59A 56D9FD6C 695002B5 BFBAF591 8A6583F4 3139FC28 CA1AB4AF}
index a01d6545287abb47636bf7e838d870ada6f6e130..1b5c5e03c94b8b07499e3c9c4204a891e155213a 100644 (file)
@@ -6,7 +6,7 @@
 This manual is for NNCP (Node to Node copy) --  collection of utilities
 simplifying secure store-and-forward files and mail exchanging.
 
-Copyright @copyright{} 2016-2017 @email{stargrave@@stargrave.org, Sergey Matveev}
+Copyright @copyright{} 2016-2018 @email{stargrave@@stargrave.org, Sergey Matveev}
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
index a3c1cc2ead95f77f0b4b3cd4d7fa9917527c50b8..3f2131bd22899fa88e875c593773abdf7e3d3749 100644 (file)
@@ -5,7 +5,7 @@ Possibly NNCP package already exists for your distribution:
 
 @itemize
 @item @url{https://github.com/voidlinux/void-packages/blob/master/srcpkgs/nncp/template, Void Linux}
-@item @url{https://git.cypherpunks.ru/cgit.cgi/nncp.git/tree/ports/nncp, FreeBSD currently uncommitted port}
+@item @url{https://www.freshports.org/net/nncp/, FreeBSD ports}
 @end itemize
 
 NNCP should run on any POSIX-compatible operating system.
index c27cb363afdf6852642817bb1e99da1fd2196142..bd531193617d376d4d11d97db8489ac62dfdf775 100644 (file)
@@ -9,6 +9,7 @@ making them store-and-forward friendly.
 * Web feeds: Feeds.
 * Web pages: WARCs.
 * BitTorrent and huge files: BitTorrent.
+* Downloading service: DownloadService.
 * Git::
 * Multimedia streaming: Multimedia.
 @end menu
@@ -27,7 +28,7 @@ mail to a LAN that is connected via NNCP.
 
 @itemize
 
-@item You need an @ref{nncp-mail} program that extracts the sender
+@item You need an @ref{nncp-exec} program that extracts the sender
 address from mail that arrives via NNCP, and that feeds the mail into
 the Postfix @command{sendmail} command.
 
@@ -36,13 +37,13 @@ delivery via NNCP:
 @verbatim
 /usr/local/etc/postfix/master.cf:
 nncp      unix  -       n       n       -       -       pipe
-          flags=F user=nncp argv=nncp-mail -quiet $nexthop $recipient
+          flags=F user=nncp argv=nncp-exec -quiet $nexthop sendmail $recipient
 @end verbatim
 
-This runs the @command{nncp-mail} command to place outgoing mail into
+This runs the @command{nncp-exec} command to place outgoing mail into
 the NNCP queue after replacing @var{$nexthop} by the the receiving NNCP
 node and after replacing @var{$recipient} by the recipients. The
-@command{pipe(8)} delivery agent executes the @command{nncp-mail}
+@command{pipe(8)} delivery agent executes the @command{nncp-exec}
 command without assistance from the shell, so there are no problems with
 shell meta characters in command-line parameters.
 
@@ -89,7 +90,7 @@ Here is how to relay mail from a LAN via NNCP to the Internet.
 
 @itemize
 
-@item You need an @ref{nncp-mail} program that extracts the sender
+@item You need an @ref{nncp-exec} program that extracts the sender
 address from mail that arrives via NNCP, and that feeds the mail into
 the Postfix @command{sendmail} command.
 
@@ -115,13 +116,13 @@ mail delivery via NNCP:
 @verbatim
 /usr/local/etc/postfix/master.cf:
 nncp      unix  -       n       n       -       -       pipe
-          flags=F user=nncp argv=nncp-mail -quiet $nexthop $recipient
+          flags=F user=nncp argv=nncp-exec -quiet $nexthop sendmail $recipient
 @end verbatim
 
-This runs the @command{nncp-mail} command to place outgoing mail into
+This runs the @command{nncp-exec} command to place outgoing mail into
 the NNCP queue. It substitutes the hostname (@emph{nncp-gateway}, or
 whatever you specified) and the recipients before executing the command.
-The @command{nncp-mail} command is executed without assistance from the
+The @command{nncp-exec} command is executed without assistance from the
 shell, so there are no problems with shell meta characters.
 
 @item Execute the command @command{postfix reload} to make the changes
@@ -246,17 +247,9 @@ URIs, Web-seeding, selective downloads, LPD. @command{aria2} can
 accelerate HTTP*/*FTP downloads by segmented multiple parallel
 connections.
 
-You can queue you files after they are completely downloaded:
-@verbatim
-% cat send-downloaded.sh
-#!/bin/sh
-nncp-file -chunked $(( 1024 * 100 )) "$3" remote.node
-
-% aria2c \
-    --on-download-complete send-downloaded.sh \
-    http://example.org/file.iso \
-    http://example.org/file.iso.asc
-@end verbatim
+You can queue you files after they are completely downloaded.
+@file{aria2-downloaded.sh} contents:
+@verbatiminclude aria2-downloaded.sh
 
 Also you can prepare
 @url{http://aria2.github.io/manual/en/html/aria2c.html#files, input file}
@@ -268,12 +261,50 @@ http://www.nncpgo.org/download/nncp-0.11.tar.xz
 http://www.nncpgo.org/download/nncp-0.11.tar.xz.sig
     out=nncp.txz.sig
 % aria2c \
-    --on-download-complete send-downloaded.sh \
+    --on-download-complete aria2-downloaded.sh \
     --input-file jobs
 @end verbatim
 and all that downloaded (@file{nncp.txz}, @file{nncp.txz.sig}) files
 will be sent to @file{remote.node} when finished.
 
+@node DownloadService
+@section Downloading service
+
+Previous sections tell about manual downloading and sending results to
+remote node. But one wish to remotely initiate downloading. That can be
+easily solved with @ref{CfgExec, exec} handles.
+
+@verbatim
+exec:
+  warcer: ["/bin/sh", "/path/to/warcer.sh"]
+  wgeter: ["/bin/sh", "/path/to/wgeter.sh"]
+  aria2c: [
+    "/usr/local/bin/aria2c",
+    "--on-download-complete", "aria2-downloaded.sh",
+    "--on-bt-download-complete", "aria2-downloaded.sh"
+  ]
+@end verbatim
+
+@file{warcer.sh} contents:
+@verbatiminclude warcer.sh
+
+@file{wgeter.sh} contents:
+@verbatiminclude wgeter.sh
+
+Now you can queue that node to send you some website's page, file or
+BitTorrents:
+
+@verbatim
+% echo http://www.nncpgo.org/Postfix.html |
+    nncp-exec remote.node warcer postfix-whole-page
+% echo http://www.nncpgo.org/Postfix.html |
+    nncp-exec remote.node wgeter postfix-html-page
+% echo \
+    http://www.nncpgo.org/download/nncp-0.11.tar.xz
+    http://www.nncpgo.org/download/nncp-0.11.tar.xz.sig |
+    nncp-exec remote.node aria2c
+@end verbatim
+
 @node Git
 @section Integration with Git
 
index 3325a196eaf6ea4e05d4eeb145e061dd85ac16d6..ea8606a2476bd1f3cb445491232b77cb6272546d 100644 (file)
@@ -1,6 +1,51 @@
 @node Новости
 @section Новости
 
+@node Релиз 3.0
+@subsection Релиз 3.0
+@itemize
+@item
+@strong{Несовместимое} изменение формата простых пакетов. Работа со
+старыми версиями не поддерживается.
+@item
+Добавлена возможность удалённого исполнения команд, путём
+конфигурирования @option{exec} опции конфигурационного файла и
+использования команды @command{nncp-exec}:
+    @itemize
+    @item
+    Команда @command{nncp-mail} заменена более гибкой и широкой
+    @command{nncp-exec}. Вместо вызова @verb{|nncp-mail NODE RECIPIENT|}
+    нужно использовать @verb{|nncp-exec NODE sendmail RECIPIENT|}.
+    @item
+    @option{sendmail} опция конфигурационного файла заменена на более гибкую
+    @option{exec}. @verb{|sendmail: [...]|} нужно заменить на @verb{|exec:
+    sendmail: [...]|}.
+    @end itemize
+@item
+Возможность переопределить @option{via} опцию конфигурации для целевого
+узла через @option{-via} опцию командной строки для следующих команд:
+@command{nncp-file}, @command{nncp-freq}, @command{nncp-exec}.
+@item
+Chunked файлы, меньшего размера чем указанный chunk, отправляются просто
+в виде одного файла.
+@item
+Exec команды вызываются с дополнительными переменными окружения
+@env{NNCP_NICE} и @env{NNCP_SELF}.
+@item
+Отправляемые файлы в ответ на запрос имеют приоритет указанный в запросе.
+Указать их желаемый приоритет во время вызова @command{nncp-freq} можно
+аргументом @option{-replynice}.
+@item
+Команде @command{nncp-toss} можно сказать не обрабатывать определённые
+типы пакетов, за счёт опций @option{-nofile}, @option{-nofreq},
+@option{-noexec}, @option{-notrns}.
+@item
+По-умолчанию @command{nncp-file} команда для
+@option{-minsize}/@option{-chunked} опций использует
+@option{FreqMinSize}/@option{FreqChunked} из конфигурационного файла.
+Это можно отключить указав нулевое значение.
+@end itemize
+
 @node Релиз 2.0
 @subsection Релиз 2.0
 @itemize
@@ -103,7 +148,7 @@ HKDF-BLAKE2b-256 KDF алгоритм заменён на BLAKE2Xb XOF. Ещё 
 @option{-mkdir} для ясности.
 
 @item
-Опция @option{-minsize} задётся в KiB, а не байтах, для удобства.
+Опция @option{-minsize} задаётся в KiB, а не байтах, для удобства.
 
 @item
 Команда @command{nncp-newcfg} переименована в @command{nncp-cfgnew},
index 23112e29c27719d3245821a398699b6b91179d63..4d9e7dccdd8a07fed6a787cb9e1c4f2a518c5130 100644 (file)
@@ -3,6 +3,50 @@
 
 See also this page @ref{Новости, on russian}.
 
+@node Release 3.0
+@section Release 3.0
+@itemize
+@item
+@strong{Incompatible} plain packet format changes. Older versions are
+not supported.
+@item
+Ability to queue remote command execution, by configuring @option{exec}
+option in configuration file and using @command{nncp-exec} command:
+    @itemize
+    @item
+    @command{nncp-mail} command is replaced with more flexible
+    @command{nncp-exec}. Instead of @verb{|nncp-mail NODE RECIPIENT|}
+    you must use @verb{|nncp-exec NODE sendmail RECIPIENT|}.
+    @item
+    @option{sendmail} configuration file option is replaced with
+    @option{exec}. @verb{|sendmail: [...]|} must be replaced with
+    @verb{|exec: sendmail: [...]|}.
+    @end itemize
+@item
+Ability to override @option{via} configuration option for destination
+node via @option{-via} command line option for following commands:
+@command{nncp-file}, @command{nncp-freq}, @command{nncp-exec}.
+@item
+Chunked files, having size less than specified chunk size, will be sent
+as an ordinary single file.
+@item
+Exec commands are invoked with additional @env{NNCP_NICE} and
+@env{NNCP_SELF} environment variables.
+@item
+Files, that are sent as a reply to freq, have niceness level taken from
+the freq packet. You can set desired niceness during @command{nncp-freq}
+invocation using @option{-replynice} option.
+@item
+@command{nncp-toss} command can ignore specified packet types during
+processing: @option{-nofile}, @option{-nofreq}, @option{-noexec},
+@option{-notrns}.
+@item
+@command{nncp-file} command uses
+@option{FreqMinSize}/@option{FreqChunked} conifiguration file options
+for @option{-minsize}/@option{-chunked} by default. You can turn this
+off by specifying zero value.
+@end itemize
+
 @node Release 2.0
 @section Release 2.0
 @itemize
index 50f392b350fc20a67998c70a214566d958c312d6..b0f99e9cc206818526090ba07ada52cc5afaedd6 100644 (file)
@@ -10,6 +10,6 @@ Send big files with higher nicer level! That will guarantee you that
 higher priority packets, like mail messages, will pass first, even when
 lower priority packet was already been partly downloaded.
 
-There are default niceness levels built-in for @ref{nncp-mail},
+There are default niceness levels built-in for @ref{nncp-exec},
 @ref{nncp-file} and @ref{nncp-freq} commands. But pay attention that it
 can give information about underlying payload to the adversary!
index 0f5d693e50b992128c8e4d0afff6e38320faf374..b1c2c38b37cb5d7ad0f2254645d6e8120b94b1e8 100644 (file)
@@ -13,15 +13,15 @@ All packets are
 @section Plain packet
 
 Plain packet contains either the whole file, or file request (freq), or
-transition packet or email message. It is called "plain", because it
+transition packet or exec message. It is called "plain", because it
 contains plaintext, but plain packets would never be stored on your hard
 drive.
 
 @verbatim
             HEADER
-+-------------------------------+--...---+
-| MAGIC | TYPE | PATHLEN | PATH | PAYLOAD|
-+-------------------------------+--...---+
++--------------------------------------+--...---+
+| MAGIC | TYPE | NICE | PATHLEN | PATH | PAYLOAD|
++--------------------------------------+--...---+
 @end verbatim
 
 @multitable @columnfractions 0.2 0.3 0.5
@@ -31,7 +31,10 @@ drive.
     @verb{|N N C P P 0x00 0x00 0x01|}
 @item Payload type @tab
     unsigned integer @tab
-    0 (file), 1 (freq), 2 (mail), 3 (transition)
+    0 (file), 1 (freq), 2 (exec), 3 (transition)
+@item Niceness @tab
+    unsigned integer @tab
+    1-255, preferred packet @ref{Niceness, niceness} level
 @item Path length @tab
     unsigned integer @tab
     actual length of @emph{path} field's payload
@@ -40,7 +43,7 @@ drive.
     @itemize
     @item UTF-8 encoded destination path for file transfer
     @item UTF-8 encoded source path for file request
-    @item UTF-8 encoded, space separated, email recipients list
+    @item UTF-8 encoded, zero byte separated, exec's arguments
     @item Node's id the transition packet must be relayed on
     @end itemize
 @end multitable
@@ -55,10 +58,17 @@ Depending on the packet's type, payload could store:
 @itemize
 @item File contents
 @item Destination path for freq
-@item @url{http://zlib.net/, zlib} compressed email
+@item @url{http://zlib.net/, zlib} compressed exec body
 @item Whole encrypted packet we need to relay on
 @end itemize
 
+Also depending on packet's type, niceness level means:
+
+@itemize
+@item Preferable niceness level for files sent by freq
+@item @env{NNCP_NICE} variable's value passed during @ref{CfgExec} invocation.
+@end itemize
+
 @node Encrypted
 @section Encrypted packet
 
index 1407c8e7e359f52c71117ab46bac23b3e8fe1cd3..3e3caba2dbdd889cb32f761c52ebb3db131401c2 100644 (file)
@@ -35,7 +35,7 @@ Postfix} SMTP сервер подключённый к Интернету. Но
 KISS}!
 
 Просто скажите вашим обоим Postfix-ам (на сервере и ноутбуке) отправлять
-сообщения через NNCP (@ref{nncp-mail}) на заданный узел. Это делается
+сообщения через NNCP (@ref{nncp-exec}) на заданный узел. Это делается
 аналогично тому как с UUCP, и описано в
 @url{http://www.postfix.org/UUCP_README.html, документации Postfix}.
 
@@ -49,7 +49,7 @@ KISS}!
 
 @ref{nncp-daemon} может быть соединён с @ref{nncp-caller} длительное
 время -- он создаёт TCP соединение на многие часы. Когда SMTP сервер
-получает письмо, то вызывает @ref{nncp-mail} для создания исходящего
+получает письмо, то вызывает @ref{nncp-exec} для создания исходящего
 зашифрованного пакета. Демон ежесекундно проверяет исходящую директорию
 и сразу же посылает оповещение о недоставленных пакетах противоположной
 стороне, которая сразу же их может скачать.
@@ -70,7 +70,7 @@ IMAP4, как правило, нет). У вас легковесный, сжа
 проблематично получить. Более того, каждый обрыв может приводить к
 отсылке данных с самого начала, что не всегда по карману.
 
-Просто отправьте вашу @ref{nncp-mail, почту} и @ref{nncp-file, файлы}
+Просто отправьте вашу @ref{nncp-exec, почту} и @ref{nncp-file, файлы}
 через NNCP. Вы сможете использовать или offline методы доставки --
 читайте о них в следующем разделе, либо использовать поставляемый NNCP
 @ref{nncp-daemon, TCP демон}.
index 47307f8d0546bdf08e4eb80570f639de616c2331..c2764350451617e2f310231653adfc99d38b83cb 100644 (file)
@@ -34,7 +34,7 @@ overcomplicated and bloated for the simple task. Not an option.
 @url{https://en.wikipedia.org/wiki/KISS_principle, KISS}!
 
 Just tell both of your Postfixes (on the server and notebook) to drop
-email as a mail via NNCP (@ref{nncp-mail}) to specified node. This is
+email as a mail via NNCP (@ref{nncp-exec}) to specified node. This is
 done similarly as with UUCP and as written in
 @url{http://www.postfix.org/UUCP_README.html, Postfix documentation}.
 
@@ -48,7 +48,7 @@ that happened on the same machine.
 
 @ref{nncp-daemon} can be connected with @ref{nncp-caller} for a long
 time -- it can create TCP connection that lasts for many hours. When
-SMTP server receives mail, it will call @ref{nncp-mail} creating an
+SMTP server receives mail, it will call @ref{nncp-exec} creating an
 outbound encrypted packet. Daemon checks outbound directory each second
 and immediately sends notification about undelivered packets to remote
 side, that also downloads it at once.
@@ -68,7 +68,7 @@ download continuation. SMTP does not support resuming at all and heavy
 messages is problematic to retrieve. Moreover, each disconnect leads to
 the same data retransmission again, that can not be afforded sometimes.
 
-Just send your @ref{nncp-mail, mail} and @ref{nncp-file, files} through
+Just send your @ref{nncp-exec, mail} and @ref{nncp-file, files} through
 NNCP. You can use either offline delivery methods -- read about them in
 the next section, or you can use included NNCP @ref{nncp-daemon, TCP
 daemon}.
diff --git a/doc/warcer.sh b/doc/warcer.sh
new file mode 100755 (executable)
index 0000000..9448592
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh -ex
+
+name="$1"-$(date '+%Y%M%d%H%m%S')
+read cmdline
+
+tmp=$(mktemp -d)
+cd $tmp
+wget \
+    --page-requisites \
+    --convert-links \
+    --adjust-extension \
+    --restrict-file-names=ascii \
+    --span-hosts \
+    --random-wait \
+    --execute robots=off \
+    --reject '*.woff*,*.ttf,*.eot,*.js' \
+    --tries 10 \
+    --warc-file "$name" \
+    --no-warc-compression \
+    --no-warc-keep-log \
+    $cmdline || :
+xz -9 "$name".warc
+nncp-file -nice $NNCP_NICE "$name".warc.xz $NNCP_SENDER:
+rm -r $tmp
diff --git a/doc/wgeter.sh b/doc/wgeter.sh
new file mode 100755 (executable)
index 0000000..5f80d81
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh -ex
+
+name=$1-$(date '+%Y%M%d%H%m%S')
+read cmdline
+
+tmp=$(mktemp)
+wget --output-document=$tmp $cmdline
+xz -9 $tmp
+nncp-file -nice $NNCP_NICE $tmp.xz $NNCP_SENDER:$name.xz
+rm $tmp.xz
index 27a7ea9a1e3432fd6caf1a59bf3044cfaca3545c..def29296ab8bcf4a50f0753159de18d65c54fd64 100644 (file)
@@ -12,9 +12,9 @@ following workflow:
 neighbours. Add their keys to your configuration file and do any other
 required configuration about their reachability, permissions of file or
 freq transmission.
-@item Use @ref{nncp-file}, @ref{nncp-freq}, @ref{nncp-mail}
+@item Use @ref{nncp-file}, @ref{nncp-freq}, @ref{nncp-exec}
 (@ref{Postfix, look how} Postfix SMTP server could be configured)
-commands to queue file, freq and mail transmissions. Repeat as
+commands to queue file, freq and exec transmissions. Repeat as
 many times any time as you wish.
 @item Depending on connection methods, either:
     @itemize
@@ -29,7 +29,7 @@ many times any time as you wish.
     @end itemize
 @item After successful packet exchanging (or just simply from time to
 time), run @ref{nncp-toss} for tossing (decrypting and processing) all
-inbound queues to receive mail messages, files, file requests and relay
+inbound queues to receive exec messages, files, file requests and relay
 transition packets to other nodes.
 @end enumerate
 
index 22b42d6e155fc926d2e08aef67ab6e29fb18602b..a81bdc73e8274457db5ec2a71835670320513fe7 100755 (executable)
@@ -103,12 +103,13 @@ NNCP (Node to Node copy) is a collection of utilities simplifying
 secure store-and-forward files and mail exchanging.
 
 This utilities are intended to help build up small size (dozens of
-nodes) ad-hoc friend-to-friend (F2F) statically routed darknet networks
-for fire-and-forget secure reliable files, file requests and Internet
-mail transmission. All packets are integrity checked, end-to-end
-encrypted (E2EE), explicitly authenticated by known participants public
-keys. Onion encryption is applied to relayed packets. Each node acts
-both as a client and server, can use push and poll behaviour model.
+nodes) ad-hoc friend-to-friend (F2F) statically routed darknet
+delay-tolerant networks for fire-and-forget secure reliable files, file
+requests, Internet mail and commands transmission. All packets are
+integrity checked, end-to-end encrypted (E2EE), explicitly authenticated
+by known participants public keys. Onion encryption is applied to
+relayed packets. Each node acts both as a client and server, can use
+push and poll behaviour model.
 
 Out-of-box offline sneakernet/floppynet, dead drops, sequential and
 append-only CD-ROM/tape storages, air-gapped computers support. But
@@ -147,10 +148,10 @@ Subject: [RU] Состоялся релиз NNCP $release
 NNCP (Node to Node copy) это набор утилит упрощающий безопасный обмен
 файлами и почтой в режиме сохранить-и-переслать.
 
-ЭÑ\82и Ñ\83Ñ\82илиÑ\82Ñ\8b Ð¿Ñ\80едназнаÑ\87енÑ\8b Ð¿Ð¾Ð¼Ð¾Ñ\87Ñ\8c Ñ\81 Ð¿Ð¾Ñ\81Ñ\82Ñ\80оением Ð¾Ð´Ð½Ð¾Ñ\80анговÑ\8bÑ\85 Ñ\81еÑ\82ей
-небольшого размера (дюжины узлов), в режиме друг-к-другу (F2F) со
-статической маршрутизацией для безопасной надёжной передачи файлов,
-запросов на передачу файлов и Интернет почты по принципу
+ЭÑ\82и Ñ\83Ñ\82илиÑ\82Ñ\8b Ð¿Ñ\80едназнаÑ\87енÑ\8b Ð¿Ð¾Ð¼Ð¾Ñ\87Ñ\8c Ñ\81 Ð¿Ð¾Ñ\81Ñ\82Ñ\80оением Ð¾Ð´Ð½Ð¾Ñ\80анговÑ\8bÑ\85 Ñ\83Ñ\81Ñ\82ойÑ\87ивÑ\8bÑ\85 Ðº
+разрывам сетей небольшого размера (дюжины узлов), в режиме друг-к-другу
+(F2F) со статической маршрутизацией для безопасной надёжной передачи
+файлов, запросов на передачу файлов, Интернет почты и команд по принципу
 выстрелил-и-забыл. Все пакеты проверяются на целостность, шифруются по
 принципу точка-точка (E2EE), аутентифицируются известными публичными
 ключами участников. Луковичное (onion) шифрование применяется ко всем
index 2b3805f0e9439b0dc30701956db911eb73a44ffe..ce2e217be19c9f5c5fd69006534f3040e65927e6 100644 (file)
@@ -1,12 +1,12 @@
-# $FreeBSD$
+# $FreeBSD: head/net/nncp/Makefile 460314 2018-01-29 16:17:45Z yuri $
 
 PORTNAME=      nncp
-PORTVERSION=   2.0
+DISTVERSION=   3.0
 CATEGORIES=    net
 MASTER_SITES=  http://www.nncpgo.org/download/
 
 MAINTAINER=    stargrave@stargrave.org
-COMMENT=       Utilities for secure store-and-forward files and mail exchanging
+COMMENT=       Utilities for secure store-and-forward files, mail and command exchanging
 
 LICENSE=       GPLv3+
 LICENSE_FILE=  ${WRKSRC}/COPYING
@@ -15,38 +15,17 @@ BUILD_DEPENDS=      go:lang/go
 
 USES=          tar:xz
 MAKEFILE=      BSDmakefile
-
 USE_RC_SUBR=   nncp-caller nncp-daemon nncp-toss
-REQUIRE=       DAEMON
+INSTALL_TARGET=        install-strip
+
+SUB_FILES=     pkg-message pkg-install pkg-deinstall
 
-SUB_FILES=     pkg-message pkg-install pkg-deinstall nncp.newsyslog.conf.sample
+OPTIONS_DEFINE=        DOCS
 
 PORTDOCS=      AUTHORS NEWS NEWS.RU README README.RU THANKS
 INFO=          nncp
-INSTALL_TARGET=        install-strip
-
-PLIST_FILES=   bin/nncp-bundle \
-               bin/nncp-call \
-               bin/nncp-caller \
-               bin/nncp-cfgenc \
-               bin/nncp-cfgmin \
-               bin/nncp-cfgnew \
-               bin/nncp-check \
-               bin/nncp-daemon \
-               bin/nncp-file \
-               bin/nncp-freq \
-               bin/nncp-log \
-               bin/nncp-mail \
-               bin/nncp-pkt \
-               bin/nncp-reass \
-               bin/nncp-rm \
-               bin/nncp-stat \
-               bin/nncp-toss \
-               bin/nncp-xfer \
-               "@sample etc/newsyslog.conf.d/nncp.conf.sample"
 
 post-install:
-       ${MKDIR} ${STAGEDIR}${PREFIX}/etc/newsyslog.conf.d
-       ${INSTALL_DATA} ${WRKDIR}/nncp.newsyslog.conf.sample ${STAGEDIR}${PREFIX}/etc/newsyslog.conf.d/nncp.conf.sample
+       ${INSTALL_DATA} ${FILESDIR}/nncp.newsyslog.conf.sample ${STAGEDIR}${PREFIX}/etc/nncp.conf.sample
 
 .include <bsd.port.mk>
index 56713d2d9acc0ee0075331c9ebf399e6790205f9..a68f1a34e610eff2c2cc9f6b12ef987fa2430df4 100644 (file)
@@ -13,5 +13,5 @@
 - Generate NNCP configuration file using the command:
 
     # umask 077
-    # nncp-newcfg > %%PREFIX%%/etc/nncp.yaml
+    # nncp-cfgnew > %%PREFIX%%/etc/nncp.yaml
 ======================================================================
index 37b709118e5bd1d7c36b1f4aba82b15f103be4e6..ce972a9da8cb0b31df2397fed5d95ce9316f4230 100644 (file)
@@ -2,12 +2,13 @@ NNCP (Node to Node copy) is a collection of utilities simplifying
 secure store-and-forward files and mail exchanging.
 
 This utilities are intended to help build up small size (dozens of
-nodes) ad-hoc friend-to-friend (F2F) statically routed darknet networks
-for fire-and-forget secure reliable files, file requests and Internet
-mail transmission. All packets are integrity checked, end-to-end
-encrypted (E2EE), explicitly authenticated by known participants public
-keys. Onion encryption is applied to relayed packets. Each node acts
-both as a client and server, can use push and poll behaviour model.
+nodes) ad-hoc friend-to-friend (F2F) statically routed darknet
+delay-tolerant networks for fire-and-forget secure reliable files, file
+requests, Internet mail and commands transmission. All packets are
+integrity checked, end-to-end encrypted (E2EE), explicitly authenticated
+by known participants public keys. Onion encryption is applied to
+relayed packets. Each node acts both as a client and server, can use
+push and poll behaviour model.
 
 Out-of-box offline sneakernet/floppynet, dead drops, sequential and
 append-only CD-ROM/tape storages, air-gapped computers support. But
diff --git a/ports/nncp/pkg-plist b/ports/nncp/pkg-plist
new file mode 100644 (file)
index 0000000..e98d84e
--- /dev/null
@@ -0,0 +1,19 @@
+bin/nncp-bundle
+bin/nncp-call
+bin/nncp-caller
+bin/nncp-cfgenc
+bin/nncp-cfgmin
+bin/nncp-cfgnew
+bin/nncp-check
+bin/nncp-daemon
+bin/nncp-exec
+bin/nncp-file
+bin/nncp-freq
+bin/nncp-log
+bin/nncp-pkt
+bin/nncp-reass
+bin/nncp-rm
+bin/nncp-stat
+bin/nncp-toss
+bin/nncp-xfer
+@sample etc/nncp.conf.sample etc/newsyslog.conf.d/nncp.conf
index 95f85aa47858705926bd6a73ccbf4f9d7bf5df74..883eae7b16454a384fbc1de37140612edafeec3e 120000 (symlink)
@@ -1 +1 @@
-golang.org/x/crypto/chacha20poly1305/internal/chacha20
\ No newline at end of file
+golang.org/x/crypto/internal/chacha20
\ No newline at end of file
index 3cd3006ad829a0afc7ca3d964ff333ef068464bd..92c161713a13cc78403468c09f1557eb7c4a3a4a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3cd3006ad829a0afc7ca3d964ff333ef068464bd
+Subproject commit 92c161713a13cc78403468c09f1557eb7c4a3a4a
index 496720a2bc9499a65793075f7b132a5a3830f2e2..ab120ad890c69e824db3a66ce8bfcdc3d258db1b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index d948a274086438719aa6e09ae36c08f27405c93a..b75196175e429b89f7408789fd932077bafd8cfd 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -48,14 +48,14 @@ type NodeYAML struct {
        Id          string
        ExchPub     string
        SignPub     string
-       NoisePub    *string    `noisepub,omitempty`
-       Sendmail    []string   `sendmail,omitempty`
-       Incoming    *string    `incoming,omitempty`
-       Freq        *string    `freq,omitempty`
-       FreqChunked *uint64    `freqchunked,omitempty`
-       FreqMinSize *uint64    `freqminsize,omitempty`
-       Via         []string   `via,omitempty`
-       Calls       []CallYAML `calls,omitempty`
+       NoisePub    *string             `noisepub,omitempty`
+       Exec        map[string][]string `exec,omitempty`
+       Incoming    *string             `incoming,omitempty`
+       Freq        *string             `freq,omitempty`
+       FreqChunked *uint64             `freqchunked,omitempty`
+       FreqMinSize *uint64             `freqminsize,omitempty`
+       Via         []string            `via,omitempty`
+       Calls       []CallYAML          `calls,omitempty`
 
        Addrs map[string]string `addrs,omitempty`
 
@@ -232,7 +232,7 @@ func NewNode(name string, yml NodeYAML) (*Node, error) {
                Id:             nodeId,
                ExchPub:        new([32]byte),
                SignPub:        ed25519.PublicKey(signPub),
-               Sendmail:       yml.Sendmail,
+               Exec:           yml.Exec,
                Incoming:       incoming,
                Freq:           freq,
                FreqChunked:    freqChunked,
index 1477763d22c8b0d25c7f59a599806a1fc525d15c..53dd549a0faaf2d47607957f7a5f69f1fd28d2d9 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 61564c47ddd1ac1f4d79b06eb731518416a2ac75..417e2a0e897629047a37401c0df66b1fe854847e 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index bfa48169e6edd8dc872968b07287738c3019cbeb..3b754bc1b56a8d8d1311fe18217fbcdc38503cf7 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -44,7 +44,7 @@ const (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-bundle -- Create/digest stream of NNCP encrypted packets\n")
+       fmt.Fprintf(os.Stderr, "nncp-bundle -- Create/digest stream of NNCP encrypted packets\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] -tx [-delete] NODE [NODE ...] > ...\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] -rx -delete [-dryrun] [NODE ...] < ...\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] -rx [-check] [-dryrun] [NODE ...] < ...\n", os.Args[0])
index 062593e6301ecd1f88d8cafc8721d68c623fe6bc..bbf9bfa2ff3671c63502cc117af56dc67377d0a3 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -31,7 +31,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-call -- call TCP daemon\n")
+       fmt.Fprintf(os.Stderr, "nncp-call -- call TCP daemon\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE[:ADDR] [FORCEADDR]\n", os.Args[0])
        fmt.Fprintln(os.Stderr, "Options:")
        flag.PrintDefaults()
index 459a623858c7d117d04fc1abc0a5c380c1dc4b5a..a975878cb4066635bd16aed4adb0e673ec61a71f 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -33,7 +33,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-caller -- croned NNCP TCP daemon caller\n")
+       fmt.Fprintf(os.Stderr, "nncp-caller -- croned NNCP TCP daemon caller\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] [NODE ...]\n", os.Args[0])
        fmt.Fprintln(os.Stderr, "Options:")
        flag.PrintDefaults()
index 30f4137b4024980b6bb5470dc6c9769b9a20ea3f..3ad1d69784d44da48d21dbe74bf982e197395c9a 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -36,7 +36,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-cfgenc -- encrypt/decrypt configuration file\n")
+       fmt.Fprintf(os.Stderr, "nncp-cfgenc -- encrypt/decrypt configuration file\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] cfg.yaml > cfg.yaml.eblob\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] -d cfg.yaml.eblob > cfg.yaml\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] -dump cfg.yaml.eblob\n", os.Args[0])
index 7de3247e466ac1f839a55807f6be5006aa9600f2..cf1626e8498de9549b81fb053ad86fde323a20c7 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -31,7 +31,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-cfgmin -- print stripped configuration\n")
+       fmt.Fprintf(os.Stderr, "nncp-cfgmin -- print stripped configuration\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
index 2601d46532fc8e0a82ebf8894568116d7d348328..a119e3830989d73de494f3d9741c53b8e3f28cfc 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -70,7 +70,9 @@ func main() {
                                ExchPub:  nncp.ToBase32(nodeOur.ExchPub[:]),
                                SignPub:  nncp.ToBase32(nodeOur.SignPub[:]),
                                NoisePub: &noisePub,
-                               Sendmail: []string{nncp.DefaultSendmailPath},
+                               Exec: map[string][]string{
+                                       "sendmail": []string{nncp.DefaultSendmailPath},
+                               },
                        },
                },
                Spool: nncp.DefaultSpoolPath,
index a10c8cfd2f0417f749b661ef3c13b5a23b9d7018..f426fd455d65374a4707b753ab293220612af9fa 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -30,7 +30,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-check -- verify Rx/Tx packets checksum\n")
+       fmt.Fprintf(os.Stderr, "nncp-check -- verify Rx/Tx packets checksum\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
index de0a0b3bf62b10cd6b5a0e43e0bcd3a0d489240d..1ea30de168b8fb3300adb7dd41a0eb52cef917cd 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -33,7 +33,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-daemon -- TCP daemon\n")
+       fmt.Fprintf(os.Stderr, "nncp-daemon -- TCP daemon\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
similarity index 50%
rename from src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go
rename to src/cypherpunks.ru/nncp/cmd/nncp-exec/main.go
index f9d346f4f27cb5f206ec1b6192cfdcf635b9dbf6..8e7aec62682a1e3002d2557145ee33144273b044 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-// Send email via NNCP
+// Send execution command via NNCP
 package main
 
 import (
@@ -33,22 +33,24 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-mail -- send email\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE USER ...\nOptions:\n", os.Args[0])
+       fmt.Fprintf(os.Stderr, "nncp-exec -- send execution command\n\n")
+       fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE HANDLE [ARG0 ARG1 ...]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
 func main() {
        var (
-               cfgPath   = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
-               niceRaw   = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness")
-               minSize   = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
-               spoolPath = flag.String("spool", "", "Override path to spool")
-               logPath   = flag.String("log", "", "Override path to logfile")
-               quiet     = flag.Bool("quiet", false, "Print only errors")
-               debug     = flag.Bool("debug", false, "Print debug messages")
-               version   = flag.Bool("version", false, "Print version information")
-               warranty  = flag.Bool("warranty", false, "Print warranty information")
+               cfgPath      = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
+               niceRaw      = flag.Int("nice", nncp.DefaultNiceExec, "Outbound packet niceness")
+               replyNiceRaw = flag.Int("replynice", nncp.DefaultNiceFile, "Possible reply packet niceness")
+               minSize      = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
+               viaOverride  = flag.String("via", "", "Override Via path to destination node")
+               spoolPath    = flag.String("spool", "", "Override path to spool")
+               logPath      = flag.String("log", "", "Override path to logfile")
+               quiet        = flag.Bool("quiet", false, "Print only errors")
+               debug        = flag.Bool("debug", false, "Print debug messages")
+               version      = flag.Bool("version", false, "Print version information")
+               warranty     = flag.Bool("warranty", false, "Print warranty information")
        )
        flag.Usage = usage
        flag.Parse()
@@ -68,6 +70,10 @@ func main() {
                log.Fatalln("-nice must be between 1 and 255")
        }
        nice := uint8(*niceRaw)
+       if *replyNiceRaw < 1 || *replyNiceRaw > 255 {
+               log.Fatalln("-replynice must be between 1 and 255")
+       }
+       replyNice := uint8(*replyNiceRaw)
 
        ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
        if err != nil {
@@ -82,15 +88,29 @@ func main() {
                log.Fatalln("Invalid NODE specified:", err)
        }
 
+       if *viaOverride != "" {
+               vias := make([]*nncp.NodeId, 0, strings.Count(*viaOverride, ",")+1)
+               for _, via := range strings.Split(*viaOverride, ",") {
+                       foundNodeId, err := ctx.FindNode(via)
+                       if err != nil {
+                               log.Fatalln("Invalid Via node specified:", err)
+                       }
+                       vias = append(vias, foundNodeId.Id)
+               }
+               node.Via = vias
+       }
+
        body, err := ioutil.ReadAll(bufio.NewReader(os.Stdin))
        if err != nil {
-               log.Fatalln("Can not read mail body from stdin:", err)
+               log.Fatalln("Can not read body from stdin:", err)
        }
 
-       if err = ctx.TxMail(
+       if err = ctx.TxExec(
                node,
                nice,
-               strings.Join(flag.Args()[1:], " "),
+               replyNice,
+               flag.Args()[1],
+               flag.Args()[2:],
                body,
                int64(*minSize)*1024,
        ); err != nil {
index 3c35ab9081799429d12dcd6edcabb997a5759440..43259146071cd558e3e4e99df367e65ec751354a 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -31,26 +31,30 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-file -- send file\n")
+       fmt.Fprintf(os.Stderr, "nncp-file -- send file\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] SRC NODE:[DST]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
        fmt.Fprint(os.Stderr, `
 If SRC equals to -, then read data from stdin to temporary file.
+
+-minsize/-chunked take NODE's FreqMinSize/FreqChunked configuration
+options by default. You can forcefully turn them off by specifying 0 value.
 `)
 }
 
 func main() {
        var (
-               cfgPath   = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
-               niceRaw   = flag.Int("nice", nncp.DefaultNiceFile, "Outbound packet niceness")
-               minSize   = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
-               chunkSize = flag.Uint64("chunked", 0, "Split file on specified size chunks, in KiB")
-               spoolPath = flag.String("spool", "", "Override path to spool")
-               logPath   = flag.String("log", "", "Override path to logfile")
-               quiet     = flag.Bool("quiet", false, "Print only errors")
-               debug     = flag.Bool("debug", false, "Print debug messages")
-               version   = flag.Bool("version", false, "Print version information")
-               warranty  = flag.Bool("warranty", false, "Print warranty information")
+               cfgPath      = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
+               niceRaw      = flag.Int("nice", nncp.DefaultNiceFile, "Outbound packet niceness")
+               argMinSize   = flag.Int64("minsize", -1, "Minimal required resulting packet size, in KiB")
+               argChunkSize = flag.Int64("chunked", -1, "Split file on specified size chunks, in KiB")
+               viaOverride  = flag.String("via", "", "Override Via path to destination node")
+               spoolPath    = flag.String("spool", "", "Override path to spool")
+               logPath      = flag.String("log", "", "Override path to logfile")
+               quiet        = flag.Bool("quiet", false, "Print only errors")
+               debug        = flag.Bool("debug", false, "Print debug messages")
+               version      = flag.Bool("version", false, "Print version information")
+               warranty     = flag.Bool("warranty", false, "Print warranty information")
        )
        flag.Usage = usage
        flag.Parse()
@@ -89,13 +93,39 @@ func main() {
                log.Fatalln("Invalid NODE specified:", err)
        }
 
-       if *chunkSize == 0 {
+       if *viaOverride != "" {
+               vias := make([]*nncp.NodeId, 0, strings.Count(*viaOverride, ",")+1)
+               for _, via := range strings.Split(*viaOverride, ",") {
+                       foundNodeId, err := ctx.FindNode(via)
+                       if err != nil {
+                               log.Fatalln("Invalid Via node specified:", err)
+                       }
+                       vias = append(vias, foundNodeId.Id)
+               }
+               node.Via = vias
+       }
+
+       var minSize int64
+       if *argMinSize < 0 {
+               minSize = node.FreqMinSize
+       } else if *argMinSize > 0 {
+               minSize = *argMinSize * 1024
+       }
+
+       var chunkSize int64
+       if *argChunkSize < 0 {
+               chunkSize = node.FreqChunked
+       } else if *argChunkSize > 0 {
+               chunkSize = *argChunkSize * 1024
+       }
+
+       if chunkSize == 0 {
                err = ctx.TxFile(
                        node,
                        nice,
                        flag.Arg(0),
                        splitted[1],
-                       int64(*minSize)*1024,
+                       minSize,
                )
        } else {
                err = ctx.TxFileChunked(
@@ -103,8 +133,8 @@ func main() {
                        nice,
                        flag.Arg(0),
                        splitted[1],
-                       int64(*minSize)*1024,
-                       int64(*chunkSize)*1024,
+                       minSize,
+                       chunkSize,
                )
        }
        if err != nil {
index c089abc102c88a9c8e6d6fb8ed649f9d1c000eb0..cab8a8d2d53e67aec22ad5cd403e6d404acdb38b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -32,22 +32,24 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-freq -- send file request\n")
+       fmt.Fprintf(os.Stderr, "nncp-freq -- send file request\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE:SRC [DST]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
 func main() {
        var (
-               cfgPath   = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
-               niceRaw   = flag.Int("nice", nncp.DefaultNiceFreq, "Outbound packet niceness")
-               minSize   = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
-               spoolPath = flag.String("spool", "", "Override path to spool")
-               logPath   = flag.String("log", "", "Override path to logfile")
-               quiet     = flag.Bool("quiet", false, "Print only errors")
-               debug     = flag.Bool("debug", false, "Print debug messages")
-               version   = flag.Bool("version", false, "Print version information")
-               warranty  = flag.Bool("warranty", false, "Print warranty information")
+               cfgPath      = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
+               niceRaw      = flag.Int("nice", nncp.DefaultNiceFreq, "Outbound packet niceness")
+               replyNiceRaw = flag.Int("replynice", nncp.DefaultNiceFile, "Reply file packet niceness")
+               minSize      = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
+               viaOverride  = flag.String("via", "", "Override Via path to destination node")
+               spoolPath    = flag.String("spool", "", "Override path to spool")
+               logPath      = flag.String("log", "", "Override path to logfile")
+               quiet        = flag.Bool("quiet", false, "Print only errors")
+               debug        = flag.Bool("debug", false, "Print debug messages")
+               version      = flag.Bool("version", false, "Print version information")
+               warranty     = flag.Bool("warranty", false, "Print warranty information")
        )
        flag.Usage = usage
        flag.Parse()
@@ -67,6 +69,10 @@ func main() {
                log.Fatalln("-nice must be between 1 and 255")
        }
        nice := uint8(*niceRaw)
+       if *replyNiceRaw < 1 || *replyNiceRaw > 255 {
+               log.Fatalln("-replynice must be between 1 and 255")
+       }
+       replyNice := uint8(*replyNiceRaw)
 
        ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
        if err != nil {
@@ -86,6 +92,18 @@ func main() {
                log.Fatalln("Invalid NODE specified:", err)
        }
 
+       if *viaOverride != "" {
+               vias := make([]*nncp.NodeId, 0, strings.Count(*viaOverride, ",")+1)
+               for _, via := range strings.Split(*viaOverride, ",") {
+                       foundNodeId, err := ctx.FindNode(via)
+                       if err != nil {
+                               log.Fatalln("Invalid Via node specified:", err)
+                       }
+                       vias = append(vias, foundNodeId.Id)
+               }
+               node.Via = vias
+       }
+
        var dst string
        if flag.NArg() == 2 {
                dst = flag.Arg(1)
@@ -96,6 +114,7 @@ func main() {
        if err = ctx.TxFreq(
                node,
                nice,
+               replyNice,
                splitted[1],
                dst,
                int64(*minSize)*1024,
index c045715447ee36bb72e7c0815bbbadb7145ebc70..c578ec9a773a675817b442eb8dbbd9807b104333 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -31,7 +31,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-log -- read logs\n")
+       fmt.Fprintf(os.Stderr, "nncp-log -- read logs\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
index 891298bf3ebde2f3b4d9077aba50f3050c91e39d..f4de406a4b17eab7eb6b22cff66849d476cdc9d8 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -36,7 +36,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-pkt -- parse raw packet\n")
+       fmt.Fprintf(os.Stderr, "nncp-pkt -- parse raw packet\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
        fmt.Fprintln(os.Stderr, "Packet is read from stdin.")
@@ -68,7 +68,7 @@ func main() {
        }
        var pkt nncp.Pkt
        _, err = xdr.Unmarshal(bytes.NewReader(beginning), &pkt)
-       if err == nil && pkt.Magic == nncp.MagicNNCPPv1 {
+       if err == nil && pkt.Magic == nncp.MagicNNCPPv2 {
                if *dump {
                        bufW := bufio.NewWriter(os.Stdout)
                        var r io.Reader
@@ -94,19 +94,29 @@ func main() {
                        payloadType = "file"
                case nncp.PktTypeFreq:
                        payloadType = "file request"
-               case nncp.PktTypeMail:
-                       payloadType = "mail"
+               case nncp.PktTypeExec:
+                       payloadType = "exec"
                case nncp.PktTypeTrns:
                        payloadType = "transitional"
                }
                var path string
                switch pkt.Type {
+               case nncp.PktTypeExec:
+                       path = string(bytes.Replace(
+                               pkt.Path[:pkt.PathLen],
+                               []byte{0},
+                               []byte(" "),
+                               -1,
+                       ))
                case nncp.PktTypeTrns:
                        path = nncp.ToBase32(pkt.Path[:pkt.PathLen])
                default:
                        path = string(pkt.Path[:pkt.PathLen])
                }
-               fmt.Printf("Packet type: plain\nPayload type: %s\nPath: %s\n", payloadType, path)
+               fmt.Printf(
+                       "Packet type: plain\nPayload type: %s\nNiceness: %d\nPath: %s\n",
+                       payloadType, pkt.Nice, path,
+               )
                return
        }
        var pktEnc nncp.PktEnc
index 9c6cae2af1fe4dd1ab3358548eaecfaf11f9eaa2..06549b8426a50f3f9ccfa913926472ad523bdfe4 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -42,7 +42,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-reass -- reassemble chunked files\n")
+       fmt.Fprintf(os.Stderr, "nncp-reass -- reassemble chunked files\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] [FILE.nncp.meta]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
        fmt.Fprint(os.Stderr, `
index b616ad8163cc578faae942a3c7cdde052dc99365..7ce924fce88081e0dc21154a42e51e22ee8f59ad 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -32,7 +32,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-rm -- remove packet\n")
+       fmt.Fprintf(os.Stderr, "nncp-rm -- remove packet\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] -tmp\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] -lock\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] -node NODE -part\n", os.Args[0])
index fd20e620a6a51954c22c08e2a8adaadb66588f60..94a0bb1fd2557959393041c7f6bf86ad5c084d11 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -32,7 +32,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-stat -- show queued Rx/Tx stats\n")
+       fmt.Fprintf(os.Stderr, "nncp-stat -- show queued Rx/Tx stats\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
index eb2158c9c67d17b2a1ddfa6dd4eac52a05f8c03f..cc3ca67fb57e6afd6a215d66d634b833e9aee098 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -31,7 +31,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-toss -- process inbound packets\n")
+       fmt.Fprintf(os.Stderr, "nncp-toss -- process inbound packets\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
@@ -44,6 +44,10 @@ func main() {
                dryRun    = flag.Bool("dryrun", false, "Do not actually write any tossed data")
                doSeen    = flag.Bool("seen", false, "Create .seen files")
                cycle     = flag.Uint("cycle", 0, "Repeat tossing after N seconds in infinite loop")
+               noFile    = flag.Bool("nofile", false, "Do not process packets with type: file")
+               noFreq    = flag.Bool("nofreq", false, "Do not process packets with type: freq")
+               noExec    = flag.Bool("noexec", false, "Do not process packets with type: exec")
+               noTrns    = flag.Bool("notrns", false, "Do not process packets with type: transitional")
                spoolPath = flag.String("spool", "", "Override path to spool")
                logPath   = flag.String("log", "", "Override path to logfile")
                quiet     = flag.Bool("quiet", false, "Print only errors")
@@ -88,7 +92,16 @@ Cycle:
                if nodeOnly != nil && nodeId != *nodeOnly.Id {
                        continue
                }
-               isBad = ctx.Toss(node.Id, nice, *dryRun, *doSeen)
+               isBad = ctx.Toss(
+                       node.Id,
+                       nice,
+                       *dryRun,
+                       *doSeen,
+                       *noFile,
+                       *noFreq,
+                       *noExec,
+                       *noTrns,
+               )
        }
        if *cycle > 0 {
                time.Sleep(time.Duration(*cycle) * time.Second)
index 28d2eb27ff40bfa81db7d7d6f5e69b747a1df5d5..15e4843600c51559455f60947e9a173d11afe81e 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -36,7 +36,7 @@ import (
 
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
-       fmt.Fprintln(os.Stderr, "nncp-xfer -- copy inbound and outbounds packets\n")
+       fmt.Fprintf(os.Stderr, "nncp-xfer -- copy inbound and outbounds packets\n\n")
        fmt.Fprintf(os.Stderr, "Usage: %s [options] DIR\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
index 8e550fb94e8c1bb3d18d166e9bf1da1c37e0cbb4..ab3fc6699d7328030b0e77efce69ddfa767e027a 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 5fb402206a173c0ed6a64640125d8a23f9d81ab8..b25f5ab208dd9269848c42dad5d06a9c2175f1d0 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 4a79fcd9e6facae990d490bdd55ba8e761c1d3d5..cea9546b150d619f9022bb415fd686949f3a390b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -84,10 +84,10 @@ func (ctx *Ctx) Humanize(s string) string {
                                "File request from %s:%s to %s: %s",
                                nodeS, sds["src"], sds["dst"], rem,
                        )
-               case "mail":
+               case "exec":
                        msg = fmt.Sprintf(
-                               "Mail to %s@%s (%s): %s",
-                               nodeS, strings.Replace(sds["dst"], " ", ",", -1), size, rem,
+                               "Exec to %s@%s (%s): %s",
+                               nodeS, sds["dst"], size, rem,
                        )
                case "trns":
                        msg = fmt.Sprintf(
@@ -102,10 +102,10 @@ func (ctx *Ctx) Humanize(s string) string {
                }
        case "rx":
                switch sds["type"] {
-               case "mail":
+               case "exec":
                        msg = fmt.Sprintf(
-                               "Got mail from %s to %s (%s)",
-                               nodeS, strings.Replace(sds["dst"], " ", ",", -1), size,
+                               "Got exec from %s to %s (%s)",
+                               nodeS, sds["dst"], size,
                        )
                case "file":
                        msg = fmt.Sprintf("Got file %s (%s) from %s", sds["dst"], size, nodeS)
index 8630846d254747e1b59e5c75b94b17720389b844..019fe70aa72be0ff7bda20ade657eb0ab3b11ceb 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 25316b8118c60e4757f725ef103d4d08e40584ab..cc94cb690905389ad963c411eda2f088decf34bc 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 5b64880897edcbaa74dc4cfa850104e9402d7129..55d8844a8edad89ddff96d76810206c7d4ba245b 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 15f751a008a98254ec16eb2ab02f61bb9ec580f7..490214065073e8bbd7792351a48966ca47e25e14 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 1ea490309ff45b2146d3e6b22b0317d6b222508e..f1fb79ff5bdf8df4b7bca8f44bdc1eb08e3b4802 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -42,7 +42,7 @@ type Node struct {
        ExchPub        *[32]byte
        SignPub        ed25519.PublicKey
        NoisePub       *[32]byte
-       Sendmail       []string
+       Exec           map[string][]string
        Incoming       *string
        Freq           *string
        FreqChunked    int64
@@ -85,7 +85,10 @@ func NewNodeGenerate() (*NodeOur, error) {
        if err != nil {
                return nil, err
        }
-       noiseKey := noise.DH25519.GenerateKeypair(rand.Reader)
+       noiseKey, err := noise.DH25519.GenerateKeypair(rand.Reader)
+       if err != nil {
+               return nil, err
+       }
        noisePub := new([32]byte)
        noisePrv := new([32]byte)
        copy(noisePrv[:], noiseKey.Private)
index c24dad39cca7ed510fe4cad1fe857f805804c69b..b1c506a590d4ec816a61ac030781aa2645a7a8ea 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -42,12 +42,12 @@ const (
 
        PktTypeFile PktType = iota
        PktTypeFreq PktType = iota
-       PktTypeMail PktType = iota
+       PktTypeExec PktType = iota
        PktTypeTrns PktType = iota
 
        MaxPathSize = 1<<8 - 1
 
-       DefaultNiceMail = 64
+       DefaultNiceExec = 64
        DefaultNiceFreq = 64
        DefaultNiceFile = 196
 
@@ -55,7 +55,7 @@ const (
 )
 
 var (
-       MagicNNCPPv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 1}
+       MagicNNCPPv2 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 2}
        MagicNNCPEv3 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 3}
        BadMagic     error   = errors.New("Unknown magic number")
        BadPktType   error   = errors.New("Unknown packet type")
@@ -67,6 +67,7 @@ var (
 type Pkt struct {
        Magic   [8]byte
        Type    PktType
+       Nice    uint8
        PathLen uint8
        Path    *[MaxPathSize]byte
 }
@@ -120,18 +121,18 @@ func init() {
        PktEncOverhead = int64(n)
 }
 
-func NewPkt(typ PktType, path string) (*Pkt, error) {
-       pb := []byte(path)
-       if len(pb) > MaxPathSize {
+func NewPkt(typ PktType, nice uint8, path []byte) (*Pkt, error) {
+       if len(path) > MaxPathSize {
                return nil, errors.New("Too long path")
        }
        pkt := Pkt{
-               Magic:   MagicNNCPPv1,
+               Magic:   MagicNNCPPv2,
                Type:    typ,
-               PathLen: uint8(len(pb)),
+               Nice:    nice,
+               PathLen: uint8(len(path)),
                Path:    new([MaxPathSize]byte),
        }
-       copy(pkt.Path[:], pb)
+       copy(pkt.Path[:], path)
        return &pkt, nil
 }
 
index 15bff169132f01aa11eeb572f7aaa21c23ae7908..e0765b3a7179c53be091cc421f4d4ff63c58d50a 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -41,7 +41,7 @@ func TestPktEncWrite(t *testing.T) {
                if len(path) > int(pathSize) {
                        path = path[:int(pathSize)]
                }
-               pkt, err := NewPkt(PktTypeFile, path)
+               pkt, err := NewPkt(PktTypeFile, 123, []byte(path))
                if err != nil {
                        panic(err)
                }
@@ -87,7 +87,7 @@ func TestPktEncRead(t *testing.T) {
                if len(path) > int(pathSize) {
                        path = path[:int(pathSize)]
                }
-               pkt, err := NewPkt(PktTypeFile, path)
+               pkt, err := NewPkt(PktTypeFile, 123, []byte(path))
                if err != nil {
                        panic(err)
                }
index 6daab72c643c4eb3f7df571c0c205da48abdf74d..5bffe28d306f6d37301ede3ff433926f54293ae2 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -297,9 +297,13 @@ func (ctx *Ctx) StartI(conn net.Conn, nodeId *NodeId, nice uint8, xxOnly TRxTx,
                },
                PeerStatic: node.NoisePub[:],
        }
+       hs, err := noise.NewHandshakeState(conf)
+       if err != nil {
+               return nil, err
+       }
        state := SPState{
                ctx:            ctx,
-               hs:             noise.NewHandshakeState(conf),
+               hs:             hs,
                Node:           node,
                onlineDeadline: onlineDeadline,
                maxOnlineTime:  maxOnlineTime,
@@ -328,7 +332,11 @@ func (ctx *Ctx) StartI(conn net.Conn, nodeId *NodeId, nice uint8, xxOnly TRxTx,
 
        var buf []byte
        var payload []byte
-       buf, _, _ = state.hs.WriteMessage(nil, firstPayload)
+       buf, _, _, err = state.hs.WriteMessage(nil, firstPayload)
+       if err != nil {
+               state.dirUnlock()
+               return nil, err
+       }
        sds := SDS{"node": nodeId, "nice": strconv.Itoa(int(nice))}
        ctx.LogD("sp-start", sds, "sending first message")
        conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second))
@@ -371,9 +379,13 @@ func (ctx *Ctx) StartR(conn net.Conn, nice uint8, xxOnly TRxTx) (*SPState, error
                        Public:  ctx.Self.NoisePub[:],
                },
        }
+       hs, err := noise.NewHandshakeState(conf)
+       if err != nil {
+               return nil, err
+       }
        state := SPState{
                ctx:          ctx,
-               hs:           noise.NewHandshakeState(conf),
+               hs:           hs,
                nice:         nice,
                payloads:     make(chan []byte),
                infosOurSeen: make(map[[32]byte]struct{}),
@@ -383,7 +395,6 @@ func (ctx *Ctx) StartR(conn net.Conn, nice uint8, xxOnly TRxTx) (*SPState, error
        }
        var buf []byte
        var payload []byte
-       var err error
        ctx.LogD(
                "sp-start",
                SDS{"nice": strconv.Itoa(int(nice))},
@@ -449,7 +460,11 @@ func (ctx *Ctx) StartR(conn net.Conn, nice uint8, xxOnly TRxTx) (*SPState, error
        }
 
        ctx.LogD("sp-start", sds, "sending first message")
-       buf, state.csTheir, state.csOur = state.hs.WriteMessage(nil, firstPayload)
+       buf, state.csTheir, state.csOur, err = state.hs.WriteMessage(nil, firstPayload)
+       if err != nil {
+               state.dirUnlock()
+               return nil, err
+       }
        conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second))
        if err = state.WriteSP(conn, buf); err != nil {
                ctx.LogE("sp-start", SdsAdd(sds, SDS{"err": err}), "")
index 47a20d0a6e85623ee5774bc6d0f135a325aed119..14af6b95f6b020f75b229bb5206ef5dbfdac4b43 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
index 7777ecd50e5c2c213ecf0d829758b713a5ba2af0..86d154b2aa310a36b454e87c36ab989312c80e44 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -20,6 +20,7 @@ package nncp
 
 import (
        "bufio"
+       "bytes"
        "compress/zlib"
        "fmt"
        "io"
@@ -51,7 +52,7 @@ func newNotification(fromTo *FromToYAML, subject string) io.Reader {
        ))
 }
 
-func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
+func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen, noFile, noFreq, noExec, noTrns bool) bool {
        isBad := false
        for job := range ctx.Jobs(nodeId, TRx) {
                pktName := filepath.Base(job.Fd.Name())
@@ -92,35 +93,45 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                sds["size"] = strconv.FormatInt(pktSize, 10)
                ctx.LogD("rx", sds, "taken")
                switch pkt.Type {
-               case PktTypeMail:
-                       recipients := string(pkt.Path[:int(pkt.PathLen)])
+               case PktTypeExec:
+                       if noExec {
+                               goto Closing
+                       }
+                       path := bytes.Split(pkt.Path[:int(pkt.PathLen)], []byte{0})
+                       handle := string(path[0])
+                       args := make([]string, 0, len(path)-1)
+                       for _, p := range path[1:] {
+                               args = append(args, string(p))
+                       }
                        sds := SdsAdd(sds, SDS{
-                               "type": "mail",
-                               "dst":  recipients,
+                               "type": "exec",
+                               "dst":  strings.Join(append([]string{handle}, args...), " "),
                        })
                        decompressor, err := zlib.NewReader(pipeR)
                        if err != nil {
                                log.Fatalln(err)
                        }
                        sender := ctx.Neigh[*job.PktEnc.Sender]
-                       sendmail := sender.Sendmail
-                       if len(sendmail) == 0 {
-                               ctx.LogE("rx", SdsAdd(sds, SDS{"err": "No sendmail configured"}), "")
+                       cmdline, exists := sender.Exec[handle]
+                       if !exists || len(cmdline) == 0 {
+                               ctx.LogE("rx", SdsAdd(sds, SDS{"err": "No handle found"}), "")
                                isBad = true
                                goto Closing
                        }
                        if !dryRun {
                                cmd := exec.Command(
-                                       sendmail[0],
-                                       append(
-                                               sendmail[1:len(sendmail)],
-                                               strings.Split(recipients, " ")...,
-                                       )...,
+                                       cmdline[0],
+                                       append(cmdline[1:len(cmdline)], args...)...,
+                               )
+                               cmd.Env = append(
+                                       cmd.Env,
+                                       "NNCP_SELF="+ctx.Self.Id.String(),
+                                       "NNCP_SENDER="+sender.Id.String(),
+                                       "NNCP_NICE="+strconv.Itoa(int(pkt.Nice)),
                                )
-                               cmd.Env = append(cmd.Env, "NNCP_SENDER="+sender.Id.String())
                                cmd.Stdin = decompressor
                                if err = cmd.Run(); err != nil {
-                                       ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "sendmail")
+                                       ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "handle")
                                        isBad = true
                                        goto Closing
                                }
@@ -138,6 +149,9 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                }
                        }
                case PktTypeFile:
+                       if noFile {
+                               goto Closing
+                       }
                        dst := string(pkt.Path[:int(pkt.PathLen)])
                        sds := SdsAdd(sds, SDS{"type": "file", "dst": dst})
                        if filepath.IsAbs(dst) {
@@ -207,8 +221,8 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                        ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "remove")
                                        isBad = true
                                }
-                               sendmail := ctx.Neigh[*ctx.SelfId].Sendmail
-                               if ctx.NotifyFile != nil {
+                               sendmail, exists := ctx.Neigh[*ctx.SelfId].Exec["sendmail"]
+                               if exists && len(sendmail) > 0 && ctx.NotifyFile != nil {
                                        cmd := exec.Command(
                                                sendmail[0],
                                                append(sendmail[1:len(sendmail)], ctx.NotifyFile.To)...,
@@ -223,6 +237,9 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                }
                        }
                case PktTypeFreq:
+                       if noFreq {
+                               goto Closing
+                       }
                        src := string(pkt.Path[:int(pkt.PathLen)])
                        if filepath.IsAbs(src) {
                                ctx.LogE("rx", sds, "non-relative source path")
@@ -249,7 +266,7 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                if sender.FreqChunked == 0 {
                                        err = ctx.TxFile(
                                                sender,
-                                               job.PktEnc.Nice,
+                                               pkt.Nice,
                                                filepath.Join(*freq, src),
                                                dst,
                                                sender.FreqMinSize,
@@ -257,7 +274,7 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                } else {
                                        err = ctx.TxFileChunked(
                                                sender,
-                                               job.PktEnc.Nice,
+                                               pkt.Nice,
                                                filepath.Join(*freq, src),
                                                dst,
                                                sender.FreqMinSize,
@@ -281,8 +298,8 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                        ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "remove")
                                        isBad = true
                                }
-                               if ctx.NotifyFreq != nil {
-                                       sendmail := ctx.Neigh[*ctx.SelfId].Sendmail
+                               sendmail, exists := ctx.Neigh[*ctx.SelfId].Exec["sendmail"]
+                               if exists && len(sendmail) > 0 && ctx.NotifyFreq != nil {
                                        cmd := exec.Command(
                                                sendmail[0],
                                                append(sendmail[1:len(sendmail)], ctx.NotifyFreq.To)...,
@@ -296,6 +313,9 @@ func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun, doSeen bool) bool {
                                }
                        }
                case PktTypeTrns:
+                       if noTrns {
+                               goto Closing
+                       }
                        dst := new([blake2b.Size256]byte)
                        copy(dst[:], pkt.Path[:int(pkt.PathLen)])
                        nodeId := NodeId(*dst)
index a5687a72c0a18b5663b432fd06ac019f56c760ac..4d49d21857edbad5b6de3d18ec5058ed20b1127e 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -51,8 +51,9 @@ func dirFiles(path string) []string {
        return names
 }
 
-func TestTossEmail(t *testing.T) {
-       f := func(recipients [16]uint8) bool {
+func TestTossExec(t *testing.T) {
+       f := func(replyNice uint8, handleRaw uint32, recipients [16]uint8) bool {
+               handle := strconv.Itoa(int(handleRaw))
                for i, recipient := range recipients {
                        recipients[i] = recipient % 8
                }
@@ -90,11 +91,13 @@ func TestTossEmail(t *testing.T) {
                        ctx.Neigh[*our.Id] = our.Their()
                }
                for _, recipient := range recipients {
-                       if err := ctx.TxMail(
+                       if err := ctx.TxExec(
                                ctx.Neigh[*privates[recipient].Id],
-                               DefaultNiceMail,
-                               "recipient",
-                               []byte{123},
+                               DefaultNiceExec,
+                               replyNice,
+                               handle,
+                               []string{"arg0", "arg1"},
+                               []byte("BODY\n"),
                                1<<15,
                        ); err != nil {
                                t.Error(err)
@@ -108,20 +111,25 @@ func TestTossEmail(t *testing.T) {
                        if len(dirFiles(rxPath)) == 0 {
                                continue
                        }
-                       ctx.Toss(ctx.Self.Id, DefaultNiceMail-1, false, false)
+                       ctx.Toss(ctx.Self.Id, DefaultNiceExec-1, false, false, false, false, false, false)
                        if len(dirFiles(rxPath)) == 0 {
                                return false
                        }
-                       ctx.Neigh[*nodeOur.Id].Sendmail = []string{"/bin/sh", "-c", "false"}
-                       ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false)
+                       ctx.Neigh[*nodeOur.Id].Exec = make(map[string][]string)
+                       ctx.Neigh[*nodeOur.Id].Exec[handle] = []string{"/bin/sh", "-c", "false"}
+                       ctx.Toss(ctx.Self.Id, DefaultNiceExec, false, false, false, false, false, false)
                        if len(dirFiles(rxPath)) == 0 {
                                return false
                        }
-                       ctx.Neigh[*nodeOur.Id].Sendmail = []string{
+                       ctx.Neigh[*nodeOur.Id].Exec[handle] = []string{
                                "/bin/sh", "-c",
-                               fmt.Sprintf("cat >> %s", filepath.Join(spool, "mbox")),
+                               fmt.Sprintf(
+                                       "echo $NNCP_NICE $0 $1 >> %s ; cat >> %s",
+                                       filepath.Join(spool, "mbox"),
+                                       filepath.Join(spool, "mbox"),
+                               ),
                        }
-                       ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false)
+                       ctx.Toss(ctx.Self.Id, DefaultNiceExec, false, false, false, false, false, false)
                        if len(dirFiles(rxPath)) != 0 {
                                return false
                        }
@@ -132,7 +140,11 @@ func TestTossEmail(t *testing.T) {
                }
                expected := make([]byte, 0, 16)
                for i := 0; i < 16; i++ {
-                       expected = append(expected, 123)
+                       expected = append(
+                               expected,
+                               []byte(fmt.Sprintf("%d arg0 arg1\n", replyNice))...,
+                       )
+                       expected = append(expected, []byte("BODY\n")...)
                }
                return bytes.Compare(mbox, expected) == 0
        }
@@ -195,12 +207,12 @@ func TestTossFile(t *testing.T) {
                }
                rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
                os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
-               ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false)
+               ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false)
                if len(dirFiles(rxPath)) == 0 {
                        return false
                }
                ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
-               ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false)
+               ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false)
                if len(dirFiles(rxPath)) != 0 {
                        return false
                }
@@ -270,7 +282,7 @@ func TestTossFileSameName(t *testing.T) {
                rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
                os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
                ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
-               ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false)
+               ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false)
                expected := make(map[string]struct{})
                expected["samefile"] = struct{}{}
                for i := 0; i < files-1; i++ {
@@ -293,7 +305,7 @@ func TestTossFileSameName(t *testing.T) {
 }
 
 func TestTossFreq(t *testing.T) {
-       f := func(fileSizes []uint8) bool {
+       f := func(fileSizes []uint8, replyNice uint8) bool {
                if len(fileSizes) == 0 {
                        return true
                }
@@ -328,6 +340,7 @@ func TestTossFreq(t *testing.T) {
                        if err := ctx.TxFreq(
                                ctx.Neigh[*nodeOur.Id],
                                DefaultNiceFreq,
+                               replyNice,
                                fileName,
                                fileName,
                                1<<15,
@@ -340,12 +353,12 @@ func TestTossFreq(t *testing.T) {
                txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
                os.Rename(txPath, rxPath)
                os.MkdirAll(txPath, os.FileMode(0700))
-               ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false)
+               ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false)
                if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
                        return false
                }
                ctx.Neigh[*nodeOur.Id].Freq = &spool
-               ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false)
+               ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false)
                if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
                        return false
                }
@@ -358,7 +371,7 @@ func TestTossFreq(t *testing.T) {
                                panic(err)
                        }
                }
-               ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false)
+               ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false)
                if len(dirFiles(txPath)) == 0 || len(dirFiles(rxPath)) != 0 {
                        return false
                }
@@ -374,6 +387,9 @@ func TestTossFreq(t *testing.T) {
                                t.Error(err)
                                return false
                        }
+                       if pkt.Nice != replyNice {
+                               return false
+                       }
                        dst := string(pkt.Path[:int(pkt.PathLen)])
                        if bytes.Compare(buf.Bytes(), files[dst]) != 0 {
                                return false
@@ -426,7 +442,7 @@ func TestTossTrns(t *testing.T) {
                os.MkdirAll(txPath, os.FileMode(0700))
                for _, data := range datum {
                        pktTrans := Pkt{
-                               Magic:   MagicNNCPPv1,
+                               Magic:   MagicNNCPPv2,
                                Type:    PktTypeTrns,
                                PathLen: blake2b.Size256,
                                Path:    new([MaxPathSize]byte),
@@ -455,7 +471,7 @@ func TestTossTrns(t *testing.T) {
                                panic(err)
                        }
                }
-               ctx.Toss(ctx.Self.Id, 123, false, false)
+               ctx.Toss(ctx.Self.Id, 123, false, false, false, false, false, false)
                if len(dirFiles(rxPath)) != 0 {
                        return false
                }
@@ -467,7 +483,6 @@ func TestTossTrns(t *testing.T) {
                        for k, data := range datum {
                                if bytes.Compare(dataRead, data) == 0 {
                                        delete(datum, k)
-                                       break
                                }
                        }
                }
index 5dff27c3be2aa5dcd030eabb0ea8d1bc20191da6..43198138b6440907abf09668e31c0cff7fc4b649 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -68,13 +68,7 @@ func (ctx *Ctx) Tx(node *Node, pkt *Pkt, nice uint8, size, minSize int64, src io
 
        var pipeRPrev io.Reader
        for i := 1; i < len(hops); i++ {
-               pktTrans := Pkt{
-                       Magic:   MagicNNCPPv1,
-                       Type:    PktTypeTrns,
-                       PathLen: blake2b.Size256,
-                       Path:    new([MaxPathSize]byte),
-               }
-               copy(pktTrans.Path[:], hops[i-1].Id[:])
+               pktTrns, _ := NewPkt(PktTypeTrns, 0, hops[i-1].Id[:])
                curSize += PktOverhead + PktEncOverhead
                pipeRPrev = pipeR
                pipeR, pipeW = io.Pipe()
@@ -86,7 +80,7 @@ func (ctx *Ctx) Tx(node *Node, pkt *Pkt, nice uint8, size, minSize int64, src io
                        }, "trns wrote")
                        errs <- PktEncWrite(ctx.Self, node, pkt, nice, size, 0, src, dst)
                        dst.Close()
-               }(hops[i], &pktTrans, curSize, pipeRPrev, pipeW)
+               }(hops[i], pktTrns, curSize, pipeRPrev, pipeW)
        }
        go func() {
                _, err := io.Copy(tmp.W, pipeR)
@@ -157,7 +151,7 @@ func (ctx *Ctx) TxFile(node *Node, nice uint8, srcPath, dstPath string, minSize
        if filepath.IsAbs(dstPath) {
                return errors.New("Relative destination path required")
        }
-       pkt, err := NewPkt(PktTypeFile, dstPath)
+       pkt, err := NewPkt(PktTypeFile, nice, []byte(dstPath))
        if err != nil {
                return err
        }
@@ -169,25 +163,19 @@ func (ctx *Ctx) TxFile(node *Node, nice uint8, srcPath, dstPath string, minSize
                return err
        }
        _, err = ctx.Tx(node, pkt, nice, fileSize, minSize, reader)
+       sds := SDS{
+               "type": "file",
+               "node": node.Id,
+               "nice": strconv.Itoa(int(nice)),
+               "src":  srcPath,
+               "dst":  dstPath,
+               "size": strconv.FormatInt(fileSize, 10),
+       }
        if err == nil {
-               ctx.LogI("tx", SDS{
-                       "type": "file",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "src":  srcPath,
-                       "dst":  dstPath,
-                       "size": strconv.FormatInt(fileSize, 10),
-               }, "sent")
+               ctx.LogI("tx", sds, "sent")
        } else {
-               ctx.LogE("tx", SDS{
-                       "type": "file",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "src":  srcPath,
-                       "dst":  dstPath,
-                       "size": strconv.FormatInt(fileSize, 10),
-                       "err":  err,
-               }, "sent")
+               sds["err"] = err
+               ctx.LogE("tx", sds, "sent")
        }
        return err
 }
@@ -211,6 +199,29 @@ func (ctx *Ctx) TxFileChunked(node *Node, nice uint8, srcPath, dstPath string, m
                return err
        }
 
+       if fileSize <= chunkSize {
+               pkt, err := NewPkt(PktTypeFile, nice, []byte(dstPath))
+               if err != nil {
+                       return err
+               }
+               _, err = ctx.Tx(node, pkt, nice, fileSize, minSize, reader)
+               sds := SDS{
+                       "type": "file",
+                       "node": node.Id,
+                       "nice": strconv.Itoa(int(nice)),
+                       "src":  srcPath,
+                       "dst":  dstPath,
+                       "size": strconv.FormatInt(fileSize, 10),
+               }
+               if err == nil {
+                       ctx.LogI("tx", sds, "sent")
+               } else {
+                       sds["err"] = err
+                       ctx.LogE("tx", sds, "sent")
+               }
+               return err
+       }
+
        leftSize := fileSize
        metaPkt := ChunkedMeta{
                Magic:     MagicNNCPMv1,
@@ -234,7 +245,7 @@ func (ctx *Ctx) TxFileChunked(node *Node, nice uint8, srcPath, dstPath string, m
                        sizeToSend = chunkSize
                }
                path = dstPath + ChunkedSuffixPart + strconv.Itoa(chunkNum)
-               pkt, err = NewPkt(PktTypeFile, path)
+               pkt, err = NewPkt(PktTypeFile, nice, []byte(path))
                if err != nil {
                        return err
                }
@@ -250,25 +261,19 @@ func (ctx *Ctx) TxFileChunked(node *Node, nice uint8, srcPath, dstPath string, m
                        minSize,
                        io.TeeReader(reader, hsh),
                )
+               sds := SDS{
+                       "type": "file",
+                       "node": node.Id,
+                       "nice": strconv.Itoa(int(nice)),
+                       "src":  srcPath,
+                       "dst":  path,
+                       "size": strconv.FormatInt(sizeToSend, 10),
+               }
                if err == nil {
-                       ctx.LogI("tx", SDS{
-                               "type": "file",
-                               "node": node.Id,
-                               "nice": strconv.Itoa(int(nice)),
-                               "src":  srcPath,
-                               "dst":  path,
-                               "size": strconv.FormatInt(sizeToSend, 10),
-                       }, "sent")
+                       ctx.LogI("tx", sds, "sent")
                } else {
-                       ctx.LogE("tx", SDS{
-                               "type": "file",
-                               "node": node.Id,
-                               "nice": strconv.Itoa(int(nice)),
-                               "src":  srcPath,
-                               "dst":  path,
-                               "size": strconv.FormatInt(sizeToSend, 10),
-                               "err":  err,
-                       }, "sent")
+                       sds["err"] = err
+                       ctx.LogE("tx", sds, "sent")
                        return err
                }
                hsh.Sum(metaPkt.Checksums[chunkNum][:0])
@@ -284,36 +289,30 @@ func (ctx *Ctx) TxFileChunked(node *Node, nice uint8, srcPath, dstPath string, m
                return err
        }
        path = dstPath + ChunkedSuffixMeta
-       pkt, err = NewPkt(PktTypeFile, path)
+       pkt, err = NewPkt(PktTypeFile, nice, []byte(path))
        if err != nil {
                return err
        }
        metaPktSize := int64(metaBuf.Len())
        _, err = ctx.Tx(node, pkt, nice, metaPktSize, minSize, &metaBuf)
+       sds := SDS{
+               "type": "file",
+               "node": node.Id,
+               "nice": strconv.Itoa(int(nice)),
+               "src":  srcPath,
+               "dst":  path,
+               "size": strconv.FormatInt(metaPktSize, 10),
+       }
        if err == nil {
-               ctx.LogI("tx", SDS{
-                       "type": "file",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "src":  srcPath,
-                       "dst":  path,
-                       "size": strconv.FormatInt(metaPktSize, 10),
-               }, "sent")
+               ctx.LogI("tx", sds, "sent")
        } else {
-               ctx.LogE("tx", SDS{
-                       "type": "file",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "src":  srcPath,
-                       "dst":  path,
-                       "size": strconv.FormatInt(metaPktSize, 10),
-                       "err":  err,
-               }, "sent")
+               sds["err"] = err
+               ctx.LogE("tx", sds, "sent")
        }
        return err
 }
 
-func (ctx *Ctx) TxFreq(node *Node, nice uint8, srcPath, dstPath string, minSize int64) error {
+func (ctx *Ctx) TxFreq(node *Node, nice, replyNice uint8, srcPath, dstPath string, minSize int64) error {
        dstPath = filepath.Clean(dstPath)
        if filepath.IsAbs(dstPath) {
                return errors.New("Relative destination path required")
@@ -322,36 +321,37 @@ func (ctx *Ctx) TxFreq(node *Node, nice uint8, srcPath, dstPath string, minSize
        if filepath.IsAbs(srcPath) {
                return errors.New("Relative source path required")
        }
-       pkt, err := NewPkt(PktTypeFreq, srcPath)
+       pkt, err := NewPkt(PktTypeFreq, replyNice, []byte(srcPath))
        if err != nil {
                return err
        }
        src := strings.NewReader(dstPath)
        size := int64(src.Len())
        _, err = ctx.Tx(node, pkt, nice, size, minSize, src)
+       sds := SDS{
+               "type":      "freq",
+               "node":      node.Id,
+               "nice":      strconv.Itoa(int(nice)),
+               "replynice": strconv.Itoa(int(replyNice)),
+               "src":       srcPath,
+               "dst":       dstPath,
+       }
        if err == nil {
-               ctx.LogI("tx", SDS{
-                       "type": "freq",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "src":  srcPath,
-                       "dst":  dstPath,
-               }, "sent")
+               ctx.LogI("tx", sds, "sent")
        } else {
-               ctx.LogE("tx", SDS{
-                       "type": "freq",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "src":  srcPath,
-                       "dst":  dstPath,
-                       "err":  err,
-               }, "sent")
+               sds["err"] = err
+               ctx.LogE("tx", sds, "sent")
        }
        return err
 }
 
-func (ctx *Ctx) TxMail(node *Node, nice uint8, recipient string, body []byte, minSize int64) error {
-       pkt, err := NewPkt(PktTypeMail, recipient)
+func (ctx *Ctx) TxExec(node *Node, nice, replyNice uint8, handle string, args []string, body []byte, minSize int64) error {
+       path := make([][]byte, 0, 1+len(args))
+       path = append(path, []byte(handle))
+       for _, arg := range args {
+               path = append(path, []byte(arg))
+       }
+       pkt, err := NewPkt(PktTypeExec, replyNice, bytes.Join(path, []byte{0}))
        if err != nil {
                return err
        }
@@ -366,34 +366,31 @@ func (ctx *Ctx) TxMail(node *Node, nice uint8, recipient string, body []byte, mi
        compressor.Close()
        size := int64(compressed.Len())
        _, err = ctx.Tx(node, pkt, nice, size, minSize, &compressed)
+       sds := SDS{
+               "type":      "exec",
+               "node":      node.Id,
+               "nice":      strconv.Itoa(int(nice)),
+               "replynice": strconv.Itoa(int(replyNice)),
+               "dst":       strings.Join(append([]string{handle}, args...), " "),
+               "size":      strconv.FormatInt(size, 10),
+       }
        if err == nil {
-               ctx.LogI("tx", SDS{
-                       "type": "mail",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "dst":  recipient,
-                       "size": strconv.FormatInt(size, 10),
-               }, "sent")
+               ctx.LogI("tx", sds, "sent")
        } else {
-               ctx.LogE("tx", SDS{
-                       "type": "mail",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "dst":  recipient,
-                       "size": strconv.FormatInt(size, 10),
-                       "err":  err,
-               }, "sent")
+               sds["err"] = err
+               ctx.LogE("tx", sds, "sent")
        }
        return err
 }
 
 func (ctx *Ctx) TxTrns(node *Node, nice uint8, size int64, src io.Reader) error {
-       ctx.LogD("tx", SDS{
+       sds := SDS{
                "type": "trns",
                "node": node.Id,
                "nice": strconv.Itoa(int(nice)),
                "size": strconv.FormatInt(size, 10),
-       }, "taken")
+       }
+       ctx.LogD("tx", sds, "taken")
        tmp, err := ctx.NewTmpFileWHash()
        if err != nil {
                return err
@@ -404,20 +401,10 @@ func (ctx *Ctx) TxTrns(node *Node, nice uint8, size int64, src io.Reader) error
        nodePath := filepath.Join(ctx.Spool, node.Id.String())
        err = tmp.Commit(filepath.Join(nodePath, string(TTx)))
        if err == nil {
-               ctx.LogI("tx", SDS{
-                       "type": "trns",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "size": strconv.FormatInt(size, 10),
-               }, "sent")
+               ctx.LogI("tx", sds, "sent")
        } else {
-               ctx.LogI("tx", SDS{
-                       "type": "trns",
-                       "node": node.Id,
-                       "nice": strconv.Itoa(int(nice)),
-                       "size": strconv.FormatInt(size, 10),
-                       "err":  err,
-               }, "sent")
+               sds["err"] = err
+               ctx.LogI("tx", sds, "sent")
        }
        os.Symlink(nodePath, filepath.Join(ctx.Spool, node.Name))
        return err
index ad721bc09e90a80577837fb99a845538c77f71e0..6ea7ef2cb7b9613c4e78fe7020f9c6420af794c7 100644 (file)
@@ -1,6 +1,6 @@
 /*
 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2018 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
@@ -33,7 +33,7 @@ import (
 )
 
 func TestTx(t *testing.T) {
-       f := func(hops uint8, pathSrc, data string, nice uint8, padSize int16) bool {
+       f := func(hops uint8, pathSrc, data string, nice, replyNice uint8, padSize int16) bool {
                if len(pathSrc) > int(MaxPathSize) {
                        pathSrc = pathSrc[:MaxPathSize]
                }
@@ -76,7 +76,7 @@ func TestTx(t *testing.T) {
                        privates[*node.Id] = node
                        nodeTgt.Via = append(nodeTgt.Via, node.Id)
                }
-               pkt, err := NewPkt(PktTypeMail, pathSrc)
+               pkt, err := NewPkt(PktTypeExec, replyNice, []byte(pathSrc))
                src := strings.NewReader(data)
                dstNode, err := ctx.Tx(
                        nodeTgt,
@@ -121,7 +121,10 @@ func TestTx(t *testing.T) {
                                return false
                        }
                        if *hopId == *nodeTgt.Id {
-                               if pkt.Type != PktTypeMail {
+                               if pkt.Type != PktTypeExec {
+                                       return false
+                               }
+                               if pkt.Nice != replyNice {
                                        return false
                                }
                                if !bytes.HasPrefix(pkt.Path[:], []byte(pathSrc)) {
index fc3a9f3b3c4fba0af38ac409e8867672499d26e4..01638cb52dafe42224b938fb517721f984c03100 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fc3a9f3b3c4fba0af38ac409e8867672499d26e4
+Subproject commit 01638cb52dafe42224b938fb517721f984c03100
index d585fd2cc9195196078f516b69daff6744ef5e84..650f4a345ab4e5b245a3034b110ebc7299e68186 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d585fd2cc9195196078f516b69daff6744ef5e84
+Subproject commit 650f4a345ab4e5b245a3034b110ebc7299e68186
index d866cfc389cec985d6fda2859936a575a55a3ab6..136a25c244d3019482a795d728110278d6ba09a4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d866cfc389cec985d6fda2859936a575a55a3ab6
+Subproject commit 136a25c244d3019482a795d728110278d6ba09a4
index 83801418e1b59fb1880e363299581ee543af32ca..37707fdb30a5b38865cfb95e5aab41707daec7fd 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 83801418e1b59fb1880e363299581ee543af32ca
+Subproject commit 37707fdb30a5b38865cfb95e5aab41707daec7fd