From: Sergey Matveev Date: Sun, 22 Dec 2019 18:13:32 +0000 (+0300) Subject: Merge branch 'develop' X-Git-Tag: v5.3.0^0 X-Git-Url: http://www.git.cypherpunks.ru/?a=commitdiff_plain;h=510478b83a2808262f7167fffe5296b489a2bf03;hp=421facfd8b67ace5107afad173123f48655eb6c1;p=nncp.git Merge branch 'develop' --- diff --git a/VERSION b/VERSION index 26d99a2..03f488b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.2.1 +5.3.0 diff --git a/doc/Makefile b/doc/Makefile index 205c2b4..c3af5d4 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -13,7 +13,7 @@ CSS != cat style.css 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 2606b6e..c4c6d01 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 2eb52ff..fd6c17d 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -24,6 +24,10 @@ Tarballs include all necessary required libraries: @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 a83ea31..0278b86 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -6,7 +6,7 @@ This manual is for NNCP (Node to Node copy) -- collection of utilities simplifying secure store-and-forward files and mail exchanging. -Copyright @copyright{} 2016-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 1c8497e..5db01d0 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 @@ Possibly NNCP package already exists for your distribution: @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 2e5d927..ba34716 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 6cdc998..9d9e877 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -3,6 +3,36 @@ 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 d6be2d9..ef00f63 100644 --- a/doc/sp.texi +++ b/doc/sp.texi @@ -61,6 +61,15 @@ just an unsigned integer telling what body structure follows. +------+ @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 461c95a..b86ee68 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 98532ae..5e7812d 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 d42954f..f118c0b 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 5e66e0a..d8ba2e8 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 @@ type Call struct { RxRate int TxRate int Addr *string - OnlineDeadline uint - MaxOnlineTime uint + OnlineDeadline time.Duration + MaxOnlineTime time.Duration } func (ctx *Ctx) CallNode( @@ -40,7 +41,7 @@ func (ctx *Ctx) CallNode( 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 615e382..f003dcb 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 @@ import ( "os" "path" "strconv" + "time" "github.com/gorhill/cronexpr" "github.com/hjson/hjson-go" @@ -116,13 +117,13 @@ type CfgJSON struct { 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { } 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { } 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { } 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { } 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { 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 @@ func NewNode(name string, yml NodeJSON) (*Node, error) { 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 @@ func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) { 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 @@ func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) { 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 @@ func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) { 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 @@ func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) { 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 @@ func NewNodeOur(yml *NodeOurJSON) (*NodeOur, error) { 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 4c1f542..ae5b80f 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 @@ func Check(src io.Reader, checksum []byte, sds SDS, showPrgrs bool) (bool, error 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 2e5fb9e..824f49a 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 0bca23f..7685428 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 @@ func main() { 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 @@ func main() { 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 @@ func main() { 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 @@ func main() { 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 @@ func main() { } } 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 @@ func main() { 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 0072e98..ae6bffe 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 @@ import ( "log" "os" "strings" + "time" "go.cypherpunks.ru/nncp/v5" ) @@ -55,8 +56,8 @@ func main() { 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 @@ func main() { 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 @@ func main() { 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 7297350..81c90c4 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 055b644..7cedca0 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 43d5b3e..b8eae7e 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 6f43b69..ff63826 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 77fae4a..252f79a 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 3fdba33..2d52fcf 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 @@ func (c InetdConn) SetWriteDeadline(t time.Time) error { } 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 @@ func performSP(ctx *nncp.Ctx, conn nncp.ConnDeadlined, nice uint8) { 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 @@ func main() { 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 805577e..ddd3ffd 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 9d975f7..9a69e6c 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 62a851a..1bbcf98 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 883d06f..2535b89 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 aaf0c2d..3f42cd2 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 75aaf5a..f39d5ac 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 @@ func process(ctx *nncp.Ctx, path string, keep, dryRun, stdout, dumpMeta bool) bo 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 @@ func process(ctx *nncp.Ctx, path string, keep, dryRun, stdout, dumpMeta bool) bo 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 31c0492..911db63 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 f058892..22eaca0 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 5cf0a93..89b94d9 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 df7acd3..1a2351d 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 @@ func main() { 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 @@ Tx: 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 @@ Tx: 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 19c7b9c..c1625a1 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 0616c84..e1fd012 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 c7a3543..eca5fae 100644 --- a/src/go.mod +++ b/src/go.mod @@ -9,10 +9,10 @@ require ( 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 a0803fc..2a006d9 100644 --- a/src/go.sum +++ b/src/go.sum @@ -17,19 +17,19 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN 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 8ac19ea..1eded3c 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 705bb7e..16c95bf 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 50e90f4..f87e6c6 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 @@ import ( "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 bc91043..a5bef48 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 9ff5b6d..93e4446 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 VersionGet() string { 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 65f5e9c..7bfd0ef 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 @@ type Node struct { 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 a5d8610..a250cee 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 8324ffb..6eb4ef2 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 c69ba96..d076b63 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 d071857..546979a 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 (pb ProgressBar) Kill() { func CopyProgressed( dst io.Writer, src io.Reader, + prgrsPrefix string, sds SDS, showPrgrs bool, ) (written int64, err error) { @@ -96,7 +96,7 @@ func CopyProgressed( written += int64(nw) if showPrgrs { sds["size"] = written - Progress(sds) + Progress(prgrsPrefix, sds) } } if ew != nil { @@ -118,13 +118,13 @@ func CopyProgressed( 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 @@ func Progress(sds SDS) { 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 fa853b0..1297c41 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 @@ import ( ) 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 @@ var ( noise.HashBLAKE2b, ) + DefaultDeadline = 10 * time.Second + PingTimeout = time.Minute + spWorkersGroup sync.WaitGroup ) @@ -65,6 +68,7 @@ const ( SPTypeFile SPType = iota SPTypeDone SPType = iota SPTypeHalt SPType = iota + SPTypePing SPType = iota ) type SPHead struct { @@ -114,8 +118,16 @@ func init() { 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 init() { 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 @@ type SPState struct { 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) NotAlive() bool { - if state.isDead { - return true +func (state *SPState) SetDead() { + state.Lock() + defer state.Unlock() + select { + case <-state.isDead: + // Already closed channel, dead + return + default: } - now := time.Now() - if state.maxOnlineTime > 0 && state.started.Add(time.Duration(state.maxOnlineTime)*time.Second).Before(now) { + close(state.isDead) + go func() { + for _ = range state.payloads { + } + }() + go func() { + for _ = range state.pings { + } + }() +} + +func (state *SPState) NotAlive() bool { + 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 @@ func (state *SPState) dirUnlock() { 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 @@ func (state *SPState) StartI(conn ConnDeadlined) error { } 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 @@ func (state *SPState) StartI(conn ConnDeadlined) error { } 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 @@ func (state *SPState) StartI(conn ConnDeadlined) error { } 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 @@ func (state *SPState) StartI(conn ConnDeadlined) error { if err != nil { state.Ctx.LogE("sp-start", sds, err, "") state.dirUnlock() - return err } return err } @@ -396,6 +439,7 @@ func (state *SPState) StartR(conn ConnDeadlined) error { 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 @@ func (state *SPState) StartR(conn ConnDeadlined) error { 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 @@ func (state *SPState) StartR(conn ConnDeadlined) error { } 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 @@ func (state *SPState) StartR(conn ConnDeadlined) error { 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 @@ func (state *SPState) StartR(conn ConnDeadlined) error { 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 @@ func (state *SPState) StartR(conn ConnDeadlined) error { err = state.StartWorkers(conn, infosPayloads, payload) if err != nil { state.dirUnlock() - return err } return err } @@ -489,9 +532,17 @@ func (state *SPState) StartR(conn ConnDeadlined) error { 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 @@ func (state *SPState) StartWorkers( ) 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 @@ func (state *SPState) StartWorkers( 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 @@ func (state *SPState) StartWorkers( ) 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 @@ func (state *SPState) StartWorkers( "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 @@ func (state *SPState) StartWorkers( )) 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 @@ func (state *SPState) StartWorkers( 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 @@ func (state *SPState) StartWorkers( 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 @@ func (state *SPState) StartWorkers( } 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 @@ func (state *SPState) StartWorkers( 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 @@ func (state *SPState) StartWorkers( ) 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) StartWorkers( 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 @@ func (state *SPState) ProcessSP(payload []byte) ([][]byte, error) { 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 @@ func (state *SPState) ProcessSP(payload []byte) ([][]byte, error) { 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 @@ func (state *SPState) ProcessSP(payload []byte) ([][]byte, error) { 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 @@ func (state *SPState) ProcessSP(payload []byte) ([][]byte, error) { } 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", @@ -989,6 +1089,9 @@ func (state *SPState) ProcessSP(payload []byte) ([][]byte, error) { ) return nil, BadPktType } + if head.Type != SPTypePing { + state.RxLastNonPing = state.RxLastSeen + } } if infosGot { var pkts int diff --git a/src/tmp.go b/src/tmp.go index 0784b99..32c3fdb 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 6abf278..0bedeca 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 @@ func (ctx *Ctx) Toss( 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 @@ func (ctx *Ctx) Toss( 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 3a6f29f..b6df326 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 67bb659..831cb6f 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 @@ func (ctx *Ctx) Tx( } 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 @@ func (ctx *Ctx) TxTrns(node *Node, nice uint8, size int64, src io.Reader) error 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 46e5b1e..9a16d9a 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 d8bdbbb..251af21 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