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