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
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) шифрование применяется ко всем
nncp-cfgnew \
nncp-check \
nncp-daemon \
+ nncp-exec \
nncp-file \
nncp-freq \
nncp-log \
- nncp-mail \
nncp-pkt \
nncp-reass \
nncp-rm \
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
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
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)
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,
точка-точка}, аутентифицируются известными публичными ключами
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,
--- /dev/null
+#!/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
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
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
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
@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,
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
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
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.
@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.
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
@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
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
3: 0e9e229501bf0ca42d4aa07393d19406d40b179f3922a3986ef12b41019b45a3
@end verbatim
+ Do not forget about @ref{ChunkedZFS, possible} ZFS deduplication issues.
+
@node nncp-rm
@section nncp-rm
@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
@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
@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 Нет
@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
@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}
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
@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.
* Web feeds: Feeds.
* Web pages: WARCs.
* BitTorrent and huge files: BitTorrent.
+* Downloading service: DownloadService.
* Git::
* Multimedia streaming: Multimedia.
@end menu
@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.
@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.
@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.
@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
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}
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
@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
@option{-mkdir} для ясности.
@item
-Опция @option{-minsize} задётся в KiB, а не байтах, для удобства.
+Опция @option{-minsize} задаётся в KiB, а не байтах, для удобства.
@item
Команда @command{nncp-newcfg} переименована в @command{nncp-cfgnew},
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
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!
@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
@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
@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
@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
KISS}!
Просто скажите вашим обоим Postfix-ам (на сервере и ноутбуке) отправлять
-сообщения через NNCP (@ref{nncp-mail}) на заданный узел. Это делается
+сообщения через NNCP (@ref{nncp-exec}) на заданный узел. Это делается
аналогично тому как с UUCP, и описано в
@url{http://www.postfix.org/UUCP_README.html, документации Postfix}.
@ref{nncp-daemon} может быть соединён с @ref{nncp-caller} длительное
время -- он создаёт TCP соединение на многие часы. Когда SMTP сервер
-получает письмо, то вызывает @ref{nncp-mail} для создания исходящего
+получает письмо, то вызывает @ref{nncp-exec} для создания исходящего
зашифрованного пакета. Демон ежесекундно проверяет исходящую директорию
и сразу же посылает оповещение о недоставленных пакетах противоположной
стороне, которая сразу же их может скачать.
проблематично получить. Более того, каждый обрыв может приводить к
отсылке данных с самого начала, что не всегда по карману.
-Просто отправьте вашу @ref{nncp-mail, почту} и @ref{nncp-file, файлы}
+Просто отправьте вашу @ref{nncp-exec, почту} и @ref{nncp-file, файлы}
через NNCP. Вы сможете использовать или offline методы доставки --
читайте о них в следующем разделе, либо использовать поставляемый NNCP
@ref{nncp-daemon, TCP демон}.
@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}.
@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.
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}.
--- /dev/null
+#!/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
--- /dev/null
+#!/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
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
@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
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
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) шифрование применяется ко всем
-# $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
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>
- Generate NNCP configuration file using the command:
# umask 077
- # nncp-newcfg > %%PREFIX%%/etc/nncp.yaml
+ # nncp-cfgnew > %%PREFIX%%/etc/nncp.yaml
======================================================================
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
--- /dev/null
+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
-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
-Subproject commit 3cd3006ad829a0afc7ca3d964ff333ef068464bd
+Subproject commit 92c161713a13cc78403468c09f1557eb7c4a3a4a
/*
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
/*
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
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`
Id: nodeId,
ExchPub: new([32]byte),
SignPub: ed25519.PublicKey(signPub),
- Sendmail: yml.Sendmail,
+ Exec: yml.Exec,
Incoming: incoming,
Freq: freq,
FreqChunked: freqChunked,
/*
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
/*
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
/*
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
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])
/*
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
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()
/*
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
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()
/*
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
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])
/*
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
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()
}
/*
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
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,
/*
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
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()
}
/*
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
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()
}
/*
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
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-// Send email via NNCP
+// Send execution command via NNCP
package main
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()
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 {
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 {
/*
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
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()
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(
nice,
flag.Arg(0),
splitted[1],
- int64(*minSize)*1024,
- int64(*chunkSize)*1024,
+ minSize,
+ chunkSize,
)
}
if err != nil {
/*
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
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()
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 {
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)
if err = ctx.TxFreq(
node,
nice,
+ replyNice,
splitted[1],
dst,
int64(*minSize)*1024,
/*
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
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()
}
/*
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
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.")
}
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
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
/*
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
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, `
/*
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
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])
/*
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
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()
}
/*
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
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()
}
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")
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)
/*
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
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()
}
/*
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
/*
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
/*
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
"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(
}
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)
/*
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
/*
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
/*
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
/*
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
/*
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
ExchPub *[32]byte
SignPub ed25519.PublicKey
NoisePub *[32]byte
- Sendmail []string
+ Exec map[string][]string
Incoming *string
Freq *string
FreqChunked int64
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)
/*
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
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
)
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")
type Pkt struct {
Magic [8]byte
Type PktType
+ Nice uint8
PathLen uint8
Path *[MaxPathSize]byte
}
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
}
/*
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
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)
}
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)
}
/*
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
},
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,
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))
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{}),
}
var buf []byte
var payload []byte
- var err error
ctx.LogD(
"sp-start",
SDS{"nice": strconv.Itoa(int(nice))},
}
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}), "")
/*
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
/*
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
import (
"bufio"
+ "bytes"
"compress/zlib"
"fmt"
"io"
))
}
-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())
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
}
}
}
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) {
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)...,
}
}
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")
if sender.FreqChunked == 0 {
err = ctx.TxFile(
sender,
- job.PktEnc.Nice,
+ pkt.Nice,
filepath.Join(*freq, src),
dst,
sender.FreqMinSize,
} else {
err = ctx.TxFileChunked(
sender,
- job.PktEnc.Nice,
+ pkt.Nice,
filepath.Join(*freq, src),
dst,
sender.FreqMinSize,
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)...,
}
}
case PktTypeTrns:
+ if noTrns {
+ goto Closing
+ }
dst := new([blake2b.Size256]byte)
copy(dst[:], pkt.Path[:int(pkt.PathLen)])
nodeId := NodeId(*dst)
/*
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
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
}
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)
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
}
}
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
}
}
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
}
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++ {
}
func TestTossFreq(t *testing.T) {
- f := func(fileSizes []uint8) bool {
+ f := func(fileSizes []uint8, replyNice uint8) bool {
if len(fileSizes) == 0 {
return true
}
if err := ctx.TxFreq(
ctx.Neigh[*nodeOur.Id],
DefaultNiceFreq,
+ replyNice,
fileName,
fileName,
1<<15,
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
}
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
}
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
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),
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
}
for k, data := range datum {
if bytes.Compare(dataRead, data) == 0 {
delete(datum, k)
- break
}
}
}
/*
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
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()
}, "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)
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
}
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
}
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,
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
}
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])
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")
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
}
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
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
/*
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
)
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]
}
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,
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)) {
-Subproject commit fc3a9f3b3c4fba0af38ac409e8867672499d26e4
+Subproject commit 01638cb52dafe42224b938fb517721f984c03100
-Subproject commit d585fd2cc9195196078f516b69daff6744ef5e84
+Subproject commit 650f4a345ab4e5b245a3034b110ebc7299e68186
-Subproject commit d866cfc389cec985d6fda2859936a575a55a3ab6
+Subproject commit 136a25c244d3019482a795d728110278d6ba09a4
-Subproject commit 83801418e1b59fb1880e363299581ee543af32ca
+Subproject commit 37707fdb30a5b38865cfb95e5aab41707daec7fd