NNCP is copylefted free software: see the file COPYING for copying
conditions. It should work on all POSIX-compatible systems. Easy
-integration with existing SMTP servers. Single YAML configuration file.
+integration with existing SMTP servers. Single Hjson configuration file.
Home page: http://www.nncpgo.org/
NNCP это свободное программное обеспечением: условия распространения
находятся в файле COPYING. Оно должно работать на всех POSIX-совместимых
системах. Лёгкая интеграция с существующими SMTP серверами. Единственный
-конфигурационный YAML файл.
+конфигурационный Hjson файл.
Домашняя страница: http://www.nncpgo.org/
PREFIX ?= /usr/local
SENDMAIL ?= /usr/sbin/sendmail
-CFGPATH ?= $(PREFIX)/etc/nncp.yaml
+CFGPATH ?= $(PREFIX)/etc/nncp.hjson
SPOOLPATH ?= /var/spool/nncp
LOGPATH ?= /var/spool/nncp/log
INFODIR = $(DESTDIR)$(PREFIX)/info
DOCDIR = $(DESTDIR)$(PREFIX)/share/doc/nncp
-MOD = go.cypherpunks.ru/nncp/v4
+MOD = go.cypherpunks.ru/nncp/v5
LDFLAGS = \
-X $(MOD).Version=$(VERSION) \
должно работать на всех @url{https://ru.wikipedia.org/wiki/POSIX,
POSIX}-совместимых системах. Лёгкая @ref{Integration, интеграция} с
существующими @url{https://ru.wikipedia.org/wiki/SMTP, SMTP} серверами.
-Единственный конфигурационный @url{http://yaml.org/, YAML} файл.
+Единственный конфигурационный @url{https://hjson.org/, Hjson} файл.
Зачем создавать ещё одно решение с принципом сохранить-и-переслать когда
уже существуют UUCP, FTN и даже SMTP? Посмотрите @ref{Сравнение, сравнение}!
It should work on all @url{https://en.wikipedia.org/wiki/POSIX,
POSIX}-compatible systems. Easy @ref{Integration, integration} with existing
@url{https://en.wikipedia.org/wiki/SMTP, SMTP} servers. Single
-@url{http://yaml.org/, YAML} configuration file.
+@url{https://hjson.org/, Hjson} configuration file.
Why create yet another store-and-forward solution when UUCP, FTN and
even SMTP exists? Look in @ref{Comparison, comparison} section!
Example list of call structures:
@verbatim
-calls:
- -
- cron: "*/1 * * * MON-FRI"
- onlinedeadline: 3600
- nice: PRIORITY+10
- -
- cron: "30 * * * SAT,SUN"
- onlinedeadline: 1800
- maxonlinetime: 1750
- nice: NORMAL
- rxrate: 10
- txrate: 20
- -
- cron: "0 * * * SAT,SUN"
- xx: rx
- addr: lan
+calls: [
+ {
+ cron: "*/1 * * * MON-FRI"
+ onlinedeadline: 3600
+ nice: PRIORITY+10
+ },
+ {
+ cron: "30 * * * SAT,SUN"
+ onlinedeadline: 1800
+ maxonlinetime: 1750
+ nice: NORMAL
+ rxrate: 10
+ txrate: 20
+ },
+ {
+ cron: "0 * * * SAT,SUN"
+ xx: rx
+ addr: lan
+ },
+]
@end verbatim
tells that on work days of the week call that node every minute,
@node Configuration
@unnumbered Configuration file
-Example YAML configuration file:
+Example @url{https://hjson.org/, Hjson} configuration file:
@verbatim
-spool: /var/spool/nncp
-log: /var/spool/nncp/log
-notify:
- file:
- from: nncp@localhost
- to: user+file@example.com
- freq:
- from: nncp@localhost
- to: user+freq@example.com
-self:
- id: TIJQL...2NGIA
- exchpub: CYVGQ...PSEWQ
- exchprv: 65PUY...MPZ3Q
- signpub: 2NMVC...CMH5Q
- signprv: 555JD...RGD6Y
- noiseprv: D62XU...NKYPA
- noisepub: KIBKK...ESM7Q
-neigh:
- self:
+{
+ spool: /var/spool/nncp
+ log: /var/spool/nncp/log
+ notify: {
+ file: {
+ from: nncp@localhost
+ to: user+file@example.com
+ }
+ freq: {
+ from: nncp@localhost
+ to: user+freq@example.com
+ }
+ }
+ self: {
id: TIJQL...2NGIA
exchpub: CYVGQ...PSEWQ
+ exchprv: 65PUY...MPZ3Q
signpub: 2NMVC...CMH5Q
+ signprv: 555JD...RGD6Y
+ noiseprv: D62XU...NKYPA
noisepub: KIBKK...ESM7Q
- exec:
- sendmail: [/usr/sbin/sendmail]
- alice:
- id: XJZBK...65IJQ
- exchpub: MJACJ...FAI6A
- signpub: T4AFC...N2FRQ
- noisepub: UBM5K...VI42A
- exec:
- flag: ["/usr/bin/touch", "-t"]
- incoming: /home/alice/incoming
- onlinedeadline: 1800
- maxonlinetime: 3600
- addrs:
- lan: "[fe80::1234%igb0]:5400"
- internet: alice.com:3389
- calls:
- -
- cron: "*/2 * * * *"
- bob:
- id: 2IZNP...UYGYA
- exchpub: WFLMZ...B7NHA
- signpub: GTGXG...IE3OA
- exec:
- sendmail: [/usr/sbin/sendmail]
- warcer: [/path/to/warcer.sh]
- wgeter: [/path/to/wgeter.sh]
- freq: /home/bob/pub
- freqchunked: 1024
- freqminsize: 2048
- via: [alice]
- rxrate: 10
- txrate: 20
+ }
+ neigh: {
+ self: {
+ id: TIJQL...2NGIA
+ exchpub: CYVGQ...PSEWQ
+ signpub: 2NMVC...CMH5Q
+ noisepub: KIBKK...ESM7Q
+ exec: {sendmail: ["/usr/sbin/sendmail"]}
+ }
+ alice: {
+ id: "XJZBK...65IJQ"
+ exchpub: MJACJ...FAI6A
+ signpub: T4AFC...N2FRQ
+ noisepub: UBM5K...VI42A
+ exec: {flag: ["/usr/bin/touch", "-t"]}
+ incoming: "/home/alice/incoming"
+ onlinedeadline: 1800
+ maxonlinetime: 3600
+ addrs: {
+ lan: "[fe80::1234%igb0]:5400"
+ internet: alice.com:3389
+ }
+ calls: [
+ {
+ cron: "*/2 * * * *"
+ },
+ ]
+ }
+ bob: {
+ id: 2IZNP...UYGYA
+ exchpub: WFLMZ...B7NHA
+ signpub: GTGXG...IE3OA
+ exec: {
+ sendmail: ["/usr/sbin/sendmail"]
+ warcer: ["/path/to/warcer.sh"]
+ wgeter: ["/path/to/wgeter.sh"]
+ }
+ freq: "/home/bob/pub"
+ freqchunked: 1024
+ freqminsize: 2048
+ via: ["alice"]
+ rxrate: 10
+ txrate: 20
+ }
+ }
+}
@end verbatim
@strong{spool} field contains an absolute path to @ref{Spool, spool}
@section nncp-cfgenc
@verbatim
-$ nncp-cfgmin [options] [-s INT] [-t INT] [-p INT] cfg.yaml > cfg.yaml.eblob
-$ nncp-cfgmin [options] -d cfg.yaml.eblob > cfg.yaml
+$ nncp-cfgmin [options] [-s INT] [-t INT] [-p INT] cfg.hjson > cfg.hjson.eblob
+$ nncp-cfgmin [options] -d cfg.hjson.eblob > cfg.hjson
@end verbatim
-This command allows you to encrypt provided @file{cfg.yaml} file with
+This command allows you to encrypt provided @file{cfg.hjson} file with
the passphrase, producing @ref{EBlob, eblob}, to safely keep your
configuration file with private keys. This utility was written for users
who do not want (or can not) to use either @url{https://gnupg.org/,
@option{-dump} options parses @file{eblob} and prints parameters used
during its creation. For example:
@verbatim
-$ nncp-cfgenc -dump /usr/local/etc/nncp.yaml.eblob
+$ nncp-cfgenc -dump /usr/local/etc/nncp.hjson.eblob
Strengthening function: Balloon with BLAKE2b-256
Memory space cost: 1048576 bytes
Number of rounds: 16
@section nncp-cfgmin
@verbatim
-$ nncp-cfgmin [options] > stripped.yaml
+$ nncp-cfgmin [options] > stripped.hjson
@end verbatim
Print out stripped configuration version: only path to @ref{Spool,
@section nncp-cfgnew
@verbatim
-$ nncp-cfgnew [options] > new.yaml
+$ nncp-cfgnew [options] [-nocomments] > new.hjson
@end verbatim
Generate new node configuration: private keys, example configuration
file and print it to stdout. You must use this command when you setup
-the new node.
+the new node. @option{-nocomments} will create configuration file
+without descriptive huge comments -- useful for advanced users.
Pay attention that private keys generation consumes an entropy from your
operating system.
node:
@verbatim
-exec:
+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
того, из коробки не предоставляется никакого шифрования и сильной
аутентификации.
- NNCP требует редактирование единственного YAML @ref{Configuration,
+ NNCP требует редактирование единственного Hjson @ref{Configuration,
конфигурационного файла}.
@item Передача новостей
like GoldEd, not an ordinary email client. Moreover, there is no
out-of-box encryption and strong authentication involved.
- NNCP requires editing of single YAML @ref{Configuration,
+ NNCP requires editing of single Hjson @ref{Configuration,
configuration file}.
@item News transmission
@item @code{github.com/dustin/go-humanize} @tab MIT
@item @code{github.com/flynn/noise} @tab BSD 3-Clause
@item @code{github.com/go-check/check} @tab BSD 2-Clause
-@item @code{github.com/go-yaml/yaml} @tab Apache License 2.0 and MIT
@item @code{github.com/gorhill/cronexpr} @tab GNU GPLv3
+@item @code{github.com/hjson/hjson-go} @tab MIT
@item @code{go.cypherpunks.ru/balloon} @tab GNU LGPLv3
@item @code{golang.org/x/crypto} @tab BSD 3-Clause
@item @code{golang.org/x/net} @tab BSD 3-Clause
easily solved with @ref{CfgExec, exec} handles.
@verbatim
-exec:
+exec: {
warcer: ["/bin/sh", "/path/to/warcer.sh"]
wgeter: ["/bin/sh", "/path/to/wgeter.sh"]
aria2c: [
"--on-download-complete", "aria2-downloaded.sh",
"--on-bt-download-complete", "aria2-downloaded.sh"
]
+}
@end verbatim
@file{warcer.sh} contents:
Then you could verify tarballs signature:
@verbatim
-$ gpg --verify nncp-4.2.0.tar.xz.sig nncp-4.2.0.tar.xz
+$ gpg --verify nncp-5.0.0.tar.xz.sig nncp-5.0.0.tar.xz
@end verbatim
@node Новости
@section Новости
-@node Релиз 4.2.0
-@subsection Релиз 4.2.0
+@node Релиз 5.0.0
+@subsection Релиз 5.0.0
@itemize
+@item @strong{Несовместимое} изменение формата конфигурационного файла:
+ YAML заменён на Hjson, из-за его гораздо большей простоты, без
+ заметного потеря функционала и удобства.
+@item @command{nncp-cfgnew} генерирует конфигурационный файл с
+ множеством комментариев. Можно использовать @option{-nocomments}
+ опцию для старого поведения.
@item Дубликаты имён файлов имеют суффикс @file{.CTR}, вместо
@file{CTR}, чтобы избежать возможных коллизий с @file{.nncp.chunkCTR}.
@item По умолчанию файлы и директории создаются с 666/777 правами
доступа, позволяя управлять ими @command{umask}-ом.
@item Обновлены зависимости.
@item Полное использование go модулей для управления зависимостями
- (используется @code{go.cypherpunks.ru/nncp/v4} namespace).
+ (используется @code{go.cypherpunks.ru/nncp/v5} namespace).
@end itemize
@node Релиз 4.1
See also this page @ref{Новости, on russian}.
-@node Release 4.2.0
-@section Release 4.2.0
+@node Release 5.0.0
+@section Release 5.0.0
@itemize
+@item @strong{Incompatible} configuration file format change: YAML is
+ replaced with Hjson, due to its simplicity, without noticeable lack
+ of either functionality or convenience.
+@item @command{nncp-cfgnew} generates configuration file with many
+ comments. @option{-nocomments} option can be used for an old
+ behaviour.
@item Duplicate filenames have @file{.CTR} suffix, instead of
@file{CTR}, to avoid possible collisions with @file{.nncp.chunkCTR}.
@item Files and directories are created with 666/777 permissions by
default, allowing control with @command{umask}.
@item Updated dependencies.
@item Full usage of go modules for dependencies management
- (@code{go.cypherpunks.ru/nncp/v4} namespace is used).
+ (@code{go.cypherpunks.ru/nncp/v5} namespace is used).
@end itemize
@node Release 4.1
Look @ref{Integrity, here} for finding public keys for tarball authentication.
@verbatim
-$ wget http://www.nncpgo.org/download/nncp-4.2.0.tar.xz
-$ wget http://www.nncpgo.org/download/nncp-4.2.0.tar.xz.sig
-$ gpg --verify nncp-4.2.0.tar.xz.sig nncp-4.2.0.tar.xz
-$ xz -d --stdout nncp-4.2.0.tar.xz | tar xf nncp-4.2.0.tar
-$ make -C nncp-4.2.0 all
+$ wget http://www.nncpgo.org/download/nncp-5.0.0.tar.xz
+$ wget http://www.nncpgo.org/download/nncp-5.0.0.tar.xz.sig
+$ gpg --verify nncp-5.0.0.tar.xz.sig nncp-5.0.0.tar.xz
+$ xz -d --stdout nncp-5.0.0.tar.xz | tar xf nncp-5.0.0.tar
+$ make -C nncp-5.0.0 all
@end verbatim
There is @command{install} target respecting @env{DESTDIR}. It will
follow @ref{General, general} installation instructions
@verbatim
-# make -C nncp-4.2.0 install PREFIX=/usr
+# make -C nncp-5.0.0 install PREFIX=/usr
@end verbatim
@item Ubuntu 14.04
libraries source code. Because of that, it is recommended for porters
to use @ref{Tarballs, tarballs} instead.
-You can obtain it and fetch dependent libraries source code as git submodules:
@verbatim
$ git clone git://git.cypherpunks.ru/nncp.git nncp
$ cd nncp
$ git checkout develop
-$ git submodule update --init
@end verbatim
Also there is mirror of dependent libraries for safety if their native
@item @code{github.com/dustin/go-humanize} @tab @url{git://git.cypherpunks.ru/go-humanize.git}
@item @code{github.com/flynn/noise} @tab @url{git://git.cypherpunks.ru/noise.git}
@item @code{github.com/gorhill/cronexpr} @tab @url{git://git.cypherpunks.ru/cronexpr.git}
+@item @code{github.com/hjson/hjson-go} @tab @url{git://git.cypherpunks.ru/hjson-go.git}
@item @code{golang.org/x/crypto} @tab @url{git://git.cypherpunks.ru/crypto.git}
@item @code{golang.org/x/net} @tab @url{git://git.cypherpunks.ru/net.git}
@item @code{golang.org/x/sys} @tab @url{git://git.cypherpunks.ru/sys.git}
@item @code{gopkg.in/check.v1} @tab @url{git://git.cypherpunks.ru/check.git}
-@item @code{gopkg.in/yaml.v2} @tab @url{git://git.cypherpunks.ru/yaml.git}
@end multitable
NNCP из коробки поддерживает ретрансляцию пакетов.
@verbatim
-neigh:
- bob:
+neigh: {
+ bob: {
[...]
- addrs:
- lan: [fe80::5400%igb0]:5400
+ addrs: {
+ lan: "[fe80::5400%igb0]:5400"
+ }
+ }
bob-airgap:
[...]
- via: [bob]
+ via: ["bob"]
+ }
+}
@end verbatim
Такой @ref{Configuration, конфигурационный файл} говорит что у нас есть
звонков} для @ref{nncp-caller} команды, используемой при online связи.
@verbatim
-neigh:
+neigh: {
[...]
- some-node:
+ some-node: {
[...]
- addrs:
+ addrs: {
lan: "[fe80::be5f:f4ff:fedd:2752%igb0]:5400"
wan: "some-node.com:5400"
- calls:
- -
+ }
+ calls: [
+ {
cron: "*/1 * * * *"
addr: lan
nice: MAX
onlinedeadline: 3600
- -
+ },
+ {
cron: "*/10 * * * *"
addr: wan
nice: PRIORITY
xx: rx
- -
+ },
+ {
cron: "*/1 0-7 * * *"
addr: wan
nice: BULK
onlinedeadline: 3600
maxonlinetime: 3600
+ },
+ ]
+ }
+}
@end verbatim
NNCP supports packets relying (transitioning) out-of-box.
@verbatim
-neigh:
- bob:
+neigh: {
+ bob: {
[...]
- addrs:
- lan: [fe80::5400%igb0]:5400
+ addrs: {
+ lan: "[fe80::5400%igb0]:5400"
+ }
+ }
bob-airgap:
[...]
- via: [bob]
+ via: ["bob"]
+ }
+}
@end verbatim
That @ref{Configuration, configuration file} tells that we have got two
communications.
@verbatim
-neigh:
+neigh: {
[...]
- some-node:
+ some-node: {
[...]
- addrs:
+ addrs: {
lan: "[fe80::be5f:f4ff:fedd:2752%igb0]:5400"
wan: "some-node.com:5400"
- calls:
- -
+ }
+ calls: [
+ {
cron: "*/1 * * * *"
addr: lan
nice: MAX
onlinedeadline: 3600
- -
+ },
+ {
cron: "*/10 * * * *"
addr: wan
nice: PRIORITY
xx: rx
- -
+ },
+ {
cron: "*/1 0-7 * * *"
addr: wan
nice: BULK
onlinedeadline: 3600
maxonlinetime: 3600
+ },
+ ]
+ }
+}
@end verbatim
git checkout v$release
rm -fr .git
-mod_name=go.cypherpunks.ru/nncp/v4
+mod_name=go.cypherpunks.ru/nncp/v5
mv src src.orig
mkdir -p src/$mod_name
mv src.orig/* src/$mod_name
github.com/dustin/go-humanize
github.com/flynn/noise
github.com/gorhill/cronexpr
+github.com/hjson/hjson-go
go.cypherpunks.ru/balloon
golang.org/x/crypto
golang.org/x/net
golang.org/x/sys
-gopkg.in/yaml.v2
"
for mod in $mods; do
mod_path=$(sed -n "s#^ \($mod\) \(.*\)\$#\1@\2#p" src/$mod_name/go.mod)
# $FreeBSD: head/net/nncp/Makefile 484628 2018-11-10 18:12:57Z bapt $
PORTNAME= nncp
-DISTVERSION= 4.0
+DISTVERSION= 5.0.0
PORTREVISION= 1
CATEGORIES= net
MASTER_SITES= http://www.nncpgo.org/download/
#
# nncp_caller_enable (bool): Set to NO by default.
# Set it to YES to enable nncp-caller.
-# nncp_caller_config (path): Set to %%PREFIX%%/etc/nncp.yaml by default.
+# nncp_caller_config (path): Set to %%PREFIX%%/etc/nncp.hjson by default.
. /etc/rc.subr
load_rc_config $name
: ${nncp_caller_enable:="NO"}
-: ${nncp_caller_config="%%PREFIX%%/etc/nncp.yaml"}
+: ${nncp_caller_config="%%PREFIX%%/etc/nncp.hjson"}
command=%%PREFIX%%/bin/nncp-caller
command_args="-quiet -cfg $nncp_caller_config &"
#
# nncp_daemon_enable (bool): Set to NO by default.
# Set it to YES to enable nncp-daemon.
-# nncp_daemon_config (path): Set to %%PREFIX%%/etc/nncp.yaml by default.
+# nncp_daemon_config (path): Set to %%PREFIX%%/etc/nncp.hjson by default.
# nncp_daemon_bind (string): Address:port to bind to
# Default is "[::]:5400".
load_rc_config $name
: ${nncp_daemon_enable:="NO"}
-: ${nncp_daemon_config="%%PREFIX%%/etc/nncp.yaml"}
+: ${nncp_daemon_config="%%PREFIX%%/etc/nncp.hjson"}
: ${nncp_daemon_bind="[::]:5400"}
command=%%PREFIX%%/bin/nncp-daemon
#
# nncp_toss_enable (bool): Set to NO by default.
# Set it to YES to enable nncp-toss.
-# nncp_toss_config (path): Set to %%PREFIX%%/etc/nncp.yaml by default.
+# nncp_toss_config (path): Set to %%PREFIX%%/etc/nncp.hjson by default.
# nncp_toss_cycle (int): Repeat tossing after that number of seconds.
# Default is "60".
load_rc_config $name
: ${nncp_toss_enable:="NO"}
-: ${nncp_toss_config="%%PREFIX%%/etc/nncp.yaml"}
+: ${nncp_toss_config="%%PREFIX%%/etc/nncp.hjson"}
: ${nncp_toss_cycle="60"}
command=%%PREFIX%%/bin/nncp-toss
[ "$2" = "POST-DEINSTALL" ] || exit 0
-if [ -e %%PREFIX%%/etc/nncp.yaml ]; then
- echo "%%PREFIX%%/etc/nncp.yaml with your private keys is not removed!"
+if [ -e %%PREFIX%%/etc/nncp.hjson ]; then
+ echo "%%PREFIX%%/etc/nncp.hjson with your private keys is not removed!"
fi
exec rmdir /var/spool/nncp
- Generate NNCP configuration file using the command:
# umask 077
- # nncp-cfgnew > %%PREFIX%%/etc/nncp.yaml
+ # nncp-cfgnew > %%PREFIX%%/etc/nncp.hjson
======================================================================
import (
"bytes"
+ "encoding/json"
"errors"
"log"
"os"
"path"
"github.com/gorhill/cronexpr"
+ "github.com/hjson/hjson-go"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/ssh/terminal"
- "gopkg.in/yaml.v2"
)
const (
)
var (
- DefaultCfgPath string = "/usr/local/etc/nncp.yaml"
+ DefaultCfgPath string = "/usr/local/etc/nncp.hjson"
DefaultSendmailPath string = "/usr/sbin/sendmail"
DefaultSpoolPath string = "/var/spool/nncp"
DefaultLogPath string = "/var/spool/nncp/log"
)
-type NodeYAML struct {
- Id string
- ExchPub string
- SignPub string
- NoisePub *string `yaml:"noisepub,omitempty"`
- Exec map[string][]string `yaml:"exec,omitempty"`
- Incoming *string `yaml:"incoming,omitempty"`
- Freq *string `yaml:"freq,omitempty"`
- FreqChunked *uint64 `yaml:"freqchunked,omitempty"`
- FreqMinSize *uint64 `yaml:"freqminsize,omitempty"`
- Via []string `yaml:"via,omitempty"`
- Calls []CallYAML `yaml:"calls,omitempty"`
-
- Addrs map[string]string `yaml:"addrs,omitempty"`
-
- RxRate *int `yaml:"rxrate,omitempty"`
- TxRate *int `yaml:"txrate,omitempty"`
- OnlineDeadline *uint `yaml:"onlinedeadline,omitempty"`
- MaxOnlineTime *uint `yaml:"maxonlinetime,omitempty"`
+type NodeJSON struct {
+ Id string `json:"id"`
+ ExchPub string `json:"exchpub"`
+ SignPub string `json:"signpub"`
+ NoisePub *string `json:"noisepub,omitempty"`
+ Exec map[string][]string `json:"exec,omitempty"`
+ Incoming *string `json:"incoming,omitempty"`
+ Freq *string `json:"freq,omitempty"`
+ FreqChunked *uint64 `json:"freqchunked,omitempty"`
+ FreqMinSize *uint64 `json:"freqminsize,omitempty"`
+ Via []string `json:"via,omitempty"`
+ Calls []CallJSON `json:"calls,omitempty"`
+
+ Addrs map[string]string `json:"addrs,omitempty"`
+
+ RxRate *int `json:"rxrate,omitempty"`
+ TxRate *int `json:"txrate,omitempty"`
+ OnlineDeadline *uint `json:"onlinedeadline,omitempty"`
+ MaxOnlineTime *uint `json:"maxonlinetime,omitempty"`
}
-type CallYAML struct {
+type CallJSON struct {
Cron string
- Nice *string `yaml:"nice,omitempty"`
- Xx string `yaml:"xx,omitempty"`
- RxRate *int `yaml:"rxrate,omitempty"`
- TxRate *int `yaml:"txrate,omitempty"`
- Addr *string `yaml:"addr,omitempty"`
- OnlineDeadline *uint `yaml:"onlinedeadline,omitempty"`
- MaxOnlineTime *uint `yaml:"maxonlinetime,omitempty"`
+ Nice *string `json:"nice,omitempty"`
+ Xx *string `json:"xx,omitempty"`
+ RxRate *int `json:"rxrate,omitempty"`
+ TxRate *int `json:"txrate,omitempty"`
+ Addr *string `json:"addr,omitempty"`
+ OnlineDeadline *uint `json:"onlinedeadline,omitempty"`
+ MaxOnlineTime *uint `json:"maxonlinetime,omitempty"`
}
-type NodeOurYAML struct {
- Id string
- ExchPub string
- ExchPrv string
- SignPub string
- SignPrv string
- NoisePrv string
- NoisePub string
+type NodeOurJSON struct {
+ Id string `json:"id"`
+ ExchPub string `json:"exchpub"`
+ ExchPrv string `json:"exchprv"`
+ SignPub string `json:"signpub"`
+ SignPrv string `json:"signprv"`
+ NoisePrv string `json:"noiseprv"`
+ NoisePub string `json:"noisepub"`
}
-type FromToYAML struct {
+type FromToJSON struct {
From string
To string
}
-type NotifyYAML struct {
- File *FromToYAML `yaml:"file,omitempty"`
- Freq *FromToYAML `yaml:"freq,omitempty"`
+type NotifyJSON struct {
+ File *FromToJSON `json:"file,omitempty"`
+ Freq *FromToJSON `json:"freq,omitempty"`
}
-type CfgYAML struct {
- Self *NodeOurYAML `yaml:"self,omitempty"`
- Neigh map[string]NodeYAML
+type CfgJSON struct {
+ Spool string `json:"spool"`
+ Log string `json:"log"`
+ Notify *NotifyJSON `json:"notify,omitempty"`
- Spool string
- Log string
- Notify *NotifyYAML `yaml:"notify,omitempty"`
+ Self *NodeOurJSON `json:"self"`
+ Neigh map[string]NodeJSON `json:"neigh"`
}
-func NewNode(name string, yml NodeYAML) (*Node, error) {
+func NewNode(name string, yml NodeJSON) (*Node, error) {
nodeId, err := NodeIdFromString(yml.Id)
if err != nil {
return nil, err
}
var xx TRxTx
- switch callYml.Xx {
- case "rx":
- xx = TRx
- case "tx":
- xx = TTx
- case "":
- default:
- return nil, errors.New("xx field must be either \"rx\" or \"tx\"")
+ if callYml.Xx != nil {
+ switch *callYml.Xx {
+ case "rx":
+ xx = TRx
+ case "tx":
+ xx = TTx
+ default:
+ return nil, errors.New("xx field must be either \"rx\" or \"tx\"")
+ }
}
rxRate := defRxRate
return &node, nil
}
-func NewNodeOur(yml *NodeOurYAML) (*NodeOur, error) {
+func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) {
id, err := NodeIdFromString(yml.Id)
if err != nil {
return nil, err
return &node, nil
}
-func (nodeOur *NodeOur) ToYAML() string {
- yml := NodeOurYAML{
- Id: nodeOur.Id.String(),
- ExchPub: ToBase32(nodeOur.ExchPub[:]),
- ExchPrv: ToBase32(nodeOur.ExchPrv[:]),
- SignPub: ToBase32(nodeOur.SignPub[:]),
- SignPrv: ToBase32(nodeOur.SignPrv[:]),
- NoisePub: ToBase32(nodeOur.NoisePub[:]),
- NoisePrv: ToBase32(nodeOur.NoisePrv[:]),
- }
- raw, err := yaml.Marshal(&yml)
- if err != nil {
- panic(err)
- }
- return string(raw)
-}
-
func CfgParse(data []byte) (*Ctx, error) {
var err error
if bytes.Compare(data[:8], MagicNNCPBv3[:]) == 0 {
return nil, err
}
}
- var cfgYAML CfgYAML
- if err = yaml.Unmarshal(data, &cfgYAML); err != nil {
+ var cfgGeneral map[string]interface{}
+ if err = hjson.Unmarshal(data, &cfgGeneral); err != nil {
+ return nil, err
+ }
+ marshaled, err := json.Marshal(cfgGeneral)
+ if err != nil {
+ return nil, err
+ }
+ var cfgJSON CfgJSON
+ if err = json.Unmarshal(marshaled, &cfgJSON); err != nil {
return nil, err
}
- if _, exists := cfgYAML.Neigh["self"]; !exists {
+ if _, exists := cfgJSON.Neigh["self"]; !exists {
return nil, errors.New("self neighbour missing")
}
var self *NodeOur
- if cfgYAML.Self != nil {
- self, err = NewNodeOur(cfgYAML.Self)
+ if cfgJSON.Self != nil {
+ self, err = NewNodeOur(cfgJSON.Self)
if err != nil {
return nil, err
}
}
- spoolPath := path.Clean(cfgYAML.Spool)
+ spoolPath := path.Clean(cfgJSON.Spool)
if !path.IsAbs(spoolPath) {
return nil, errors.New("Spool path must be absolute")
}
- logPath := path.Clean(cfgYAML.Log)
+ logPath := path.Clean(cfgJSON.Log)
if !path.IsAbs(logPath) {
return nil, errors.New("Log path must be absolute")
}
Spool: spoolPath,
LogPath: logPath,
Self: self,
- Neigh: make(map[NodeId]*Node, len(cfgYAML.Neigh)),
+ Neigh: make(map[NodeId]*Node, len(cfgJSON.Neigh)),
Alias: make(map[string]*NodeId),
}
- if cfgYAML.Notify != nil {
- if cfgYAML.Notify.File != nil {
- ctx.NotifyFile = cfgYAML.Notify.File
+ if cfgJSON.Notify != nil {
+ if cfgJSON.Notify.File != nil {
+ ctx.NotifyFile = cfgJSON.Notify.File
}
- if cfgYAML.Notify.Freq != nil {
- ctx.NotifyFreq = cfgYAML.Notify.Freq
+ if cfgJSON.Notify.Freq != nil {
+ ctx.NotifyFreq = cfgJSON.Notify.Freq
}
}
vias := make(map[NodeId][]string)
- for name, neighYAML := range cfgYAML.Neigh {
- neigh, err := NewNode(name, neighYAML)
+ for name, neighJSON := range cfgJSON.Neigh {
+ neigh, err := NewNode(name, neighJSON)
if err != nil {
return nil, err
}
return nil, errors.New("Node names conflict")
}
ctx.Alias[name] = neigh.Id
- vias[*neigh.Id] = neighYAML.Via
+ vias[*neigh.Id] = neighJSON.Via
}
ctx.SelfId = ctx.Alias["self"]
for neighId, viasRaw := range vias {
"strings"
"github.com/davecgh/go-xdr/xdr2"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
"golang.org/x/crypto/blake2b"
)
"os"
"strings"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"sync"
"time"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"os"
"github.com/davecgh/go-xdr/xdr2"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/ssh/terminal"
)
func usage() {
fmt.Fprintf(os.Stderr, nncp.UsageHeader())
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])
+ fmt.Fprintf(os.Stderr, "Usage: %s [options] cfg.hjson > cfg.hjson.eblob\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, " %s [options] -d cfg.hjson.eblob > cfg.hjson\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, " %s [options] -dump cfg.hjson.eblob\n", os.Args[0])
fmt.Fprintln(os.Stderr, "Options:")
flag.PrintDefaults()
}
"log"
"os"
- "go.cypherpunks.ru/nncp/v4"
- "gopkg.in/yaml.v2"
+ "github.com/hjson/hjson-go"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
log.Fatalln("Error during initialization:", err)
}
- cfg := nncp.CfgYAML{
+ cfg := nncp.CfgJSON{
Spool: ctx.Spool,
Log: ctx.LogPath,
- Neigh: make(map[string]nncp.NodeYAML),
+ Neigh: make(map[string]nncp.NodeJSON),
}
for _, node := range ctx.Neigh {
var noisePub *string
np := nncp.ToBase32(node.NoisePub[:])
noisePub = &np
}
- cfg.Neigh[node.Name] = nncp.NodeYAML{
+ cfg.Neigh[node.Name] = nncp.NodeJSON{
Id: node.Id.String(),
ExchPub: nncp.ToBase32(node.ExchPub[:]),
SignPub: nncp.ToBase32(node.SignPub[:]),
NoisePub: noisePub,
}
}
- raw, err := yaml.Marshal(&cfg)
+ raw, err := hjson.Marshal(&cfg)
if err != nil {
panic(err)
}
"fmt"
"os"
- "go.cypherpunks.ru/nncp/v4"
- "gopkg.in/yaml.v2"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
func main() {
var (
- version = flag.Bool("version", false, "Print version information")
- warranty = flag.Bool("warranty", false, "Print warranty information")
+ noComments = flag.Bool("nocomments", false, "Do not include descriptive comments")
+ version = flag.Bool("version", false, "Print version information")
+ warranty = flag.Bool("warranty", false, "Print warranty information")
)
flag.Usage = usage
flag.Parse()
if err != nil {
panic(err)
}
- noisePub := nncp.ToBase32(nodeOur.NoisePub[:])
- cfg := nncp.CfgYAML{
- Self: &nncp.NodeOurYAML{
- Id: nodeOur.Id.String(),
- ExchPub: nncp.ToBase32(nodeOur.ExchPub[:]),
- ExchPrv: nncp.ToBase32(nodeOur.ExchPrv[:]),
- SignPub: nncp.ToBase32(nodeOur.SignPub[:]),
- SignPrv: nncp.ToBase32(nodeOur.SignPrv[:]),
- NoisePub: nncp.ToBase32(nodeOur.NoisePub[:]),
- NoisePrv: nncp.ToBase32(nodeOur.NoisePrv[:]),
- },
- Neigh: map[string]nncp.NodeYAML{
- "self": nncp.NodeYAML{
- Id: nodeOur.Id.String(),
- ExchPub: nncp.ToBase32(nodeOur.ExchPub[:]),
- SignPub: nncp.ToBase32(nodeOur.SignPub[:]),
- NoisePub: &noisePub,
- Exec: map[string][]string{
- "sendmail": []string{nncp.DefaultSendmailPath},
- },
- },
- },
- Spool: nncp.DefaultSpoolPath,
- Log: nncp.DefaultLogPath,
+ var cfgRaw string
+ if *noComments {
+ cfgRaw = fmt.Sprintf(`{
+ spool: %s
+ log: %s
+
+ self: {
+ # DO NOT show anyone your private keys!!!
+ id: %s
+ exchpub: %s
+ exchprv: %s
+ signpub: %s
+ signprv: %s
+ noiseprv: %s
+ noisepub: %s
+ }
+ neigh: {
+ self: {
+ id: %s
+ exchpub: %s
+ signpub: %s
+ noisepub: %s
+ exec: {sendmail: ["%s"]}
+ }
+ }
+}`,
+ nncp.DefaultSpoolPath,
+ nncp.DefaultLogPath,
+ nodeOur.Id.String(),
+ nncp.ToBase32(nodeOur.ExchPub[:]),
+ nncp.ToBase32(nodeOur.ExchPrv[:]),
+ nncp.ToBase32(nodeOur.SignPub[:]),
+ nncp.ToBase32(nodeOur.SignPrv[:]),
+ nncp.ToBase32(nodeOur.NoisePub[:]),
+ nncp.ToBase32(nodeOur.NoisePrv[:]),
+ nodeOur.Id.String(),
+ nncp.ToBase32(nodeOur.ExchPub[:]),
+ nncp.ToBase32(nodeOur.SignPub[:]),
+ nncp.ToBase32(nodeOur.NoisePub[:]),
+ nncp.DefaultSendmailPath,
+ )
+ } else {
+ cfgRaw = fmt.Sprintf(`{
+ # Path to encrypted packets spool directory
+ spool: %s
+ # Path to log file
+ log: %s
+
+ # Enable notification email sending
+ # notify: {
+ # file: {
+ # from: nncp@localhost
+ # to: user+file@example.com
+ # }
+ # freq: {
+ # from: nncp@localhost
+ # to: user+freq@example.com
+ # }
+ # }
+
+ self: {
+ # DO NOT show anyone your private keys!!!
+ id: %s
+ exchpub: %s
+ exchprv: %s
+ signpub: %s
+ signprv: %s
+ noiseprv: %s
+ noisepub: %s
+ }
+ neigh: {
+ self: {
+ # You should give public keys below to your neighbours
+ id: %s
+ exchpub: %s
+ signpub: %s
+ noisepub: %s
+
+ exec: {
+ # Default self's sendmail command is used for email notifications sending
+ sendmail: ["%s"]
+ }
+ }
+
+ # Example neighbour, most of fields are optional
+ # alice: {
+ # id: XJZBK...65IJQ
+ # exchpub: MJACJ...FAI6A
+ # signpub: T4AFC...N2FRQ
+ # noisepub: UBM5K...VI42A
+ #
+ # # He is allowed to send email
+ # exec: {sendmail: ["/usr/sbin/sendmail"]}
+ #
+ # # Allow incoming files saving in that directory
+ # incoming: "/home/alice/incoming"
+ #
+ # # Transitional nodes path
+ # via: ["bob", "eve"]
+ #
+ # # Inactivity timeout when session with remote peer should be terminated
+ # onlinedeadline: 1800
+ #
+ # # Maximal online session lifetime
+ # maxonlinetime: 3600
+ #
+ # # Allow freqing from that directory
+ # freq: "/home/bob/pub"
+ # # Send freqed files with chunks
+ # freqchunked: 1024
+ # # Send freqed files with minumal chunk size
+ # freqminsize: 2048
+ #
+ # # Set maximal packets per second receive and transmit rates
+ # rxrate: 10
+ # txrate: 20
+ #
+ # # Address aliases
+ # addrs: {
+ # lan: "[fe80::1234%%igb0]:5400"
+ # internet: alice.com:3389
+ # }
+ #
+ # # Calls configuration
+ # calls: [
+ # {
+ # cron: "*/2 * * * *"
+ # onlinedeadline: 1800
+ # maxonlinetime: 1750
+ # nice: PRIORITY+10
+ # rxrate: 10
+ # txrate: 20
+ # xx: rx
+ # addr: lan
+ # },
+ # ]
+ # }
+ }
+}`,
+ nncp.DefaultSpoolPath,
+ nncp.DefaultLogPath,
+ nodeOur.Id.String(),
+ nncp.ToBase32(nodeOur.ExchPub[:]),
+ nncp.ToBase32(nodeOur.ExchPrv[:]),
+ nncp.ToBase32(nodeOur.SignPub[:]),
+ nncp.ToBase32(nodeOur.SignPrv[:]),
+ nncp.ToBase32(nodeOur.NoisePub[:]),
+ nncp.ToBase32(nodeOur.NoisePrv[:]),
+ nodeOur.Id.String(),
+ nncp.ToBase32(nodeOur.ExchPub[:]),
+ nncp.ToBase32(nodeOur.SignPub[:]),
+ nncp.ToBase32(nodeOur.NoisePub[:]),
+ nncp.DefaultSendmailPath,
+ )
}
- raw, err := yaml.Marshal(&cfg)
- if err != nil {
+ if _, err = nncp.CfgParse([]byte(cfgRaw)); err != nil {
panic(err)
}
- fmt.Print(string(raw))
+ fmt.Println(cfgRaw)
}
"log"
"os"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"strconv"
"time"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
"golang.org/x/net/netutil"
)
"log"
"os"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"os"
"strings"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"strconv"
"strings"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"log"
"os"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"os"
"github.com/davecgh/go-xdr/xdr2"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"github.com/davecgh/go-xdr/xdr2"
"github.com/dustin/go-humanize"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
"golang.org/x/crypto/blake2b"
)
"path/filepath"
"strings"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"sort"
"github.com/dustin/go-humanize"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"os"
"time"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
"strconv"
"github.com/davecgh/go-xdr/xdr2"
- "go.cypherpunks.ru/nncp/v4"
+ "go.cypherpunks.ru/nncp/v5"
)
func usage() {
LogPath string
Quiet bool
Debug bool
- NotifyFile *FromToYAML
- NotifyFreq *FromToYAML
+ NotifyFile *FromToJSON
+ NotifyFreq *FromToJSON
}
func (ctx *Ctx) FindNode(id string) (*Node, error) {
-module go.cypherpunks.ru/nncp/v4
+module go.cypherpunks.ru/nncp/v5
require (
github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892
github.com/dustin/go-humanize v1.0.0
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
+ github.com/hjson/hjson-go v3.0.1+incompatible
github.com/kr/pretty v0.1.0 // indirect
go.cypherpunks.ru/balloon v1.1.0
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc
golang.org/x/net v0.0.0-20191007182048-72f939374954
golang.org/x/sys v0.0.0-20191008105621-543471e840be
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
- gopkg.in/yaml.v2 v2.2.4
)
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY=
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
+github.com/hjson/hjson-go v3.0.1+incompatible h1:JwOXblcMiBbiWue7iPkoFK9oXSnW8n+qXh/0Fio6TCo=
+github.com/hjson/hjson-go v3.0.1+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
SeenSuffix = ".seen"
)
-func newNotification(fromTo *FromToYAML, subject string) io.Reader {
+func newNotification(fromTo *FromToJSON, subject string) io.Reader {
return strings.NewReader(fmt.Sprintf(
"From: %s\nTo: %s\nSubject: %s\n",
fromTo.From,