VERSION | 2 +-
doc/Makefile | 2 +-
doc/cmds.texi | 6 ++++--
doc/download.texi | 4 ++++
doc/index.texi | 2 +-
doc/install.texi | 4 +++-
doc/news.ru.texi | 32 ++++++++++++++++++++++++++++++++
doc/news.texi | 30 ++++++++++++++++++++++++++++++
doc/sp.texi | 22 +++++++++++++++++++---
doc/sp.txt | 4 ++--
doc/spool.texi | 1 +
doc/thanks.texi | 3 +++
makedist.sh | 19 ++++---------------
ports/nncp/Makefile | 2 +-
src/call.go | 9 +++++----
src/cfg.go | 103 +++++++++++++++++++++++++++--------------------------
src/check.go | 4 ++--
src/chunked.go | 2 +-
src/cmd/nncp-bundle/main.go | 14 +++++++-------
src/cmd/nncp-call/main.go | 21 ++++++++++++---------
src/cmd/nncp-caller/main.go | 2 +-
src/cmd/nncp-cfgenc/main.go | 2 +-
src/cmd/nncp-cfgmin/main.go | 2 +-
src/cmd/nncp-cfgnew/main.go | 2 +-
src/cmd/nncp-check/main.go | 2 +-
src/cmd/nncp-daemon/main.go | 9 +++++++--
src/cmd/nncp-exec/main.go | 2 +-
src/cmd/nncp-file/main.go | 2 +-
src/cmd/nncp-freq/main.go | 2 +-
src/cmd/nncp-log/main.go | 2 +-
src/cmd/nncp-pkt/main.go | 2 +-
src/cmd/nncp-reass/main.go | 26 +++++++++++++++++---------
src/cmd/nncp-rm/main.go | 2 +-
src/cmd/nncp-stat/main.go | 2 +-
src/cmd/nncp-toss/main.go | 2 +-
src/cmd/nncp-xfer/main.go | 19 +++++++++++--------
src/ctx.go | 2 +-
src/eblob.go | 2 +-
src/go.mod | 8 ++++----
src/go.sum | 16 ++++++++--------
src/humanizer.go | 2 +-
src/jobs.go | 2 +-
src/lockdir.go | 6 +++---
src/log.go | 2 +-
src/nncp.go | 4 ++--
src/node.go | 7 ++++---
src/pipe.go | 2 +-
src/pkt.go | 2 +-
src/pkt_test.go | 2 +-
src/progress.go | 14 ++++++--------
src/sp.go | 293 ++++++++++++++++++++++++++++++++++++-----------------
src/tmp.go | 2 +-
src/toss.go | 11 ++++++++---
src/toss_test.go | 2 +-
src/tx.go | 16 ++++++++--------
src/tx_test.go | 2 +-
src/via.go | 2 +-
diff --git a/VERSION b/VERSION
index 37b0dd9aefbd4bc9b14859d81973f63606c1e800414d38fbe125b6fdfd4810b4..4f0e110e627bf92713cf3397658948b8ae56fa8763ad1cb2876eba9f03fee74c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5.2.1
+5.3.0
diff --git a/doc/Makefile b/doc/Makefile
index 25c71cb07155bf1a5b1d3b2a4805c312f2800649ce2cf3d00666b2adda876eeb..a224bc4a3c5d2689942046ee0d5bbe797168fed8856caa42856f737c53842b96 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -13,7 +13,7 @@
nncp.html: *.texi sp.utxt pedro.txt
rm -f nncp.html/*.html
$(MAKEINFO) --html \
- --set-customization-variable EXTRA_HEAD='' \
+ --set-customization-variable EXTRA_HEAD='' \
--set-customization-variable CSS_LINES='$(CSS)' \
--set-customization-variable SHOW_TITLE=0 \
--set-customization-variable USE_ACCESSKEY=0 \
diff --git a/doc/cmds.texi b/doc/cmds.texi
index d3dd19ef332c8a846570512615064f0f8ceff3bcdb81ef40db8acd62ec8cb442..654f4669b2c1216a1f3346285dfc5fdc02c9ac4b5376bea83f8f52750ac31682 100644
--- a/doc/cmds.texi
+++ b/doc/cmds.texi
@@ -250,10 +250,12 @@ can handle. @option{-bind} option specifies @option{addr:port} it must
bind to and listen.
It could be run as @command{inetd} service, by specifying
-@option{-inetd} option. Example inetd-entry:
+@option{-inetd} option. Pay attention that because it uses stdin/stdout,
+it can not effectively work with IO timeouts and connection closing can
+propagate up to 5 minutes in practice. Example inetd-entry:
@verbatim
-uucp stream tcp6 nowait nncpuser /usr/local/bin/nncp-daemon nncp-daemon -inetd
+uucp stream tcp6 nowait nncpuser /usr/local/bin/nncp-daemon nncp-daemon -quiet -inetd
@end verbatim
@node nncp-exec
diff --git a/doc/download.texi b/doc/download.texi
index 3d5011dec492175d775a10a4c95b6b40000ccb49df8dbcaa13f9e0f207b39d2c..0530f10d0c2d0468e5f76d3ef88ec67435e1db8551c79d1465c12fc56102bcd3 100644
--- a/doc/download.texi
+++ b/doc/download.texi
@@ -24,6 +24,10 @@
@multitable {XXXXX} {XXXX-XX-XX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
@headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum
+@item @ref{Release 5.2.1, 5.2.1} @tab 2019-12-15 @tab 1109 KiB
+@tab @url{download/nncp-5.2.1.tar.xz, link} @url{download/nncp-5.2.1.tar.xz.sig, sign}
+@tab @code{983D1A8A 4398C281 76356AE1 C5541124 B0755555 D115063B D1388F85 9C4A6B3E}
+
@item @ref{Release 5.2.0, 5.2.0} @tab 2019-12-14 @tab 1109 KiB
@tab @url{download/nncp-5.2.0.tar.xz, link} @url{download/nncp-5.2.0.tar.xz.sig, sign}
@tab @code{FFC55467 8B4ECCA6 92D90F42 ACC0286D 209E054E EA1CBF87 0307003E CF219610}
diff --git a/doc/index.texi b/doc/index.texi
index 32ce8a71a230eaf4fce048c86449335e2fb34019c859c8c016b09c41f23c5905..f1a647118ca69498f9d308bce8fab72288f5c94cd0654d92084aad68a3bdf54a 100644
--- a/doc/index.texi
+++ b/doc/index.texi
@@ -6,7 +6,7 @@ @copying
This manual is for NNCP (Node to Node copy) -- collection of utilities
simplifying secure store-and-forward files and mail exchanging.
-Copyright @copyright{} 2016-2019 @email{stargrave@@stargrave.org, Sergey Matveev}
+Copyright @copyright{} 2016-2020 @email{stargrave@@stargrave.org, Sergey Matveev}
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/install.texi b/doc/install.texi
index 1e6affb9dee608c89602b2c2578cf803dc02c0f57b51597aa4d07fa11a7bbc8a..6f261ac21d3ab5a7edc8680d45f8dae928a80732f4cd181062de6d83bba316ab 100644
--- a/doc/install.texi
+++ b/doc/install.texi
@@ -1,7 +1,7 @@
@node Installation
@unnumbered Installation
-@set VERSION 5.2.1
+@set VERSION 5.3.0
Possibly NNCP package already exists for your distribution:
@@ -9,6 +9,8 @@ @itemize
@item @url{https://www.freshports.org/net/nncp/, FreeBSD ports}
@item @url{https://github.com/DragonFlyBSD/DPorts/tree/master/net/nncp, DragonFly BSD ports}
@item @url{https://github.com/void-linux/void-packages/blob/master/srcpkgs/nncp/template, Void Linux}
+@item @url{https://qa.debian.org/developer.php?login=jgoerzen@@complete.org, Debian packages} (pending inclusion, maintainer's page)
+@item @url{https://github.com/NixOS/nixpkgs/pull/75772, NixOS packages} (pending inclusion, maintainer's page)
@end itemize
NNCP should run on any POSIX-compatible operating system.
diff --git a/doc/news.ru.texi b/doc/news.ru.texi
index e1f016bdbdd2526fcbcdc4873503dd0904721904639adfd07856f6bb13d49ae3..0af291b4c3ee23d313f0ea4872ad392ce622f55b0bcc3940debc061a11555020 100644
--- a/doc/news.ru.texi
+++ b/doc/news.ru.texi
@@ -1,6 +1,38 @@
@node Новости
@section Новости
+@node Релиз 5.3.0
+@subsection Релиз 5.3.0
+@itemize
+
+@item
+Сообщения прогресса содержат префикс, поясняющий выполняемое действие.
+
+@item
+Исправлено не происходящее дополнение (padding) handshake сообщений.
+
+@item
+Завершать все порождаемые в SP протоколе горутины, меньше утечек памяти.
+
+@item
+SP протокол порождает меньше вызовов записей (соответственно, и TCP
+пакетов) в сокет.
+
+@item
+Проверять @option{onlinedeadline} и @option{maxonlinetime} ежесекундно,
+независимо от чтения из сокета (раз в 10 секунд в худшем случае).
+
+@item
+Раз в минуту, если нет более никакого другого трафика, посылаются PING
+пакеты в SP-соединении. Это позволит быстрее понимать что соединение
+более не работоспособно.
+
+@item
+@command{nncp-toss} использует lock-file для предотвращения
+одновременной обработки зашифрованных пакетов.
+
+@end itemize
+
@node Релиз 5.2.1
@subsection Релиз 5.2.1
@itemize
diff --git a/doc/news.texi b/doc/news.texi
index 268e21054811a38f0d1cb177cfc50c6dfb88d3557b347febeacd6d5874cd9912..842099d7f5f2bb032bef1c1835ac995a551e45f6ef6b42e96b90fe1239861cc5 100644
--- a/doc/news.texi
+++ b/doc/news.texi
@@ -3,6 +3,36 @@ @unnumbered News
See also this page @ref{Новости, on russian}.
+@node Release 5.3.0
+@section Release 5.3.0
+@itemize
+
+@item
+Progress messages contain prefix, describing the running action.
+
+@item
+Fixed not occurring handshake messages padding.
+
+@item
+Finish all SP protocol related goroutines, less memory leak.
+
+@item
+SP protocol generates less socket write calls, thus generating less TCP
+packets.
+
+@item
+Check @option{onlinedeadline} and @option{maxonlinetime} options every
+second, independently from socket reads (up to 10 seconds).
+
+@item
+Once per minute, if no other traffic exists, PING packets are sent in
+SP-connection. That allows faster determining of connection unworkability.
+
+@item
+@command{nncp-toss} uses lock-file to prevent simultaneous tossing.
+
+@end itemize
+
@node Release 5.2.1
@section Release 5.2.1
@itemize
diff --git a/doc/sp.texi b/doc/sp.texi
index 7c99c4c96dd9d1f749c017e88d4be6ea6192bdf4dccfe0c06c0280c7c778f641..b3a6ad33028f34e89318383d152b09ff58d3f1664dd6663bcc88aac78ab2e7aa 100644
--- a/doc/sp.texi
+++ b/doc/sp.texi
@@ -61,6 +61,15 @@ | HALT |
+------+
@end verbatim
+@item PING
+ Dummy packet only used for determining workability of the connection.
+
+@verbatim
++------+
+| PING |
++------+
+@end verbatim
+
@item INFO
Information about the file we have for transmission.
@@ -195,13 +204,20 @@ then run background integrity checker on it. If check succeeds, then
delete @file{.part} suffix from file's name and send @emph{DONE} packet.
@item When @emph{DONE} packet received, delete corresponding file.
+
@item When @emph{HALT} packet received, empty file sending queue.
@item Each second, node checks: are there any new @emph{tx} packets
appeared and queues corresponding @emph{INFO} packets.
-@item If no packets are sent and received during @ref{CfgOnlineDeadline,
-onlinedeadline} duration, then close the connection. There is no
-explicit indication that session is over.
+@item Each minute, if no packets were sent, node sends @emph{PING}
+packet.
+
+@item If no non-PING packets are sent and received during
+@ref{CfgOnlineDeadline, onlinedeadline} duration, then close the
+connection. There is no explicit indication that session is over.
+
+@item If no packets are received during two minutes (two PING timeouts),
+then close the connection.
@end enumerate
diff --git a/doc/sp.txt b/doc/sp.txt
index 32c23dd06098ae1291028bb2a836320c5d37c81d209481504930105730efcf1a..4c898e8bce7fceb300ccfa6f0a297c99af42076556be3f6db0709b55928668cc 100644
--- a/doc/sp.txt
+++ b/doc/sp.txt
@@ -13,7 +13,7 @@ Initiator -> Responder : [e, es, s, ss], INFO..., HALT...
Initiator <- Responder : [e, ee, se], INFO..., HALT...
Initiator -> Responder : INFO..., FREQ..., DONE...
Initiator <- Responder : INFO..., FREQ..., DONE...
-Initiator -> Responder : FILE..., INFO..., DONE...
-Initiator <- Responder : FILE..., INFO..., DONE...
+Initiator -> Responder : FILE..., INFO..., DONE..., PING
+Initiator <- Responder : FILE..., INFO..., DONE..., PING
@enduml
diff --git a/doc/spool.texi b/doc/spool.texi
index 03951b8e46b62c6fc5898a59791260faa14aeb4819f7640e7d4420ce23fa173d..478c4f071f8cccd67472e94616e88d4829b5bde637cc51bd6bbc73fe6679c45f 100644
--- a/doc/spool.texi
+++ b/doc/spool.texi
@@ -10,6 +10,7 @@ spool/tmp/
spool/2WHB...OABQ/rx.lock
spool/2WHB...OABQ/rx/5ZIB...UMKW.part
spool/2WHB...OABQ/tx.lock
+spool/2WHB...OABQ/toss.lock
spool/BYRR...CG6Q/rx.lock
spool/BYRR...CG6Q/rx/
spool/BYRR...CG6Q/tx.lock
diff --git a/doc/thanks.texi b/doc/thanks.texi
index 97df6ebdde19b707fcded898e423b7f6bb04fa042386495527204e262575ce78..fb4806484e7af0676029ea45e7044ba8a67516b1875ffc9ef73743342550a94c 100644
--- a/doc/thanks.texi
+++ b/doc/thanks.texi
@@ -4,8 +4,11 @@
There are people deserving to be thanked for helping this project:
@itemize
+
@item Shawn K. Quinn for his descriptive instructions about building
NNCP under Ubuntu GNU/Linux distributions and bug reports.
+
@item @url{mailto:jgoerzen@@complete.org, John Goerzen} for his feature
suggestions and Debian package maintenance.
+
@end itemize
diff --git a/makedist.sh b/makedist.sh
index 52004652c0156038657ed22783778843c065da29e87cf5d30b32ed521c495ee7..a8dc6d0a1147a0d6abfe5a6b77c02f3f98ef0b4ec50bb5e197f8db909831c7be 100755
--- a/makedist.sh
+++ b/makedist.sh
@@ -108,23 +108,23 @@ You can obtain releases source code prepared tarballs on
@url{http://www.nncpgo.org/}.
EOF
perl -i -ne 'print unless /include pedro/' doc/index.texi doc/about.ru.texi
+perl -p -i -e 's/^(.verbatiminclude) .*$/$1 PUBKEY.asc/g' doc/integrity.texi
+mv doc/.well-known/openpgpkey/hu/i4cdqgcarfjdjnba6y4jnf498asg8c6p.asc PUBKEY.asc
+ln -s ../PUBKEY.asc doc
make -C doc
########################################################################
# Supplementary files autogeneration
########################################################################
-texi=`mktemp`
+texi=$(TMPDIR=doc mktemp)
cat > $texi < $texi < $texi < $texi <
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@ package nncp
import (
"net"
+ "time"
"github.com/gorhill/cronexpr"
)
@@ -30,8 +31,8 @@ Xx TRxTx
RxRate int
TxRate int
Addr *string
- OnlineDeadline uint
- MaxOnlineTime uint
+ OnlineDeadline time.Duration
+ MaxOnlineTime time.Duration
}
func (ctx *Ctx) CallNode(
@@ -40,7 +41,7 @@ addrs []string,
nice uint8,
xxOnly TRxTx,
rxRate, txRate int,
- onlineDeadline, maxOnlineTime uint,
+ onlineDeadline, maxOnlineTime time.Duration,
listOnly bool,
onlyPkts map[[32]byte]bool,
) (isGood bool) {
diff --git a/src/cfg.go b/src/cfg.go
index 51d47e413fb191cded95bbe14cd607fcedf3f208dddc37d5598a150d992f6e89..a95c7b2b8aa0b0a4ed9827baeaddf1301efdf5def0389674127e8a5a6a9406a8 100644
--- a/src/cfg.go
+++ b/src/cfg.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ "log"
"os"
"path"
"strconv"
+ "time"
"github.com/gorhill/cronexpr"
"github.com/hjson/hjson-go"
@@ -116,13 +117,13 @@ Self *NodeOurJSON `json:"self"`
Neigh map[string]NodeJSON `json:"neigh"`
}
-func NewNode(name string, yml NodeJSON) (*Node, error) {
- nodeId, err := NodeIdFromString(yml.Id)
+func NewNode(name string, cfg NodeJSON) (*Node, error) {
+ nodeId, err := NodeIdFromString(cfg.Id)
if err != nil {
return nil, err
}
- exchPub, err := FromBase32(yml.ExchPub)
+ exchPub, err := FromBase32(cfg.ExchPub)
if err != nil {
return nil, err
}
@@ -130,7 +131,7 @@ if len(exchPub) != 32 {
return nil, errors.New("Invalid exchPub size")
}
- signPub, err := FromBase32(yml.SignPub)
+ signPub, err := FromBase32(cfg.SignPub)
if err != nil {
return nil, err
}
@@ -139,8 +140,8 @@ return nil, errors.New("Invalid signPub size")
}
var noisePub []byte
- if yml.NoisePub != nil {
- noisePub, err = FromBase32(*yml.NoisePub)
+ if cfg.NoisePub != nil {
+ noisePub, err = FromBase32(*cfg.NoisePub)
if err != nil {
return nil, err
}
@@ -150,8 +151,8 @@ }
}
var incoming *string
- if yml.Incoming != nil {
- inc := path.Clean(*yml.Incoming)
+ if cfg.Incoming != nil {
+ inc := path.Clean(*cfg.Incoming)
if !path.IsAbs(inc) {
return nil, errors.New("Incoming path must be absolute")
}
@@ -162,8 +163,8 @@ var freqPath *string
freqChunked := int64(MaxFileSize)
var freqMinSize int64
freqMaxSize := int64(MaxFileSize)
- if yml.Freq != nil {
- f := yml.Freq
+ if cfg.Freq != nil {
+ f := cfg.Freq
if f.Path != nil {
fPath := path.Clean(*f.Path)
if !path.IsAbs(fPath) {
@@ -186,44 +187,44 @@ }
}
defRxRate := 0
- if yml.RxRate != nil && *yml.RxRate > 0 {
- defRxRate = *yml.RxRate
+ if cfg.RxRate != nil && *cfg.RxRate > 0 {
+ defRxRate = *cfg.RxRate
}
defTxRate := 0
- if yml.TxRate != nil && *yml.TxRate > 0 {
- defTxRate = *yml.TxRate
+ if cfg.TxRate != nil && *cfg.TxRate > 0 {
+ defTxRate = *cfg.TxRate
}
- defOnlineDeadline := uint(DefaultDeadline)
- if yml.OnlineDeadline != nil {
- if *yml.OnlineDeadline <= 0 {
+ defOnlineDeadline := DefaultDeadline
+ if cfg.OnlineDeadline != nil {
+ if *cfg.OnlineDeadline <= 0 {
return nil, errors.New("OnlineDeadline must be at least 1 second")
}
- defOnlineDeadline = *yml.OnlineDeadline
+ defOnlineDeadline = time.Duration(*cfg.OnlineDeadline) * time.Second
}
- var defMaxOnlineTime uint
- if yml.MaxOnlineTime != nil {
- defMaxOnlineTime = *yml.MaxOnlineTime
+ var defMaxOnlineTime time.Duration
+ if cfg.MaxOnlineTime != nil {
+ defMaxOnlineTime = time.Duration(*cfg.MaxOnlineTime) * time.Second
}
var calls []*Call
- for _, callYml := range yml.Calls {
- expr, err := cronexpr.Parse(callYml.Cron)
+ for _, callCfg := range cfg.Calls {
+ expr, err := cronexpr.Parse(callCfg.Cron)
if err != nil {
return nil, err
}
nice := uint8(255)
- if callYml.Nice != nil {
- nice, err = NicenessParse(*callYml.Nice)
+ if callCfg.Nice != nil {
+ nice, err = NicenessParse(*callCfg.Nice)
if err != nil {
return nil, err
}
}
var xx TRxTx
- if callYml.Xx != nil {
- switch *callYml.Xx {
+ if callCfg.Xx != nil {
+ switch *callCfg.Xx {
case "rx":
xx = TRx
case "tx":
@@ -234,34 +235,34 @@ }
}
rxRate := defRxRate
- if callYml.RxRate != nil {
- rxRate = *callYml.RxRate
+ if callCfg.RxRate != nil {
+ rxRate = *callCfg.RxRate
}
txRate := defTxRate
- if callYml.TxRate != nil {
- txRate = *callYml.TxRate
+ if callCfg.TxRate != nil {
+ txRate = *callCfg.TxRate
}
var addr *string
- if callYml.Addr != nil {
- if a, exists := yml.Addrs[*callYml.Addr]; exists {
+ if callCfg.Addr != nil {
+ if a, exists := cfg.Addrs[*callCfg.Addr]; exists {
addr = &a
} else {
- addr = callYml.Addr
+ addr = callCfg.Addr
}
}
onlineDeadline := defOnlineDeadline
- if callYml.OnlineDeadline != nil {
- if *callYml.OnlineDeadline == 0 {
+ if callCfg.OnlineDeadline != nil {
+ if *callCfg.OnlineDeadline == 0 {
return nil, errors.New("OnlineDeadline must be at least 1 second")
}
- onlineDeadline = *callYml.OnlineDeadline
+ onlineDeadline = time.Duration(*callCfg.OnlineDeadline) * time.Second
}
- var maxOnlineTime uint
- if callYml.MaxOnlineTime != nil {
- maxOnlineTime = *callYml.MaxOnlineTime
+ var maxOnlineTime time.Duration
+ if callCfg.MaxOnlineTime != nil {
+ maxOnlineTime = time.Duration(*callCfg.MaxOnlineTime) * time.Second
}
calls = append(calls, &Call{
@@ -281,14 +282,14 @@ Name: name,
Id: nodeId,
ExchPub: new([32]byte),
SignPub: ed25519.PublicKey(signPub),
- Exec: yml.Exec,
+ Exec: cfg.Exec,
Incoming: incoming,
FreqPath: freqPath,
FreqChunked: freqChunked,
FreqMinSize: freqMinSize,
FreqMaxSize: freqMaxSize,
Calls: calls,
- Addrs: yml.Addrs,
+ Addrs: cfg.Addrs,
RxRate: defRxRate,
TxRate: defTxRate,
OnlineDeadline: defOnlineDeadline,
@@ -302,13 +303,13 @@ }
return &node, nil
}
-func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) {
- id, err := NodeIdFromString(yml.Id)
+func NewNodeOur(cfg *NodeOurJSON) (*NodeOur, error) {
+ id, err := NodeIdFromString(cfg.Id)
if err != nil {
return nil, err
}
- exchPub, err := FromBase32(yml.ExchPub)
+ exchPub, err := FromBase32(cfg.ExchPub)
if err != nil {
return nil, err
}
@@ -316,7 +317,7 @@ if len(exchPub) != 32 {
return nil, errors.New("Invalid exchPub size")
}
- exchPrv, err := FromBase32(yml.ExchPrv)
+ exchPrv, err := FromBase32(cfg.ExchPrv)
if err != nil {
return nil, err
}
@@ -324,7 +325,7 @@ if len(exchPrv) != 32 {
return nil, errors.New("Invalid exchPrv size")
}
- signPub, err := FromBase32(yml.SignPub)
+ signPub, err := FromBase32(cfg.SignPub)
if err != nil {
return nil, err
}
@@ -332,7 +333,7 @@ if len(signPub) != ed25519.PublicKeySize {
return nil, errors.New("Invalid signPub size")
}
- signPrv, err := FromBase32(yml.SignPrv)
+ signPrv, err := FromBase32(cfg.SignPrv)
if err != nil {
return nil, err
}
@@ -340,7 +341,7 @@ if len(signPrv) != ed25519.PrivateKeySize {
return nil, errors.New("Invalid signPrv size")
}
- noisePub, err := FromBase32(yml.NoisePub)
+ noisePub, err := FromBase32(cfg.NoisePub)
if err != nil {
return nil, err
}
@@ -348,7 +349,7 @@ if len(noisePub) != 32 {
return nil, errors.New("Invalid noisePub size")
}
- noisePrv, err := FromBase32(yml.NoisePrv)
+ noisePrv, err := FromBase32(cfg.NoisePrv)
if err != nil {
return nil, err
}
diff --git a/src/check.go b/src/check.go
index 020d0f2aeee458e073a727e6bdf8019a91016f4699a15a3ddb54abd4139010e3..ade49c70230f72ec3435d5b1bafd8af27c22d0e4c2ca302608f14666162e8185 100644
--- a/src/check.go
+++ b/src/check.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@ hsh, err := blake2b.New256(nil)
if err != nil {
log.Fatalln(err)
}
- if _, err = CopyProgressed(hsh, bufio.NewReader(src), sds, showPrgrs); err != nil {
+ if _, err = CopyProgressed(hsh, bufio.NewReader(src), "check", sds, showPrgrs); err != nil {
return false, err
}
return bytes.Compare(hsh.Sum(nil), checksum) == 0, nil
diff --git a/src/chunked.go b/src/chunked.go
index 275c2786bf4acfba782c2ee6c19dfbf8e8e683e372b2fe7b3459fa5c9f507ba9..e99af03353305ad8abd3c012562a8547a9a8a2db6a69f77ca8a37df0d880d8da 100644
--- a/src/chunked.go
+++ b/src/chunked.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-bundle/main.go b/src/cmd/nncp-bundle/main.go
index 6be3df8c7d828ec1a4486ccec4f632e5bff1a1a3ea004b46fe29f9d66791f251..2e4507579927b205ab0748d782a8c5414e021d86dbf6811efc7b54663b53baa1 100644
--- a/src/cmd/nncp-bundle/main.go
+++ b/src/cmd/nncp-bundle/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -153,7 +153,7 @@ }); err != nil {
log.Fatalln("Error writing tar header:", err)
}
if _, err = nncp.CopyProgressed(
- tarWr, job.Fd,
+ tarWr, job.Fd, "Tx",
nncp.SdsAdd(sds, nncp.SDS{
"pkt": nncp.ToBase32(job.HshValue[:]),
"fullsize": job.Size,
@@ -293,7 +293,7 @@ if _, err = hsh.Write(pktEncBuf); err != nil {
log.Fatalln("Error during writing:", err)
}
if _, err = nncp.CopyProgressed(
- hsh, tarR,
+ hsh, tarR, "Rx",
nncp.SdsAdd(sds, nncp.SDS{"fullsize": entry.Size}),
ctx.ShowPrgrs,
); err != nil {
@@ -341,7 +341,7 @@ }
if _, err = hsh.Write(pktEncBuf); err != nil {
log.Fatalln("Error during writing:", err)
}
- if _, err = nncp.CopyProgressed(hsh, tarR, sds, ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(hsh, tarR, "check", sds, ctx.ShowPrgrs); err != nil {
log.Fatalln("Error during copying:", err)
}
if nncp.ToBase32(hsh.Sum(nil)) != pktName {
@@ -356,7 +356,7 @@ }
if _, err = tmp.W.Write(pktEncBuf); err != nil {
log.Fatalln("Error during writing:", err)
}
- if _, err = nncp.CopyProgressed(tmp.W, tarR, sds, ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(tmp.W, tarR, "check", sds, ctx.ShowPrgrs); err != nil {
log.Fatalln("Error during copying:", err)
}
if err = tmp.W.Flush(); err != nil {
@@ -374,7 +374,7 @@ }
}
} else {
if *dryRun {
- if _, err = nncp.CopyProgressed(ioutil.Discard, tarR, sds, ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(ioutil.Discard, tarR, "Rx", sds, ctx.ShowPrgrs); err != nil {
log.Fatalln("Error during copying:", err)
}
} else {
@@ -386,7 +386,7 @@ bufTmp := bufio.NewWriterSize(tmp, CopyBufSize)
if _, err = bufTmp.Write(pktEncBuf); err != nil {
log.Fatalln("Error during writing:", err)
}
- if _, err = nncp.CopyProgressed(bufTmp, tarR, sds, ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(bufTmp, tarR, "Rx", sds, ctx.ShowPrgrs); err != nil {
log.Fatalln("Error during copying:", err)
}
if err = bufTmp.Flush(); err != nil {
diff --git a/src/cmd/nncp-call/main.go b/src/cmd/nncp-call/main.go
index 873e8525395cc9d870b8bbcca23749ef217bd26dbc6f1ab93eae0e99fcaba21e..d491900e6d52f011a1cd2f897f11b98d1a3b4704d894eb097b97adca4cb9b47b 100644
--- a/src/cmd/nncp-call/main.go
+++ b/src/cmd/nncp-call/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ "fmt"
"log"
"os"
"strings"
+ "time"
"go.cypherpunks.ru/nncp/v5"
)
@@ -55,8 +56,8 @@ debug = flag.Bool("debug", false, "Print debug messages")
version = flag.Bool("version", false, "Print version information")
warranty = flag.Bool("warranty", false, "Print warranty information")
- onlineDeadline = flag.Uint("onlinedeadline", 0, "Override onlinedeadline option")
- maxOnlineTime = flag.Uint("maxonlinetime", 0, "Override maxonlinetime option")
+ onlineDeadlineSec = flag.Uint("onlinedeadline", 0, "Override onlinedeadline option")
+ maxOnlineTimeSec = flag.Uint("maxonlinetime", 0, "Override maxonlinetime option")
)
flag.Usage = usage
flag.Parse()
@@ -105,11 +106,13 @@ if node.NoisePub == nil {
log.Fatalln("Node does not have online communication capability")
}
- if *onlineDeadline == 0 {
- onlineDeadline = &node.OnlineDeadline
+ onlineDeadline := node.OnlineDeadline
+ if *onlineDeadlineSec != 0 {
+ onlineDeadline = time.Duration(*onlineDeadlineSec) * time.Second
}
- if *maxOnlineTime == 0 {
- maxOnlineTime = &node.MaxOnlineTime
+ maxOnlineTime := node.MaxOnlineTime
+ if *maxOnlineTimeSec != 0 {
+ maxOnlineTime = time.Duration(*maxOnlineTimeSec) * time.Second
}
var xxOnly nncp.TRxTx
@@ -157,8 +160,8 @@ nice,
xxOnly,
*rxRate,
*txRate,
- *onlineDeadline,
- *maxOnlineTime,
+ onlineDeadline,
+ maxOnlineTime,
*listOnly,
onlyPkts,
) {
diff --git a/src/cmd/nncp-caller/main.go b/src/cmd/nncp-caller/main.go
index e635419864ae2e05ab3b3cf9a21776cd8aad513b54a65b89d10caab594212f87..93c6b23ea8c02d0fb228fe96ec5b7bf65c6edc2d47853c00dee6694b48029b23 100644
--- a/src/cmd/nncp-caller/main.go
+++ b/src/cmd/nncp-caller/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-cfgenc/main.go b/src/cmd/nncp-cfgenc/main.go
index ea46d32fbbc8d6660d5058702887ffc2b0fd1428d8e5c0b506db12d0e8cd37f6..42e7c5ec09e03fbe59793f7126be1f40eecfb46f3326d9db573a5e6ec6cde156 100644
--- a/src/cmd/nncp-cfgenc/main.go
+++ b/src/cmd/nncp-cfgenc/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-cfgmin/main.go b/src/cmd/nncp-cfgmin/main.go
index ccae089c87b5e91f2bd71020e6a77b39a05684082b1038fd860fa77e72c0b8db..d144edcb5de5d07faa3ab9dee7aad38684a1a1b32cb8f1556d6bfbd789e2de1d 100644
--- a/src/cmd/nncp-cfgmin/main.go
+++ b/src/cmd/nncp-cfgmin/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-cfgnew/main.go b/src/cmd/nncp-cfgnew/main.go
index 5f0653241a6f22a961d54dd872917cd344b6dd3d4c63f424974d6f571f18d7ea..d20623daef9002b6a3774e40929fbc326222ab485381312401f50287714d7499 100644
--- a/src/cmd/nncp-cfgnew/main.go
+++ b/src/cmd/nncp-cfgnew/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-check/main.go b/src/cmd/nncp-check/main.go
index be8e57e5fdf9fc09a95238f1258c9abe803f61ba43b05e5d9fe6b5a3b49cac31..29096f082a0cac84c6b8be22c86fcc32bd209c82f81551fd66539d56ef83f563 100644
--- a/src/cmd/nncp-check/main.go
+++ b/src/cmd/nncp-check/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-daemon/main.go b/src/cmd/nncp-daemon/main.go
index be505ea72964379b15335c271417b47b623142c9f2af9e4e1fe4a27a347e77cd..5acd32fdce64a533436ea67bfb62d922bfa1b02b25528f7ae79af255183ff86d 100644
--- a/src/cmd/nncp-daemon/main.go
+++ b/src/cmd/nncp-daemon/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -59,6 +59,10 @@ return c.w.SetWriteDeadline(t)
}
func (c InetdConn) Close() error {
+ if err := c.r.Close(); err != nil {
+ c.w.Close()
+ return err
+ }
return c.w.Close()
}
@@ -72,7 +76,7 @@ ctx.LogI("call-start", nncp.SDS{"node": state.Node.Id}, "connected")
state.Wait()
ctx.LogI("call-finish", nncp.SDS{
"node": state.Node.Id,
- "duration": state.Duration.Seconds(),
+ "duration": int64(state.Duration.Seconds()),
"rxbytes": state.RxBytes,
"txbytes": state.TxBytes,
"rxspeed": state.RxSpeed,
@@ -139,6 +143,7 @@ if *inetd {
os.Stderr.Close()
conn := &InetdConn{os.Stdin, os.Stdout}
performSP(ctx, conn, nice)
+ conn.Close()
return
}
diff --git a/src/cmd/nncp-exec/main.go b/src/cmd/nncp-exec/main.go
index 00a7c13cff290a5acb521bb6b595b45e36145b2589890896a8a098bfacdd5c99..70f357f81efdefd0e22f01c31bba5744ac1e151b4eded78bc478acf69fbe475d 100644
--- a/src/cmd/nncp-exec/main.go
+++ b/src/cmd/nncp-exec/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-file/main.go b/src/cmd/nncp-file/main.go
index 0d30e5cd58477f0b4a78ccebf66303dda18ee4aa119e7908e15bd65db071d441..4fb9542dc4135c8cc6f5b3d6f8065c505a9b2ebb270bb141cfe21e7fd08ace95 100644
--- a/src/cmd/nncp-file/main.go
+++ b/src/cmd/nncp-file/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-freq/main.go b/src/cmd/nncp-freq/main.go
index e9f2c845ef3d6024c59246d9cfd1ec98398cdac364cada6e2293580b62959cad..3a522d7bc003ef8a0c6dfb3e529533f7faae98ee2cfa3efda9539109a33a633a 100644
--- a/src/cmd/nncp-freq/main.go
+++ b/src/cmd/nncp-freq/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-log/main.go b/src/cmd/nncp-log/main.go
index 50c568595e1d903d54fe3b8e8b7ebc89d709dc6071a16daae82e85e3e6c1a136..f026d7a6061210a7ecc79db1e322b75306d4649c49e7d27b308e6f132b6e5766 100644
--- a/src/cmd/nncp-log/main.go
+++ b/src/cmd/nncp-log/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-pkt/main.go b/src/cmd/nncp-pkt/main.go
index 5129f785957e5cc9b11e7aeb5771070aa1c2d67c741d91fa7f0ba965db37928c..291a760a403473fe9c675057d346e52e753e787765937572da812eabf0f0001c 100644
--- a/src/cmd/nncp-pkt/main.go
+++ b/src/cmd/nncp-pkt/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-reass/main.go b/src/cmd/nncp-reass/main.go
index d486aa5138a1a73a7c581178f897110d802d143d093a692e381fa09d2553d4d4..878703d2ecb14feed89e235be60c3c734cb1144742b833a9237c16dccad9238d 100644
--- a/src/cmd/nncp-reass/main.go
+++ b/src/cmd/nncp-reass/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -144,10 +144,14 @@ hsh, err = blake2b.New256(nil)
if err != nil {
log.Fatalln(err)
}
- if _, err = nncp.CopyProgressed(hsh, bufio.NewReader(fd), nncp.SDS{
- "pkt": chunkPath,
- "fullsize": fi.Size(),
- }, ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(
+ hsh, bufio.NewReader(fd), "check",
+ nncp.SDS{
+ "pkt": chunkPath,
+ "fullsize": fi.Size(),
+ },
+ ctx.ShowPrgrs,
+ ); err != nil {
log.Fatalln(err)
}
fd.Close()
@@ -195,10 +199,14 @@ fi, err := fd.Stat()
if err != nil {
log.Fatalln("Can not stat file:", err)
}
- if _, err = nncp.CopyProgressed(dstW, bufio.NewReader(fd), nncp.SDS{
- "pkt": chunkPath,
- "fullsize": fi.Size(),
- }, ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(
+ dstW, bufio.NewReader(fd), "reass",
+ nncp.SDS{
+ "pkt": chunkPath,
+ "fullsize": fi.Size(),
+ },
+ ctx.ShowPrgrs,
+ ); err != nil {
log.Fatalln(err)
}
fd.Close()
diff --git a/src/cmd/nncp-rm/main.go b/src/cmd/nncp-rm/main.go
index 59debf09d1ceb4a34e1741847739a822404215c457acfc72727e97432b9ee4e8..af86ffeb0a59bf4f610ddd1b989d705f68e05cdb7134aa5c896971621489798a 100644
--- a/src/cmd/nncp-rm/main.go
+++ b/src/cmd/nncp-rm/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-stat/main.go b/src/cmd/nncp-stat/main.go
index 2e05348e0a7476825be7e5ca0d037fc53185aa46cdb6d984983fa45770a271f8..915562979b5ca18e021fba89eb9663252f08dd1a2761a45434c1b63f95dba9cf 100644
--- a/src/cmd/nncp-stat/main.go
+++ b/src/cmd/nncp-stat/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-toss/main.go b/src/cmd/nncp-toss/main.go
index 3f5eac3060ee5985d38dbac7361158b051e08feb2215196383d89470402e86bc..1b7c4998db5f939e283c5c4fc970dd06e603945f57e12d41fc6d6cfe6fc4614b 100644
--- a/src/cmd/nncp-toss/main.go
+++ b/src/cmd/nncp-toss/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/cmd/nncp-xfer/main.go b/src/cmd/nncp-xfer/main.go
index a7edef1501dd95b6e78239a53b9ab67f6e2232e40b6809dacea9a812f8c15925..aeb6257feae1793f602c4ff9a9ab68f4e134628226e35a51ca9e33eac0311437 100644
--- a/src/cmd/nncp-xfer/main.go
+++ b/src/cmd/nncp-xfer/main.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -215,10 +215,14 @@ }
ctx.LogE("nncp-xfer", sds, err, "copy")
w.CloseWithError(err)
}()
- if _, err = nncp.CopyProgressed(tmp.W, r, nncp.SdsAdd(sds, nncp.SDS{
- "pkt": filename,
- "fullsize": sds["size"],
- }), ctx.ShowPrgrs); err != nil {
+ if _, err = nncp.CopyProgressed(
+ tmp.W, r, "Rx",
+ nncp.SdsAdd(sds, nncp.SDS{
+ "pkt": filename,
+ "fullsize": sds["size"],
+ }),
+ ctx.ShowPrgrs,
+ ); err != nil {
ctx.LogE("nncp-xfer", sds, err, "copy")
isBad = true
}
@@ -258,7 +262,7 @@ if nodeOnly != nil && nodeId != *nodeOnly.Id {
ctx.LogD("nncp-xfer", sds, "skip")
continue
}
- dirLock, err := ctx.LockDir(&nodeId, nncp.TTx)
+ dirLock, err := ctx.LockDir(&nodeId, string(nncp.TTx))
if err != nil {
continue
}
@@ -333,8 +337,7 @@ sds["tmp"] = tmp.Name()
ctx.LogD("nncp-xfer", sds, "created")
bufW := bufio.NewWriter(tmp)
copied, err := nncp.CopyProgressed(
- bufW,
- bufio.NewReader(job.Fd),
+ bufW, bufio.NewReader(job.Fd), "Tx",
nncp.SdsAdd(sds, nncp.SDS{"fullsize": job.Size}),
ctx.ShowPrgrs,
)
diff --git a/src/ctx.go b/src/ctx.go
index 256baba51eba94ddca44f4dfe5186cc3d36f8bae3f868d14829019e63ffda0c4..caa8a202793c145d9006e06792e1f933f1a104fcdaab54edab58e38594c14b54 100644
--- a/src/ctx.go
+++ b/src/ctx.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/eblob.go b/src/eblob.go
index b43b7307953f6c53d2ee25c423cc5da23ffa1d14acd5c1ec095b0aec1e100507..a23184940cfacb52724c1ced7092bceab29c732c3d66725dbe8d0a2a213767bf 100644
--- a/src/eblob.go
+++ b/src/eblob.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/go.mod b/src/go.mod
index 249a7a9b50a50f568f77db630eca411afb5471b39b351f7c2a38aa694ea33f9c..059baaaa58ba87b57c31f3d05aee75f3d9aeef15931d6163583b03c9a57583ef 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -9,10 +9,10 @@ github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
github.com/hjson/hjson-go v3.0.1+incompatible
github.com/klauspost/compress v1.9.2
github.com/kr/pretty v0.1.0 // indirect
- go.cypherpunks.ru/balloon v1.1.0
- golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
- golang.org/x/net v0.0.0-20191112182307-2180aed22343
- golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056
+ go.cypherpunks.ru/balloon v1.1.1
+ golang.org/x/crypto v0.0.0-20191219195013-becbf705a915
+ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553
+ golang.org/x/sys v0.0.0-20191219235734-af0d71d358ab
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
)
diff --git a/src/go.sum b/src/go.sum
index cc93040520235046200fdbee7cafd74955f140be686b0ef6aeec0676b846f382..d3b498c0f5d3a2a7adb446af81bb66a9ee9da7519d316b731cc92a6e766b8c39 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -17,19 +17,19 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-go.cypherpunks.ru/balloon v1.1.0 h1:tKwBeS1xrZYS/vn87Hm/4EvgNeHKyU1uC099aPRa2JQ=
-go.cypherpunks.ru/balloon v1.1.0/go.mod h1:k4s4ozrIrhpBjj78Z7LX8ZHxMQ+XE7DZUWl8gP2ojCo=
+go.cypherpunks.ru/balloon v1.1.1 h1:ypHM1DRf/XuCrp9pDkTHg00CqZX/Np/APb//iHvDJTA=
+go.cypherpunks.ru/balloon v1.1.1/go.mod h1:k4s4ozrIrhpBjj78Z7LX8ZHxMQ+XE7DZUWl8gP2ojCo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4=
-golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191219195013-becbf705a915 h1:aJ0ex187qoXrJHPo8ZasVTASQB7llQP6YeNzgDALPRk=
+golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20191112182307-2180aed22343 h1:00ohfJ4K98s3m6BGUoBd8nyfp4Yl0GoIKvw5abItTjI=
-golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 h1:dHtDnRWQtSx0Hjq9kvKFpBh9uPPKfQN70NZZmvssGwk=
-golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191219235734-af0d71d358ab h1:j8r8g0V3tVdbo274kyTmC+yEsChru2GfvdiV84wm5T8=
+golang.org/x/sys v0.0.0-20191219235734-af0d71d358ab/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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=
diff --git a/src/humanizer.go b/src/humanizer.go
index fcbd9e7acb364d3e5723993c31c9ba7cd7c5964ed401b146081cd31f1bbbe191..2678ca977df6ed240001b37010b31ca0fd4b34e2fa6f5af5e981586b954f638c 100644
--- a/src/humanizer.go
+++ b/src/humanizer.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/jobs.go b/src/jobs.go
index 22de9149ffd36bb849a9e834d10f0e9f0a49316056f6474a952fdc0c79e2942c..2964fd84e0819887f4183f6752033e24ca327b30f6dd4ec685a093bb04ebbc70 100644
--- a/src/jobs.go
+++ b/src/jobs.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/lockdir.go b/src/lockdir.go
index 2911217049d4f918c5b05a685933154fd35e18099a717f48e7ab3ced2e1020a0..678e047fee4c256921678c784346662ced50efbe1db4b871bc816eeb878d7a44 100644
--- a/src/lockdir.go
+++ b/src/lockdir.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,9 +24,9 @@
"golang.org/x/sys/unix"
)
-func (ctx *Ctx) LockDir(nodeId *NodeId, xx TRxTx) (*os.File, error) {
+func (ctx *Ctx) LockDir(nodeId *NodeId, lockCtx string) (*os.File, error) {
ctx.ensureRxDir(nodeId)
- lockPath := filepath.Join(ctx.Spool, nodeId.String(), string(xx)) + ".lock"
+ lockPath := filepath.Join(ctx.Spool, nodeId.String(), lockCtx) + ".lock"
dirLock, err := os.OpenFile(
lockPath,
os.O_CREATE|os.O_WRONLY,
diff --git a/src/log.go b/src/log.go
index 77875d24b0685a80b907bb83416144a4154d166aafdd547fea34997b26331a84..3c22ff56507d6b82ffd49283dac3c08d881e82da6f8f77aac964715af23a30de 100644
--- a/src/log.go
+++ b/src/log.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/nncp.go b/src/nncp.go
index 572ebd3039970c1e875acf4efaf7cd3ab6984612a51ee2882bc28473dbda36fe..80a7fbae1a9fd7b22e248e4950b08fb830f1279c141bc3d9ff12d13b8a4c1af8 100644
--- a/src/nncp.go
+++ b/src/nncp.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -46,7 +46,7 @@ }
func UsageHeader() string {
return VersionGet() + `
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
License GPLv3: GNU GPL version 3
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
diff --git a/src/node.go b/src/node.go
index e8107dd3692beee714ca1fa15fa175202fb2661dcab2405a209030a00bd40ef6..7e7fbe5f567a889336af79b279c412944df771052d23edcf3a8c3051c82e3f43 100644
--- a/src/node.go
+++ b/src/node.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ import (
"crypto/rand"
"errors"
"sync"
+ "time"
"github.com/flynn/noise"
"golang.org/x/crypto/blake2b"
@@ -50,8 +51,8 @@ Via []*NodeId
Addrs map[string]string
RxRate int
TxRate int
- OnlineDeadline uint
- MaxOnlineTime uint
+ OnlineDeadline time.Duration
+ MaxOnlineTime time.Duration
Calls []*Call
Busy bool
diff --git a/src/pipe.go b/src/pipe.go
index 265557ca7a5e7547ca2202362b6b19256a53c05f247584361c71c5825345f1a0..2dcba30b420328057e172f394bda18b612c198b1132880e569a020ba7909e16c 100644
--- a/src/pipe.go
+++ b/src/pipe.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/pkt.go b/src/pkt.go
index 972952cd010cf4da95da2f7043073957800ceaa396a37e5de8b4796e8ef838f1..4960f7a3d41b79b3fc47035caef1f04a1d2e61f36a9f81597362606ab77951bb 100644
--- a/src/pkt.go
+++ b/src/pkt.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/pkt_test.go b/src/pkt_test.go
index 3aaf662529e5d46409ed91ba2933aa6c44df32bc7e65624920ff198628c1ecb3..9bb687480569ac6bf5045ce923f15d3adc6b9edde24b7aef9a6dee835628d203 100644
--- a/src/pkt_test.go
+++ b/src/pkt_test.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/progress.go b/src/progress.go
index bc79635134647b085e8f0e8b957355a59a989219459b56340a1f38387e98c5af..6018751eb1dc1ebf06d98dc7ca636eb95b3d19bfcaa98adabc430f892bf3f8bf 100644
--- a/src/progress.go
+++ b/src/progress.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@ import (
"fmt"
"io"
"os"
- "strings"
"sync"
"time"
@@ -82,6 +81,7 @@
func CopyProgressed(
dst io.Writer,
src io.Reader,
+ prgrsPrefix string,
sds SDS,
showPrgrs bool,
) (written int64, err error) {
@@ -96,7 +96,7 @@ if nw > 0 {
written += int64(nw)
if showPrgrs {
sds["size"] = written
- Progress(sds)
+ Progress(prgrsPrefix, sds)
}
}
if ew != nil {
@@ -118,13 +118,13 @@ }
return
}
-func Progress(sds SDS) {
- pkt := sds["pkt"].(string)
+func Progress(prefix string, sds SDS) {
var size int64
if sizeI, exists := sds["size"]; exists {
size = sizeI.(int64)
}
fullsize := sds["fullsize"].(int64)
+ pkt := sds["pkt"].(string)
progressBarsLock.RLock()
pb, exists := progressBars[pkt]
progressBarsLock.RUnlock()
@@ -138,9 +138,7 @@ what := pkt
if len(what) >= 52 { // Base32 encoded
what = what[:16] + ".." + what[len(what)-16:]
}
- if xx, exists := sds["xx"]; exists {
- what = strings.Title(xx.(string)) + " " + what
- }
+ what = prefix + " " + what
pb.Render(what, size)
if size >= fullsize {
pb.Kill()
diff --git a/src/sp.go b/src/sp.go
index d29b4b6f555e5536ba64a07a7a642b7068639c1c524ce98662dca9ef03713ea5..f98ada6188a104fb75726a4253fb88ad442ed46db5f732d6e32dfba810ad68bd 100644
--- a/src/sp.go
+++ b/src/sp.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -34,19 +34,19 @@ "github.com/flynn/noise"
)
const (
- MaxSPSize = 1<<16 - 256
- PartSuffix = ".part"
- DefaultDeadline = 10
+ MaxSPSize = 1<<16 - 256
+ PartSuffix = ".part"
+ SPHeadOverhead = 4
)
var (
MagicNNCPLv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'S', 0, 0, 1}
- SPHeadOverhead int
SPInfoOverhead int
SPFreqOverhead int
SPFileOverhead int
SPHaltMarshalized []byte
+ SPPingMarshalized []byte
NoiseCipherSuite noise.CipherSuite = noise.NewCipherSuite(
noise.DH25519,
@@ -54,6 +54,9 @@ noise.CipherChaChaPoly,
noise.HashBLAKE2b,
)
+ DefaultDeadline = 10 * time.Second
+ PingTimeout = time.Minute
+
spWorkersGroup sync.WaitGroup
)
@@ -65,6 +68,7 @@ SPTypeFreq SPType = iota
SPTypeFile SPType = iota
SPTypeDone SPType = iota
SPTypeHalt SPType = iota
+ SPTypePing SPType = iota
)
type SPHead struct {
@@ -114,8 +118,16 @@ spHead := SPHead{Type: SPTypeHalt}
if _, err := xdr.Marshal(&buf, spHead); err != nil {
panic(err)
}
+ SPHaltMarshalized = make([]byte, SPHeadOverhead)
copy(SPHaltMarshalized, buf.Bytes())
- SPHeadOverhead = buf.Len()
+ buf.Reset()
+
+ spHead = SPHead{Type: SPTypePing}
+ if _, err := xdr.Marshal(&buf, spHead); err != nil {
+ panic(err)
+ }
+ SPPingMarshalized = make([]byte, SPHeadOverhead)
+ copy(SPPingMarshalized, buf.Bytes())
buf.Reset()
spInfo := SPInfo{Nice: 123, Size: 123, Hash: new([32]byte)}
@@ -141,11 +153,10 @@ }
func MarshalSP(typ SPType, sp interface{}) []byte {
var buf bytes.Buffer
- var err error
- if _, err = xdr.Marshal(&buf, SPHead{typ}); err != nil {
+ if _, err := xdr.Marshal(&buf, SPHead{typ}); err != nil {
panic(err)
}
- if _, err = xdr.Marshal(&buf, sp); err != nil {
+ if _, err := xdr.Marshal(&buf, sp); err != nil {
panic(err)
}
return buf.Bytes()
@@ -171,21 +182,25 @@ type SPState struct {
Ctx *Ctx
Node *Node
Nice uint8
- onlineDeadline uint
- maxOnlineTime uint
+ onlineDeadline time.Duration
+ maxOnlineTime time.Duration
hs *noise.HandshakeState
csOur *noise.CipherState
csTheir *noise.CipherState
payloads chan []byte
+ pings chan struct{}
infosTheir map[[32]byte]*SPInfo
infosOurSeen map[[32]byte]uint8
queueTheir []*FreqWithNice
wg sync.WaitGroup
RxBytes int64
RxLastSeen time.Time
+ RxLastNonPing time.Time
TxBytes int64
TxLastSeen time.Time
+ TxLastNonPing time.Time
started time.Time
+ mustFinishAt time.Time
Duration time.Duration
RxSpeed int64
TxSpeed int64
@@ -194,22 +209,40 @@ txLock *os.File
xxOnly TRxTx
rxRate int
txRate int
- isDead bool
+ isDead chan struct{}
listOnly bool
onlyPkts map[[32]byte]bool
+ writeSPBuf bytes.Buffer
sync.RWMutex
}
+func (state *SPState) SetDead() {
+ state.Lock()
+ defer state.Unlock()
+ select {
+ case <-state.isDead:
+ // Already closed channel, dead
+ return
+ default:
+ }
+ close(state.isDead)
+ go func() {
+ for _ = range state.payloads {
+ }
+ }()
+ go func() {
+ for _ = range state.pings {
+ }
+ }()
+}
+
func (state *SPState) NotAlive() bool {
- if state.isDead {
- return true
- }
- now := time.Now()
- if state.maxOnlineTime > 0 && state.started.Add(time.Duration(state.maxOnlineTime)*time.Second).Before(now) {
+ select {
+ case <-state.isDead:
return true
+ default:
}
- return uint(now.Sub(state.RxLastSeen).Seconds()) >= state.onlineDeadline &&
- uint(now.Sub(state.TxLastSeen).Seconds()) >= state.onlineDeadline
+ return false
}
func (state *SPState) dirUnlock() {
@@ -217,11 +250,21 @@ state.Ctx.UnlockDir(state.rxLock)
state.Ctx.UnlockDir(state.txLock)
}
-func (state *SPState) WriteSP(dst io.Writer, payload []byte) error {
- n, err := xdr.Marshal(dst, SPRaw{Magic: MagicNNCPLv1, Payload: payload})
- if err == nil {
+func (state *SPState) WriteSP(dst io.Writer, payload []byte, ping bool) error {
+ state.writeSPBuf.Reset()
+ n, err := xdr.Marshal(&state.writeSPBuf, SPRaw{
+ Magic: MagicNNCPLv1,
+ Payload: payload,
+ })
+ if err != nil {
+ return err
+ }
+ if n, err = dst.Write(state.writeSPBuf.Bytes()); err == nil {
state.TxLastSeen = time.Now()
state.TxBytes += int64(n)
+ if !ping {
+ state.TxLastNonPing = state.TxLastSeen
+ }
}
return err
}
@@ -292,14 +335,14 @@ return err
}
var rxLock *os.File
if !state.listOnly && (state.xxOnly == "" || state.xxOnly == TRx) {
- rxLock, err = state.Ctx.LockDir(nodeId, TRx)
+ rxLock, err = state.Ctx.LockDir(nodeId, string(TRx))
if err != nil {
return err
}
}
var txLock *os.File
if !state.listOnly && (state.xxOnly == "" || state.xxOnly == TTx) {
- txLock, err = state.Ctx.LockDir(nodeId, TTx)
+ txLock, err = state.Ctx.LockDir(nodeId, string(TTx))
if err != nil {
return err
}
@@ -321,6 +364,7 @@ return err
}
state.hs = hs
state.payloads = make(chan []byte)
+ state.pings = make(chan struct{})
state.infosTheir = make(map[[32]byte]*SPInfo)
state.infosOurSeen = make(map[[32]byte]uint8)
state.started = started
@@ -349,14 +393,14 @@ return err
}
sds := SDS{"node": nodeId, "nice": int(state.Nice)}
state.Ctx.LogD("sp-start", sds, "sending first message")
- conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second))
- if err = state.WriteSP(conn, buf); err != nil {
+ conn.SetWriteDeadline(time.Now().Add(DefaultDeadline))
+ if err = state.WriteSP(conn, buf, false); err != nil {
state.Ctx.LogE("sp-start", sds, err, "")
state.dirUnlock()
return err
}
state.Ctx.LogD("sp-start", sds, "waiting for first message")
- conn.SetReadDeadline(time.Now().Add(DefaultDeadline * time.Second))
+ conn.SetReadDeadline(time.Now().Add(DefaultDeadline))
if buf, err = state.ReadSP(conn); err != nil {
state.Ctx.LogE("sp-start", sds, err, "")
state.dirUnlock()
@@ -373,7 +417,6 @@ err = state.StartWorkers(conn, infosPayloads, payload)
if err != nil {
state.Ctx.LogE("sp-start", sds, err, "")
state.dirUnlock()
- return err
}
return err
}
@@ -396,6 +439,7 @@ }
xxOnly := TRxTx("")
state.hs = hs
state.payloads = make(chan []byte)
+ state.pings = make(chan struct{})
state.infosOurSeen = make(map[[32]byte]uint8)
state.infosTheir = make(map[[32]byte]*SPInfo)
state.started = started
@@ -403,7 +447,7 @@ state.xxOnly = xxOnly
var buf []byte
var payload []byte
state.Ctx.LogD("sp-start", SDS{"nice": int(state.Nice)}, "waiting for first message")
- conn.SetReadDeadline(time.Now().Add(DefaultDeadline * time.Second))
+ conn.SetReadDeadline(time.Now().Add(DefaultDeadline))
if buf, err = state.ReadSP(conn); err != nil {
state.Ctx.LogE("sp-start", SDS{}, err, "")
return err
@@ -437,7 +481,7 @@ return err
}
var rxLock *os.File
if xxOnly == "" || xxOnly == TRx {
- rxLock, err = state.Ctx.LockDir(node.Id, TRx)
+ rxLock, err = state.Ctx.LockDir(node.Id, string(TRx))
if err != nil {
return err
}
@@ -445,7 +489,7 @@ }
state.rxLock = rxLock
var txLock *os.File
if xxOnly == "" || xxOnly == TTx {
- txLock, err = state.Ctx.LockDir(node.Id, TTx)
+ txLock, err = state.Ctx.LockDir(node.Id, string(TTx))
if err != nil {
return err
}
@@ -471,8 +515,8 @@ if err != nil {
state.dirUnlock()
return err
}
- conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second))
- if err = state.WriteSP(conn, buf); err != nil {
+ conn.SetWriteDeadline(time.Now().Add(DefaultDeadline))
+ if err = state.WriteSP(conn, buf, false); err != nil {
state.Ctx.LogE("sp-start", sds, err, "")
state.dirUnlock()
return err
@@ -481,7 +525,6 @@ state.Ctx.LogD("sp-start", sds, "starting workers")
err = state.StartWorkers(conn, infosPayloads, payload)
if err != nil {
state.dirUnlock()
- return err
}
return err
}
@@ -489,9 +532,17 @@
func (state *SPState) StartWorkers(
conn ConnDeadlined,
infosPayloads [][]byte,
- payload []byte) error {
+ payload []byte,
+) error {
sds := SDS{"node": state.Node.Id, "nice": int(state.Nice)}
+ state.isDead = make(chan struct{})
+ if state.maxOnlineTime > 0 {
+ state.mustFinishAt = state.started.Add(state.maxOnlineTime)
+ }
+
+ // Remaining handshake payload sending
if len(infosPayloads) > 1 {
+ state.wg.Add(1)
go func() {
for _, payload := range infosPayloads[1:] {
state.Ctx.LogD(
@@ -501,8 +552,11 @@ "queuing remaining payload",
)
state.payloads <- payload
}
+ state.wg.Done()
}()
}
+
+ // Processing of first payload and queueing its responses
state.Ctx.LogD(
"sp-work",
SdsAdd(sds, SDS{"size": len(payload)}),
@@ -513,7 +567,7 @@ if err != nil {
state.Ctx.LogE("sp-work", sds, err, "")
return err
}
-
+ state.wg.Add(1)
go func() {
for _, reply := range replies {
state.Ctx.LogD(
@@ -523,42 +577,88 @@ "queuing reply",
)
state.payloads <- reply
}
+ state.wg.Done()
}()
+ // Periodic jobs
+ state.wg.Add(1)
+ go func() {
+ deadlineTicker := time.NewTicker(time.Second)
+ pingTicker := time.NewTicker(PingTimeout)
+ for {
+ select {
+ case <-state.isDead:
+ state.wg.Done()
+ deadlineTicker.Stop()
+ pingTicker.Stop()
+ return
+ case now := <-deadlineTicker.C:
+ if (now.Sub(state.RxLastNonPing) >= state.onlineDeadline &&
+ now.Sub(state.TxLastNonPing) >= state.onlineDeadline) ||
+ (state.maxOnlineTime > 0 && state.mustFinishAt.Before(now)) ||
+ (now.Sub(state.RxLastSeen) >= 2*PingTimeout) {
+ state.SetDead()
+ conn.Close()
+ }
+ case now := <-pingTicker.C:
+ if now.After(state.TxLastSeen.Add(PingTimeout)) {
+ state.wg.Add(1)
+ go func() {
+ state.pings <- struct{}{}
+ state.wg.Done()
+ state.Ctx.LogD("HERE", SDS{}, "PING GOROUTINE QUIT")
+ }()
+ }
+ }
+ }
+ }()
+
+ // Spool checker and INFOs sender of appearing files
if !state.listOnly && (state.xxOnly == "" || state.xxOnly == TTx) {
+ state.wg.Add(1)
go func() {
- for range time.Tick(time.Second) {
- if state.NotAlive() {
+ ticker := time.NewTicker(time.Second)
+ for {
+ select {
+ case <-state.isDead:
+ state.wg.Done()
+ ticker.Stop()
return
- }
- for _, payload := range state.Ctx.infosOur(
- state.Node.Id,
- state.Nice,
- &state.infosOurSeen,
- ) {
- state.Ctx.LogD(
- "sp-work",
- SdsAdd(sds, SDS{"size": len(payload)}),
- "queuing new info",
- )
- state.payloads <- payload
+ case <-ticker.C:
+ for _, payload := range state.Ctx.infosOur(
+ state.Node.Id,
+ state.Nice,
+ &state.infosOurSeen,
+ ) {
+ state.Ctx.LogD(
+ "sp-work",
+ SdsAdd(sds, SDS{"size": len(payload)}),
+ "queuing new info",
+ )
+ state.payloads <- payload
+ }
}
}
}()
}
+ // Sender
state.wg.Add(1)
go func() {
- defer func() {
- state.isDead = true
- state.wg.Done()
- }()
+ defer conn.Close()
+ defer state.SetDead()
+ defer state.wg.Done()
for {
if state.NotAlive() {
return
}
var payload []byte
+ var ping bool
select {
+ case <-state.pings:
+ state.Ctx.LogD("sp-xmit", sds, "got ping")
+ payload = SPPingMarshalized
+ ping = true
case payload = <-state.payloads:
state.Ctx.LogD(
"sp-xmit",
@@ -566,22 +666,17 @@ SdsAdd(sds, SDS{"size": len(payload)}),
"got payload",
)
default:
- }
- if payload == nil {
state.RLock()
if len(state.queueTheir) == 0 {
- state.Ctx.LogD("sp-xmit", sds, "file queue is empty")
state.RUnlock()
time.Sleep(100 * time.Millisecond)
continue
}
freq := state.queueTheir[0].freq
state.RUnlock()
-
if state.txRate > 0 {
time.Sleep(time.Second / time.Duration(state.txRate))
}
-
sdsp := SdsAdd(sds, SDS{
"xx": string(TTx),
"pkt": ToBase32(freq.Hash[:]),
@@ -596,12 +691,12 @@ ToBase32(freq.Hash[:]),
))
if err != nil {
state.Ctx.LogE("sp-file", sdsp, err, "")
- break
+ return
}
fi, err := fd.Stat()
if err != nil {
state.Ctx.LogE("sp-file", sdsp, err, "")
- break
+ return
}
fullSize := fi.Size()
var buf []byte
@@ -609,20 +704,16 @@ if freq.Offset < uint64(fullSize) {
state.Ctx.LogD("sp-file", sdsp, "seeking")
if _, err = fd.Seek(int64(freq.Offset), io.SeekStart); err != nil {
state.Ctx.LogE("sp-file", sdsp, err, "")
- break
+ return
}
buf = make([]byte, MaxSPSize-SPHeadOverhead-SPFileOverhead)
n, err := fd.Read(buf)
if err != nil {
state.Ctx.LogE("sp-file", sdsp, err, "")
- break
+ return
}
buf = buf[:n]
- state.Ctx.LogD(
- "sp-file",
- SdsAdd(sdsp, SDS{"size": n}),
- "read",
- )
+ state.Ctx.LogD("sp-file", SdsAdd(sdsp, SDS{"size": n}), "read")
}
fd.Close()
payload = MarshalSP(SPTypeFile, SPFile{
@@ -634,7 +725,7 @@ ourSize := freq.Offset + uint64(len(buf))
sdsp["size"] = int64(ourSize)
sdsp["fullsize"] = fullSize
if state.Ctx.ShowPrgrs {
- Progress(sdsp)
+ Progress("Tx", sdsp)
}
state.Lock()
if len(state.queueTheir) > 0 && *state.queueTheir[0].freq.Hash == *freq.Hash {
@@ -653,31 +744,24 @@ state.Ctx.LogD("sp-file", sdsp, "queue disappeared")
}
state.Unlock()
}
- state.Ctx.LogD(
- "sp-xmit",
- SdsAdd(sds, SDS{"size": len(payload)}),
- "sending",
- )
- conn.SetWriteDeadline(time.Now().Add(DefaultDeadline * time.Second))
- if err := state.WriteSP(conn, state.csOur.Encrypt(nil, nil, payload)); err != nil {
+ state.Ctx.LogD("sp-xmit", SdsAdd(sds, SDS{"size": len(payload)}), "sending")
+ conn.SetWriteDeadline(time.Now().Add(DefaultDeadline))
+ if err := state.WriteSP(conn, state.csOur.Encrypt(nil, nil, payload), ping); err != nil {
state.Ctx.LogE("sp-xmit", sds, err, "")
- break
+ return
}
}
}()
+ // Receiver
state.wg.Add(1)
go func() {
- defer func() {
- state.isDead = true
- state.wg.Done()
- }()
for {
if state.NotAlive() {
- return
+ break
}
state.Ctx.LogD("sp-recv", sds, "waiting for payload")
- conn.SetReadDeadline(time.Now().Add(DefaultDeadline * time.Second))
+ conn.SetReadDeadline(time.Now().Add(DefaultDeadline))
payload, err := state.ReadSP(conn)
if err != nil {
if err == io.EOF {
@@ -714,6 +798,7 @@ if err != nil {
state.Ctx.LogE("sp-recv", sds, err, "")
break
}
+ state.wg.Add(1)
go func() {
for _, reply := range replies {
state.Ctx.LogD(
@@ -723,11 +808,16 @@ "queuing reply",
)
state.payloads <- reply
}
+ state.wg.Done()
}()
if state.rxRate > 0 {
time.Sleep(time.Second / time.Duration(state.rxRate))
}
}
+ state.SetDead()
+ state.wg.Done()
+ state.SetDead()
+ conn.Close()
}()
return nil
@@ -735,6 +825,8 @@ }
func (state *SPState) Wait() {
state.wg.Wait()
+ close(state.payloads)
+ close(state.pings)
state.dirUnlock()
state.Duration = time.Now().Sub(state.started)
state.RxSpeed = state.RxBytes
@@ -763,6 +855,13 @@ state.Ctx.LogE("sp-process", sds, err, "")
return nil, err
}
switch head.Type {
+ case SPTypeHalt:
+ state.Ctx.LogD("sp-process", SdsAdd(sds, SDS{"type": "halt"}), "")
+ state.Lock()
+ state.queueTheir = nil
+ state.Unlock()
+ case SPTypePing:
+ state.Ctx.LogD("sp-process", SdsAdd(sds, SDS{"type": "ping"}), "")
case SPTypeInfo:
infosGot = true
sdsp := SdsAdd(sds, SDS{"type": "info"})
@@ -873,19 +972,23 @@ state.Ctx.LogE("sp-file", sdsp, err, "")
fd.Close()
return nil, err
}
- ourSize := file.Offset + uint64(len(file.Payload))
+ ourSize := int64(file.Offset + uint64(len(file.Payload)))
+ sdsp["size"] = ourSize
+ fullsize := int64(0)
state.RLock()
- sdsp["size"] = int64(ourSize)
- sdsp["fullsize"] = int64(state.infosTheir[*file.Hash].Size)
+ infoTheir, ok := state.infosTheir[*file.Hash]
+ state.RUnlock()
+ if ok {
+ fullsize = int64(infoTheir.Size)
+ }
+ sdsp["fullsize"] = fullsize
if state.Ctx.ShowPrgrs {
- Progress(sdsp)
+ Progress("Rx", sdsp)
}
- if state.infosTheir[*file.Hash].Size != ourSize {
- state.RUnlock()
+ if fullsize != ourSize {
fd.Close()
continue
}
- state.RUnlock()
spWorkersGroup.Wait()
spWorkersGroup.Add(1)
go func() {
@@ -917,8 +1020,10 @@ state.Lock()
delete(state.infosTheir, *file.Hash)
state.Unlock()
spWorkersGroup.Done()
+ state.wg.Add(1)
go func() {
state.payloads <- MarshalSP(SPTypeDone, SPDone{file.Hash})
+ state.wg.Done()
}()
}()
case SPTypeDone:
@@ -975,11 +1080,6 @@ }
} else {
state.Ctx.LogD("sp-process", sdsp, "unknown")
}
- case SPTypeHalt:
- state.Ctx.LogD("sp-process", SdsAdd(sds, SDS{"type": "halt"}), "")
- state.Lock()
- state.queueTheir = nil
- state.Unlock()
default:
state.Ctx.LogE(
"sp-process",
@@ -988,6 +1088,9 @@ errors.New("unknown type"),
"",
)
return nil, BadPktType
+ }
+ if head.Type != SPTypePing {
+ state.RxLastNonPing = state.RxLastSeen
}
}
if infosGot {
diff --git a/src/tmp.go b/src/tmp.go
index a2a19cbcf91e9896525cac703e8f6a60279912a21ca95a2847068893adc2fb25..205db2a395f1e36a605c6574bac6c63c12fe3a769c2e0f08d8c31b559f21d51e 100644
--- a/src/tmp.go
+++ b/src/tmp.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/toss.go b/src/toss.go
index 998dca2ca932e065198c92ec5e7dd5b925785498539a18d7242145ce5d78e55f..cd2fd962f5690b660d36e6bec8b2d0175bf81dfa9f75c36698b12ed4548d1e7d 100644
--- a/src/toss.go
+++ b/src/toss.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -68,6 +68,12 @@ nodeId *NodeId,
nice uint8,
dryRun, doSeen, noFile, noFreq, noExec, noTrns bool,
) bool {
+ dirLock, err := ctx.LockDir(nodeId, "toss")
+ if err != nil {
+ ctx.LogE("rx", SDS{}, err, "lock")
+ return false
+ }
+ defer ctx.UnlockDir(dirLock)
isBad := false
sendmail := ctx.Neigh[*ctx.SelfId].Exec["sendmail"]
decompressor, err := zstd.NewReader(nil)
@@ -224,8 +230,7 @@ sds["tmp"] = tmp.Name()
ctx.LogD("rx", sds, "created")
bufW := bufio.NewWriter(tmp)
if _, err = CopyProgressed(
- bufW,
- pipeR,
+ bufW, pipeR, "Rx file",
SdsAdd(sds, SDS{"fullsize": sds["size"]}),
ctx.ShowPrgrs,
); err != nil {
diff --git a/src/toss_test.go b/src/toss_test.go
index 535ab95b7a5bf3bf7af2f4a4f2a0e4dd63d65a1bfa5e912bdbd2a607f717cb3d..48a291ee9e653684456bdf1c772e1e7633051ad568a2c5ffc36898c698e333c5 100644
--- a/src/toss_test.go
+++ b/src/toss_test.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/tx.go b/src/tx.go
index aa293d2cd76645d7022b026de069f085bcd3a0a0bf9c5dc2a174330c6f6bad5f..ccf1793eef8ee1f0902e0e9879f094d04a627c9733398fa887d652a13ad38449 100644
--- a/src/tx.go
+++ b/src/tx.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -108,8 +108,8 @@ curSize = PktEncOverhead + PktSizeOverhead + sizeWithTags(PktOverhead+curSize)
}
go func() {
_, err := CopyProgressed(
- tmp.W, pipeR,
- SDS{"xx": string(TTx), "pkt": pktName, "fullsize": curSize},
+ tmp.W, pipeR, "Tx",
+ SDS{"pkt": pktName, "fullsize": curSize},
ctx.ShowPrgrs,
)
errs <- err
@@ -532,11 +532,11 @@ tmp, err := ctx.NewTmpFileWHash()
if err != nil {
return err
}
- if _, err = CopyProgressed(tmp.W, src, SDS{
- "xx": string(TTx),
- "pkt": node.Id.String(),
- "fullsize": size,
- }, ctx.ShowPrgrs); err != nil {
+ if _, err = CopyProgressed(
+ tmp.W, src, "Tx trns",
+ SDS{"pkt": node.Id.String(), "fullsize": size},
+ ctx.ShowPrgrs,
+ ); err != nil {
return err
}
nodePath := filepath.Join(ctx.Spool, node.Id.String())
diff --git a/src/tx_test.go b/src/tx_test.go
index 4827ad3f2dc657f1f0d0ec50b41a6f6b1a16700c66e47219b5fb3ca3772ac703..538b95153f8456d01825e9e679f05c6e07fd4a13180018c41aa8a465b100a22b 100644
--- a/src/tx_test.go
+++ b/src/tx_test.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/via.go b/src/via.go
index ff82b6e438a3eb8cf4e5f5e29f4c347d54ae3e7672c24437b7bff229740deb8c..ccf1f35cd8080d717125f6014bc9871bd1e57fc586519b763929e1d4c366bf52 100644
--- a/src/via.go
+++ b/src/via.go
@@ -1,6 +1,6 @@
/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev
+Copyright (C) 2016-2020 Sergey Matveev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by