]> Cypherpunks.ru repositories - nncp.git/commitdiff
Generate ACKs during tossing
authorSergey Matveev <stargrave@stargrave.org>
Sun, 13 Aug 2023 18:31:21 +0000 (21:31 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 13 Aug 2023 19:53:10 +0000 (22:53 +0300)
22 files changed:
doc/ack.texi [new file with mode: 0644]
doc/call.texi
doc/cfg/neigh.texi
doc/cmd/nncp-ack.texi
doc/cmd/nncp-rm.texi
doc/cmd/nncp-toss.texi
doc/index.texi
doc/news.ru.texi
doc/news.texi
doc/spool.texi
src/call.go
src/cfg.go
src/cfgdir.go
src/cmd/nncp-ack/main.go
src/cmd/nncp-call/main.go
src/cmd/nncp-caller/main.go
src/cmd/nncp-daemon/main.go
src/cmd/nncp-rm/main.go
src/cmd/nncp-toss/main.go
src/nncp.go
src/node.go
src/toss.go

diff --git a/doc/ack.texi b/doc/ack.texi
new file mode 100644 (file)
index 0000000..085251b
--- /dev/null
@@ -0,0 +1,72 @@
+@node ACK
+@cindex ACKnowledgements
+@cindex packet acknowledgement
+@unnumbered ACKnowledgements
+
+There is possibility to explicitly acknowledge the receipt of the
+encrypted packet, by generating the reply of @code{ACK}-type which
+contains the packet identifier.
+
+ACK packets can be generated explicitly by @command{@ref{nncp-ack}}
+command, or during the tossing procedure if @option{-gen-ack} option
+is specified.
+
+General workflow with acknowledgement is following, assuming that
+Alice has some outbound packets for Bob:
+
+@itemize
+
+@item Transfer encrypted packets, without deleting them locally:
+
+@example
+alice$ nncp-xfer -keep -tx -node bob /mnt/shared
+@end example
+
+@item On Bob's side retrieve those packets:
+
+@example
+bob$ nncp-xfer -rx /mnt/shared
+@end example
+
+That will also check if copied packets checksum is not mismatched.
+
+@item Create ACK packets of received ones, saving the list of encrypted
+    ACK packets:
+
+@example
+bob$ nncp-ack -node alice 4>acks
+@end example
+
+@item Send those newly created packets back to Alice:
+
+@example
+bob$ nncp-xfer [-keep] -tx /mnt/shared
+@end example
+
+@item Remove them from outbound spool, because we expect no
+    acknowledgement for them:
+
+@example
+bob$ nncp-rm -node alice -pkt <acks
+@end example
+
+@item Get those acknowledgement packets and @ref{nncp-toss, toss} them:
+
+@example
+alice$ nncp-xfer -rx /mnt/shared
+alice$ nncp-toss
+@end example
+
+Each ACK packet will remove kept corresponding outbound packets, because
+Bob explicitly confirmed their receipt.
+
+@end itemize
+
+Similarly you can use it with @command{@ref{nncp-bundle}}, but do not
+forget that by default it does not do checksumming of the packets, so
+you should either use its @option{-check} option, or run
+@command{@ref{nncp-check}} after.
+
+If you generate ACK packet during the tossing, then the list of ACK
+packets is saved as empty files directly in the @ref{Spool, spool}.
+You can remove transferred ACK packets with @command{nncp-rm -ack}.
index 06566abc4a87c7a5c77e321e5a2c912bb84551ed..bb29b58bc8aa7acf9f9bb82a37f475ff39f9ccdd 100644 (file)
@@ -16,6 +16,7 @@ calls: [
 
         autotoss: true
         autotoss-doseen: true
+        autotoss-gen-ack: true
     }
     {
         cron: "30 * * * SAT,SUN"
@@ -88,10 +89,11 @@ Optional. Override @ref{CfgMaxOnlineTime, @emph{maxonlinetime}}
 configuration option when calling.
 
 @vindex autotoss
-@item autotoss, -doseen, -nofile, -nofreq, -noexec, -notrns
+@item autotoss, -doseen, -nofile, -nofreq, -noexec, -notrns, -noack, -gen-ack
 Optionally enable auto tossing: run tosser on node's spool every second
 during the call. You can control either are @file{seen/} files must be
-created, or skip any kind of packet processing.
+created, or skip any kind of packet processing, or enable @ref{ACK}
+packets generation.
 
 @vindex when-tx-exists
 @item when-tx-exists
index 7912fe31f9ef7298d0f36ebddb8d42cd6d7bb96a..9816c8d55c535dab9462af59bbd64c59bfa38bbc 100644 (file)
@@ -51,6 +51,10 @@ neigh: {
       chunked: 1024
       minsize: 2048
     }
+    ack: {
+      nice: FLASH
+      minsize: 2048
+    }
     via: ["alice"]
     rxrate: 10
     txrate: 20
@@ -114,6 +118,21 @@ NNCP_NICE=64 \
         transmission.
     @end table
 
+@vindex ack
+@anchor{CfgACK}
+@item ack
+    Options applied to automatically generated @ref{ACK} packets during tossing.
+
+    @table @code
+    @item nice
+        Use that @ref{Niceness, niceness} for generated packets (255 is used
+        otherwise).
+
+    @item minsize
+        If set, then apply @ref{OptMinSize, -minsize} option during file
+        transmission.
+    @end table
+
 @vindex via
 @anchor{CfgVia}
 @item via
index 2fc607788f654185ac9d24aa10589a7d3f0a3cb7..358822d089d8ce38181e5fbbe69d9088206ed0be 100644 (file)
@@ -1,5 +1,4 @@
 @node nncp-ack
-@cindex packet acknowledgement
 @pindex nncp-ack
 @section nncp-ack
 
@@ -11,68 +10,13 @@ $ nncp-ack [options] -node NODE -pkt PKT
 $ nncp-ack [@dots{}] 4>&1 >&2 | nncp-rm [@dots{}] -pkt
 @end example
 
-Send acknowledgement of successful @option{PKT} (Base32-encoded hash)
-packet receipt from @option{NODE} node. If no @option{-pkt} is
-specified, then acknowledge all packet in node's @code{rx} spool.
-If @option{-all} is specified, then do that for all nodes.
+Send @ref{ACK, acknowledgement} of successful @option{PKT}
+(Base32-encoded hash) packet receipt from @option{NODE} node. If no
+@option{-pkt} is specified, then acknowledge all packet in node's
+@code{rx} spool. If @option{-all} is specified, then do that for all
+nodes.
 
 That commands outputs list of created encrypted ACK packets
 (@code{NODE/PKT}) to @strong{4}th file descriptor. That output can be
 passed for example to @command{@ref{nncp-rm}} to remove them after
 transmission to not wait for acknowledgement and retransmission.
-
-General workflow with acknowledgement is following, assuming that
-Alice has some outbound packets for Bob:
-
-@itemize
-
-@item Transfer encrypted packets, without deleting them locally:
-
-@example
-alice$ nncp-xfer -keep -tx -node bob /mnt/shared
-@end example
-
-@item On Bob's side retrieve those packets:
-
-@example
-bob$ nncp-xfer -rx /mnt/shared
-@end example
-
-That will also check if copied packets checksum is not mismatched.
-
-@item Create ACK packets of received ones, saving the list of encrypted
-    ACK packets:
-
-@example
-bob$ nncp-ack -node alice 4>acks
-@end example
-
-@item Send those newly created packets back to Alice:
-
-@example
-bob$ nncp-xfer [-keep] -tx /mnt/shared
-@end example
-
-@item Remove them from outbound spool, because we expect no
-    acknowledgement for them:
-
-@example
-bob$ nncp-rm -node alice -pkt <acks
-@end example
-
-@item Get those acknowledgement packets and @ref{nncp-toss, toss} them:
-
-@example
-alice$ nncp-xfer -rx /mnt/shared
-alice$ nncp-toss
-@end example
-
-Each ACK packet will remove kept corresponding outbound packets, because
-Bob explicitly confirmed their receipt.
-
-@end itemize
-
-Similarly you can use it with @command{@ref{nncp-bundle}}, but do not
-forget that by default it does not do checksumming of the packets, so
-you should either use its @option{-check} option, or run
-@command{@ref{nncp-check}} after.
index 4444c3347dcd81a932bfcc77b89d44cf78f2d412..721502e17fe5911b1b5b1c4706e5ebc533deb2de 100644 (file)
@@ -10,7 +10,8 @@ $ nncp-rm [options] [-older X] @{-all|-node NODE@} -seen
 $ nncp-rm [options] [-older X] @{-all|-node NODE@} -nock
 $ nncp-rm [options] [-older X] @{-all|-node NODE@} -area
 $ nncp-rm [options] [-older X] @{-all|-node NODE@} @{-rx|-tx@} [-hdr]
-$ nncp-rm [options] [-older X] @{-all|-node NODE@} -pkt <<EOF
+$ nncp-rm [options] @{-all|-node NODE@} -pkt <<EOF
+$ nncp-rm [options] @{-all|-node NODE@} -ack
 PKT1
 PKT2
 NODEx/PKT3
index f3bbf650a7983c11c4df98137ff81c999c588b9d..3ba96494b4f8cd7f75f7e31413ab45d98144faba 100644 (file)
@@ -7,8 +7,8 @@ $ nncp-toss [options]
     [-node NODE]
     [-dryrun]
     [-cycle INT]
-    [-seen]
-    [-nofile] [-nofreq] [-noexec] [-notrns] [-noarea]
+    [-seen] [-gen-ack]
+    [-nofile] [-nofreq] [-noexec] [-notrns] [-noarea] [-noack]
 @end example
 
 Perform "tossing" operation on all inbound packets. This is the tool
@@ -31,4 +31,9 @@ already seen, processed and tossed. This is helpful to prevent
 duplicates.
 
 @option{-nofile}, @option{-nofreq}, @option{-noexec}, @option{-notrns},
-@option{-noarea} options allow disabling any kind of packet types processing.
+@option{-noarea}, @option{-noack} options allow disabling any kind of
+packet types processing.
+
+@option{-gen-ack} option tells to automatically generate @ref{ACK}
+outbound packets when tossing each packet, saving corresponding list of
+generated packets inside the special directory in the @ref{ACKFile, spool}.
index 007cc154a6dd06a19e74058044fd16ad33f610d6..a5e327dfafff69f95e89d85a6577337efd259958 100644 (file)
@@ -83,6 +83,7 @@ There are also articles about its usage outside this website:
 @include niceness.texi
 @include chunked.texi
 @include bundles.texi
+@include ack.texi
 @include spool.texi
 @include log.texi
 @include pkt/index.texi
index 31fbf580f37cec42bd172894e4b61a6039a12751..0c5dd4ab32829888d2f2827bda9060d908dea568 100644 (file)
@@ -1,13 +1,31 @@
 @node Новости
 @section Новости
 
-@node Релиз 8.8.4
-@subsection Релиз 8.8.4
+@node Релиз 8.9.0
+@subsection Релиз 8.9.0
 @itemize
 
 @item
-Избавиться от @command{redo} системы сборки при установке, так как по сути
-нет зависимостей, только компиляция Go кода.
+@command{nncp-toss} команда имеет @option{-gen-ack} опцию.
+@command{nncp-daemon}, @command{nncp-caller}, @command{nncp-call}
+команды имеют @option{-autotoss-gen-ack} опцию. Они автоматически
+генерируют ACK пакеты и сохраняют соответствующие @file{spoo/tx/ack/}
+ссылки на них, чтобы их можно было удалить после передачи.
+
+@item
+@code{autotoss-gen-ack} появился в конфигурации call.
+@code{ack} секция появилась в конфигурации ноды.
+
+@item
+@command{nncp-rm} команда имеет @option{-ack} опцию для удаления пакетов
+на которые ссылаются @file{spool/tx/ack/} файлы созданные во время toss.
+
+@item
+@command{redo} система сборки более не требуется при установке, так как
+по сути нет зависимостей, только компиляция Go кода.
+
+@item
+Обновлены некоторые зависимости.
 
 @end itemize
 
index a7ec96118c51eb1af61c1175dc384c5c04bde554..664f176685a737721e1bc6e1a1fc1ca125b15564 100644 (file)
@@ -4,14 +4,32 @@
 
 See also this page @ref{Новости, on russian}.
 
-@node Release 8_8_4
-@section Release 8.8.4
+@node Release 8_9_0
+@section Release 8.9.0
 @itemize
 
+@item
+@command{nncp-toss} command has @option{-gen-ack} option.
+@command{nncp-daemon}, @command{nncp-caller}, @command{nncp-call}
+commands have @option{-autotoss-gen-ack} option. They automatically
+generate ACK packets and store corresponding @file{spool/tx/ack/}
+references to them, to be able to remove them after the transfer.
+
+@item
+@code{autotoss-gen-ack} appeared in call configuration.
+@code{ack} section appeared in neighbour configuration.
+
+@item
+@command{nncp-rm} command has @option{-ack} option to remove packets
+referenced by stored @file{spool/tx/ack/} files generated during tossing.
+
 @item
 Get rid of @command{redo} build system during installation, as there are
 virtually none dependencies, just only compilation of the Go code.
 
+@item
+Updated some dependencies.
+
 @end itemize
 
 @node Release 8_8_3
index c7ddb31a0e5910f31dddff247aa36bec3732d4e3..3a839760beaa1d9764a89df81c0256bb3c2b34bd 100644 (file)
@@ -86,4 +86,14 @@ that will recreate them. In many cases many @file{hdr/} files will be
 allocated more or less linearly on the disk, decreasing listing time
 even more.
 
+@cindex ack files
+@anchor{ACKFile}
+@item tx/ack/LYT64MWSNDK34CVYOO7TA6ZCJ3NWI2OUDBBMX2A4QWF34FIRY4DQ
+If tossing was performed with @option{-gen-ack} option, then for each
+generated @ref{ACK} packet there will be corresponding empty @file{ack/}
+file. ACK outbound packets needs to be deleted after the transmission,
+but since they are stored encrypted in the spool, there needs to be some
+kind of knowledge what packets are ACK ones. Both ACK and corresponding
+@file{ack/} files are removed by @command{@ref{nncp-rm} -ack} command.
+
 @end table
index 50f1de1a71dc0ce399e439ee902566340394ad37..5bb5d0e08209ffdf1e82d03852ed41589522bc7e 100644 (file)
@@ -51,6 +51,7 @@ type Call struct {
        AutoTossNoTrns bool
        AutoTossNoArea bool
        AutoTossNoACK  bool
+       AutoTossGenACK bool
 }
 
 func (ctx *Ctx) CallNode(
index a57277e88be3462aee9c4dcc4ab1d1282d07cd62..8a7cb34ddc2099fea8f92b35333bad5d8a762f2d 100644 (file)
@@ -56,6 +56,7 @@ type NodeJSON struct {
        Incoming *string             `json:"incoming,omitempty"`
        Exec     map[string][]string `json:"exec,omitempty"`
        Freq     *NodeFreqJSON       `json:"freq,omitempty"`
+       ACK      *NodeACKJSON        `json:"ack,omitempty"`
        Via      []string            `json:"via,omitempty"`
        Calls    []CallJSON          `json:"calls,omitempty"`
 
@@ -74,6 +75,11 @@ type NodeFreqJSON struct {
        MaxSize *uint64 `json:"maxsize,omitempty"`
 }
 
+type NodeACKJSON struct {
+       MinSize *uint64 `json:"minsize,omitempty"`
+       Nice    *string `json:"nice,omitempty"`
+}
+
 type CallJSON struct {
        Cron           string  `json:"cron"`
        Nice           *string `json:"nice,omitempty"`
@@ -94,6 +100,8 @@ type CallJSON struct {
        AutoTossNoExec bool `json:"autotoss-noexec,omitempty"`
        AutoTossNoTrns bool `json:"autotoss-notrns,omitempty"`
        AutoTossNoArea bool `json:"autotoss-noarea,omitempty"`
+       AutoTossNoACK  bool `json:"autotoss-noack,omitempty"`
+       AutoTossGenACK bool `json:"autotoss-gen-ack,omitempty"`
 }
 
 type NodeOurJSON struct {
@@ -220,6 +228,20 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) {
                }
        }
 
+       ackNice := uint8(255)
+       var ackMinSize int64
+       if cfg.ACK != nil {
+               if cfg.ACK.Nice != nil {
+                       ackNice, err = NicenessParse(*cfg.ACK.Nice)
+                       if err != nil {
+                               return nil, err
+                       }
+               }
+               if cfg.ACK.MinSize != nil {
+                       ackMinSize = int64(*cfg.ACK.MinSize) * 1024
+               }
+       }
+
        defRxRate := 0
        if cfg.RxRate != nil && *cfg.RxRate > 0 {
                defRxRate = *cfg.RxRate
@@ -317,6 +339,8 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) {
                call.AutoTossNoExec = callCfg.AutoTossNoExec
                call.AutoTossNoTrns = callCfg.AutoTossNoTrns
                call.AutoTossNoArea = callCfg.AutoTossNoArea
+               call.AutoTossNoACK = callCfg.AutoTossNoACK
+               call.AutoTossGenACK = callCfg.AutoTossGenACK
 
                calls = append(calls, &call)
        }
@@ -332,6 +356,8 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) {
                FreqChunked:    freqChunked,
                FreqMinSize:    freqMinSize,
                FreqMaxSize:    freqMaxSize,
+               ACKNice:        ackNice,
+               ACKMinSize:     ackMinSize,
                Calls:          calls,
                Addrs:          cfg.Addrs,
                RxRate:         defRxRate,
index f9378c8b34c6abd94294a44fc4842f73c209e052..fc36636c051990ef8e6e382992e6ebb7f094f332 100644 (file)
@@ -260,6 +260,24 @@ func CfgToDir(dst string, cfg *CfgJSON) (err error) {
                        }
                }
 
+               if n.ACK != nil {
+                       if err = cfgDirMkdir(dst, "neigh", name, "ack"); err != nil {
+                               return
+                       }
+                       if err = cfgDirSave(
+                               n.ACK.MinSize,
+                               dst, "neigh", name, "ack", "minsize",
+                       ); err != nil {
+                               return
+                       }
+                       if err = cfgDirSave(
+                               n.ACK.Nice,
+                               dst, "neigh", name, "ack", "nice",
+                       ); err != nil {
+                               return
+                       }
+               }
+
                if len(n.Via) > 0 {
                        if err = cfgDirSave(
                                strings.Join(n.Via, "\n"),
@@ -372,6 +390,16 @@ func CfgToDir(dst string, cfg *CfgJSON) (err error) {
                                        return
                                }
                        }
+                       if call.AutoTossNoACK {
+                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-noack"); err != nil {
+                                       return
+                               }
+                       }
+                       if call.AutoTossGenACK {
+                               if err = cfgDirTouch(dst, "neigh", name, "calls", is, "autotoss-gen-ack"); err != nil {
+                                       return
+                               }
+                       }
                }
        }
 
@@ -689,6 +717,23 @@ func DirToCfg(src string) (*CfgJSON, error) {
                        }
                }
 
+               if cfgDirExists(src, "neigh", n, "ack") {
+                       node.ACK = &NodeACKJSON{}
+                       i64, err := cfgDirLoadIntOpt(src, "neigh", n, "ack", "minsize")
+                       if err != nil {
+                               return nil, err
+                       }
+                       if i64 != nil {
+                               i := uint64(*i64)
+                               node.ACK.MinSize = &i
+                       }
+                       if node.ACK.Nice, err = cfgDirLoadOpt(
+                               src, "neigh", n, "ack", "nice",
+                       ); err != nil {
+                               return nil, err
+                       }
+               }
+
                via, err := cfgDirLoadOpt(src, "neigh", n, "via")
                if err != nil {
                        return nil, err
@@ -856,6 +901,12 @@ func DirToCfg(src string) (*CfgJSON, error) {
                        if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-noarea") {
                                call.AutoTossNoArea = true
                        }
+                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-noack") {
+                               call.AutoTossNoACK = true
+                       }
+                       if cfgDirExists(src, "neigh", n, "calls", is, "autotoss-gen-ack") {
+                               call.AutoTossGenACK = true
+                       }
                        node.Calls = append(node.Calls, call)
                }
                cfg.Neigh[n] = node
index 7342c848e9e0e4dc0e8ef0a51cec0b6655f30893..18a6f4be359e26bb9be55b5394b982c0fbc5bb31 100644 (file)
@@ -47,7 +47,7 @@ func main() {
                cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
                niceRaw = flag.String("nice", nncp.NicenessFmt(nncp.DefaultNiceFreq),
                        "Outbound packet niceness")
-               minSizeRaw  = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
+               minSizeRaw  = flag.Int64("minsize", -1, "Minimal required resulting packet size, in KiB")
                viaOverride = flag.String("via", "", "Override Via path to destination node (ignored with -all)")
                spoolPath   = flag.String("spool", "", "Override path to spool")
                logPath     = flag.String("log", "", "Override path to logfile")
@@ -94,7 +94,6 @@ func main() {
        }
 
        ctx.Umask()
-       minSize := int64(*minSizeRaw) * 1024
 
        var nodes []*nncp.Node
        if *nodesRaw != "" {
@@ -130,6 +129,14 @@ func main() {
                        os.Exit(1)
                }
                nncp.ViaOverride(*viaOverride, ctx, nodes[0])
+
+               var minSize int64
+               if *minSizeRaw < 0 {
+                       minSize = nodes[0].ACKMinSize
+               } else if *minSizeRaw > 0 {
+                       minSize = *minSizeRaw * 1024
+               }
+
                pktName, err := ctx.TxACK(nodes[0], nice, *pktRaw, minSize)
                if err != nil {
                        log.Fatalln(err)
@@ -140,6 +147,12 @@ func main() {
 
        isBad := false
        for _, node := range nodes {
+               var minSize int64
+               if *minSizeRaw < 0 {
+                       minSize = node.ACKMinSize
+               } else if *minSizeRaw > 0 {
+                       minSize = *minSizeRaw * 1024
+               }
                for job := range ctx.Jobs(node.Id, nncp.TRx) {
                        pktName := filepath.Base(job.Path)
                        sender := ctx.Neigh[*job.PktEnc.Sender]
index a684c98ca47103cc8caa82b206239b3fd21ba89f..23b6fb9d5a91378190b86597b7b3ebc474a87d3c 100644 (file)
@@ -81,6 +81,8 @@ func main() {
                        "Do not process \"area\" packets during tossing")
                autoTossNoACK = flag.Bool("autotoss-noack", false,
                        "Do not process \"ack\" packets during tossing")
+               autoTossGenACK = flag.Bool("autotoss-gen-ack", false,
+                       "Generate ACK packets")
        )
        log.SetFlags(log.Lshortfile)
        flag.Usage = usage
@@ -229,6 +231,7 @@ func main() {
                                NoTrns: *autoTossNoTrns,
                                NoArea: *autoTossNoArea,
                                NoACK:  *autoTossNoACK,
+                               GenACK: *autoTossGenACK,
                        },
                )
        }
index 08c4afafa7ea9115626dfdcbf3fca65dca90a00d..3eff4d2a99a2fff62367d43b2b3d4abd25795c5a 100644 (file)
@@ -67,6 +67,8 @@ func main() {
                        "Do not process \"area\" packets during tossing")
                autoTossNoACK = flag.Bool("autotoss-noack", false,
                        "Do not process \"ack\" packets during tossing")
+               autoTossGenACK = flag.Bool("autotoss-gen-ack", false,
+                       "Generate ACK packets")
        )
        log.SetFlags(log.Lshortfile)
        flag.Usage = usage
@@ -229,6 +231,7 @@ func main() {
                                                                        NoTrns: call.AutoTossNoTrns || *autoTossNoTrns,
                                                                        NoArea: call.AutoTossNoArea || *autoTossNoArea,
                                                                        NoACK:  call.AutoTossNoACK || *autoTossNoACK,
+                                                                       GenACK: call.AutoTossGenACK || *autoTossGenACK,
                                                                },
                                                        )
                                                }
index f4bf2c30a7204930f5e07e21b117452297072440..33fffa764e107ddd7083c7cc54430c0d28e04c92 100644 (file)
@@ -167,6 +167,8 @@ func main() {
                        "Do not process \"area\" packets during tossing")
                autoTossNoACK = flag.Bool("autotoss-noack", false,
                        "Do not process \"ack\" packets during tossing")
+               autoTossGenACK = flag.Bool("autotoss-gen-ack", false,
+                       "Generate ACK packets")
        )
        log.SetFlags(log.Lshortfile)
        flag.Usage = usage
@@ -228,6 +230,7 @@ func main() {
                                        NoTrns: *autoTossNoTrns,
                                        NoArea: *autoTossNoArea,
                                        NoACK:  *autoTossNoACK,
+                                       GenACK: *autoTossGenACK,
                                },
                        )
                }
@@ -317,6 +320,7 @@ func main() {
                                                NoTrns: *autoTossNoTrns,
                                                NoArea: *autoTossNoArea,
                                                NoACK:  *autoTossNoACK,
+                                               GenACK: *autoTossGenACK,
                                        },
                                )
                        }
index b1d15249047251dc183f9934fafaa345c8e4c046..18931ebbcbe3fd3f9ad0196fcbd561e538eb38e1 100644 (file)
@@ -44,7 +44,8 @@ func usage() {
        fmt.Fprintf(os.Stderr, "       %s [options] [-older X] {-all|-node NODE} -nock\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] [-older X] {-all|-node NODE} -area\n", os.Args[0])
        fmt.Fprintf(os.Stderr, "       %s [options] [-older X] {-all|-node NODE} {-rx|-tx} [-hdr]\n", os.Args[0])
-       fmt.Fprintf(os.Stderr, "       %s [options] [-older X] {-all|-node NODE} -pkt < ...\n", os.Args[0])
+       fmt.Fprintf(os.Stderr, "       %s [options] {-all|-node NODE} -pkt < ...\n", os.Args[0])
+       fmt.Fprintf(os.Stderr, "       %s [options] {-all|-node NODE} -ack\n", os.Args[0])
        fmt.Fprintln(os.Stderr, "-older option's time units are: (s)econds, (m)inutes, (h)ours, (d)ays")
        fmt.Fprintln(os.Stderr, "Options:")
        flag.PrintDefaults()
@@ -67,6 +68,7 @@ func main() {
                older     = flag.String("older", "", "XXX{smhd}: only older than XXX number of time units")
                dryRun    = flag.Bool("dryrun", false, "Do not actually remove files")
                doPkt     = flag.Bool("pkt", false, "Remove only that packets")
+               doACK     = flag.Bool("ack", false, "Remove ACK packets from outbound")
                spoolPath = flag.String("spool", "", "Override path to spool")
                quiet     = flag.Bool("quiet", false, "Print only errors")
                debug     = flag.Bool("debug", false, "Print debug messages")
@@ -393,5 +395,46 @@ func main() {
                                log.Fatalln("Can not remove:", err)
                        }
                }
+               if *doACK {
+                       dirPath := filepath.Join(
+                               ctx.Spool, node.Id.String(), string(nncp.TTx), nncp.ACKDir)
+                       dir, err := os.Open(dirPath)
+                       if err != nil {
+                               continue
+                       }
+                       for {
+                               fis, err := dir.ReadDir(1 << 10)
+                               if err != nil {
+                                       if err == io.EOF {
+                                               break
+                                       }
+                                       log.Fatalln("Can not read directory:", err)
+                               }
+                               for _, fi := range fis {
+                                       for _, pth := range []string{
+                                               filepath.Join(
+                                                       ctx.Spool,
+                                                       node.Id.String(),
+                                                       string(nncp.TTx),
+                                                       fi.Name(),
+                                               ),
+                                               filepath.Join(dirPath, fi.Name()),
+                                       } {
+                                               if err = os.Remove(pth); err == nil {
+                                                       ctx.LogI(
+                                                               "rm",
+                                                               nncp.LEs{{K: "File", V: pth}},
+                                                               func(les nncp.LEs) string {
+                                                                       return fmt.Sprintf("File %s: removed", pth)
+                                                               },
+                                                       )
+                                               } else if !errors.Is(err, fs.ErrNotExist) {
+                                                       log.Fatalln("Can not remove:", pth, ":", err)
+                                               }
+                                       }
+                               }
+                       }
+                       dir.Close()
+               }
        }
 }
index dad1d3ee979120fc6a21c64bec94a7237b02f912..24b50e26d243d92952a0f2a0cd08304ebe290d79 100644 (file)
@@ -49,6 +49,7 @@ func main() {
                noTrns    = flag.Bool("notrns", false, "Do not process \"transitional\" packets")
                noArea    = flag.Bool("noarea", false, "Do not process \"area\" packets")
                noACK     = flag.Bool("noack", false, "Do not process \"ack\" packets")
+               genACK    = flag.Bool("gen-ack", false, "Generate ACK packets")
                spoolPath = flag.String("spool", "", "Override path to spool")
                logPath   = flag.String("log", "", "Override path to logfile")
                quiet     = flag.Bool("quiet", false, "Print only errors")
@@ -118,6 +119,7 @@ func main() {
                                        NoTrns: *noTrns,
                                        NoArea: *noArea,
                                        NoACK:  *noACK,
+                                       GenACK: *genACK,
                                },
                        ) || isBad
                        if nodeId == *ctx.SelfId {
@@ -174,6 +176,7 @@ func main() {
                                NoTrns: *noTrns,
                                NoArea: *noArea,
                                NoACK:  *noACK,
+                               GenACK: *genACK,
                        },
                )
                if *nodeId == *ctx.SelfId {
index dc64ffc14d0263a559a5663afe4423b880a534d5..d52137260f20a16fb5edc9ba2f7c325b9b114d6f 100644 (file)
@@ -41,7 +41,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.`
 )
 
 var (
-       Version string = "8.8.4"
+       Version string = "8.9.0"
 
        Base32Codec *base32.Encoding = base32.StdEncoding.WithPadding(base32.NoPadding)
 )
index d71fd294d9ef6d97c903ae83427f8d2edddaddf9..0587fbc2b90c2234d2911c80e2adc8ebab9e2e3c 100644 (file)
@@ -50,6 +50,8 @@ type Node struct {
        FreqChunked    int64
        FreqMinSize    int64
        FreqMaxSize    int64
+       ACKNice        uint8
+       ACKMinSize     int64
        Via            []*NodeId
        Addrs          map[string]string
        RxRate         int
index d365e2efd5c47c172f607bee0f8919817da83189..c4710494bc1a56d8ba5d785f89e0ce44ba23eb29 100644 (file)
@@ -44,6 +44,7 @@ import (
 
 const (
        SeenDir = "seen"
+       ACKDir  = "ack"
 )
 
 type TossOpts struct {
@@ -56,6 +57,7 @@ type TossOpts struct {
        NoTrns bool
        NoArea bool
        NoACK  bool
+       GenACK bool
 }
 
 func jobPath2Seen(jobPath string) string {
@@ -123,6 +125,33 @@ func jobProcess(
                        humanize.IBytes(pktSize),
                )
        })
+       if opts.GenACK && pkt.Type != PktTypeACK {
+               newPktName, err := ctx.TxACK(
+                       sender, sender.ACKNice, pktName, sender.ACKMinSize,
+               )
+               if err != nil {
+                       ctx.LogE("rx-unmarshal", les, err, func(les LEs) string {
+                               return fmt.Sprintf("Tossing %s/%s: generating ACK", sender.Name, pktName)
+                       })
+                       return err
+               }
+               ackDir := filepath.Join(ctx.Spool, sender.Id.String(), string(TTx), ACKDir)
+               os.MkdirAll(ackDir, os.FileMode(0777))
+               if fd, err := os.Create(filepath.Join(ackDir, newPktName)); err == nil {
+                       fd.Close()
+                       if err = DirSync(ackDir); err != nil {
+                               ctx.LogE("rx-genack", les, err, func(les LEs) string {
+                                       return fmt.Sprintf("Tossing %s/%s: genACK", sender.Name, pktName)
+                               })
+                               return err
+                       }
+               } else {
+                       ctx.LogE("rx-genack", les, err, func(les LEs) string {
+                               return fmt.Sprintf("Tossing %s/%s: genACK", sender.Name, pktName)
+                       })
+                       return err
+               }
+       }
        switch pkt.Type {
        case PktTypeExec, PktTypeExecFat:
                if opts.NoExec {