package main
import (
+ "bufio"
+ "errors"
"flag"
"fmt"
+ "io"
"log"
"os"
"path/filepath"
+ "strings"
+ xdr "github.com/davecgh/go-xdr/xdr2"
"go.cypherpunks.ru/nncp/v8"
)
func usage() {
fmt.Fprintf(os.Stderr, nncp.UsageHeader())
fmt.Fprintf(os.Stderr, "nncp-ack -- send packet receipt acknowledgement\n\n")
- fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE [PKT|rx]\nOptions:\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, "Usage: %s [options] -all\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, "Usage: %s [options] -node NODE[,...]\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, "Usage: %s [options] -node NODE -pkt PKT\n", os.Args[0])
+ fmt.Fprintln(os.Stderr, "Options:")
flag.PrintDefaults()
}
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")
- viaOverride = flag.String("via", "", "Override Via path to destination node")
+ 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")
+ doAll = flag.Bool("all", false, "ACK all rx packet for all nodes")
+ nodesRaw = flag.String("node", "", "ACK rx packets for that node")
+ pktRaw = flag.String("pkt", "", "ACK only that packet")
quiet = flag.Bool("quiet", false, "Print only errors")
showPrgrs = flag.Bool("progress", false, "Force progress showing")
omitPrgrs = flag.Bool("noprogress", false, "Omit progress showing")
fmt.Println(nncp.VersionGet())
return
}
- if flag.NArg() != 2 {
- usage()
- os.Exit(1)
- }
nice, err := nncp.NicenessParse(*niceRaw)
if err != nil {
log.Fatalln(err)
log.Fatalln("Config lacks private keys")
}
- node, err := ctx.FindNode(flag.Arg(0))
- if err != nil {
- log.Fatalln("Invalid NODE specified:", err)
- }
-
- nncp.ViaOverride(*viaOverride, ctx, node)
ctx.Umask()
minSize := int64(*minSizeRaw) * 1024
- if flag.Arg(1) == string(nncp.TRx) {
+ var nodes []*nncp.Node
+ if *nodesRaw != "" {
+ for _, nodeRaw := range strings.Split(*nodesRaw, ",") {
+ node, err := ctx.FindNode(nodeRaw)
+ if err != nil {
+ log.Fatalln("Invalid -node specified:", err)
+ }
+ nodes = append(nodes, node)
+ }
+ }
+ if *doAll {
+ if len(nodes) != 0 {
+ usage()
+ os.Exit(1)
+ }
+ for _, node := range ctx.Neigh {
+ nodes = append(nodes, node)
+ }
+ } else if len(nodes) == 0 {
+ usage()
+ os.Exit(1)
+ }
+
+ if *pktRaw != "" {
+ if len(nodes) != 1 {
+ usage()
+ os.Exit(1)
+ }
+ nncp.ViaOverride(*viaOverride, ctx, nodes[0])
+ if err = ctx.TxACK(nodes[0], nice, *pktRaw, minSize); err != nil {
+ log.Fatalln(err)
+ }
+ return
+ }
+
+ isBad := false
+ for _, node := range nodes {
for job := range ctx.Jobs(node.Id, nncp.TRx) {
pktName := filepath.Base(job.Path)
+ sender := ctx.Neigh[*job.PktEnc.Sender]
+ les := nncp.LEs{
+ {K: "Node", V: job.PktEnc.Sender},
+ {K: "Pkt", V: pktName},
+ }
+ logMsg := func(les nncp.LEs) string {
+ return fmt.Sprintf(
+ "ACKing %s/%s",
+ ctx.NodeName(job.PktEnc.Sender), pktName,
+ )
+ }
+ if sender == nil {
+ err := errors.New("unknown node")
+ ctx.LogE("ack-read", les, err, logMsg)
+ isBad = true
+ continue
+ }
+ fd, err := os.Open(job.Path)
+ if err != nil {
+ ctx.LogE("ack-read-open", les, err, func(les nncp.LEs) string {
+ return logMsg(les) + ": opening" + job.Path
+ })
+ isBad = true
+ continue
+ }
+ pktEnc, _, err := ctx.HdrRead(fd)
+ if err != nil {
+ fd.Close()
+ ctx.LogE("ack-read-read", les, err, func(les nncp.LEs) string {
+ return logMsg(les) + ": reading" + job.Path
+ })
+ isBad = true
+ continue
+ }
+ switch pktEnc.Magic {
+ case nncp.MagicNNCPEv1.B:
+ err = nncp.MagicNNCPEv1.TooOld()
+ case nncp.MagicNNCPEv2.B:
+ err = nncp.MagicNNCPEv2.TooOld()
+ case nncp.MagicNNCPEv3.B:
+ err = nncp.MagicNNCPEv3.TooOld()
+ case nncp.MagicNNCPEv4.B:
+ err = nncp.MagicNNCPEv4.TooOld()
+ case nncp.MagicNNCPEv5.B:
+ err = nncp.MagicNNCPEv5.TooOld()
+ case nncp.MagicNNCPEv6.B:
+ default:
+ err = errors.New("is not an encrypted packet")
+ }
+ if err != nil {
+ fd.Close()
+ ctx.LogE("ack-read-magic", les, err, logMsg)
+ isBad = true
+ continue
+ }
+ if _, err = fd.Seek(0, io.SeekStart); err != nil {
+ fd.Close()
+ ctx.LogE("ack-read-seek", les, err, func(les nncp.LEs) string {
+ return logMsg(les) + ": seeking"
+ })
+ isBad = true
+ continue
+ }
+ pipeR, pipeW := io.Pipe()
+ go nncp.PktEncRead(ctx.Self, ctx.Neigh, bufio.NewReader(fd), pipeW, true, nil)
+ var pkt nncp.Pkt
+ _, err = xdr.Unmarshal(pipeR, &pkt)
+ fd.Close()
+ pipeW.Close()
+ if err != nil {
+ ctx.LogE("ack-read-unmarshal", les, err, func(les nncp.LEs) string {
+ return logMsg(les) + ": unmarshal"
+ })
+ isBad = true
+ continue
+ }
+ if pkt.Type == nncp.PktTypeACK {
+ ctx.LogI("ack-read-if-ack", les, func(les nncp.LEs) string {
+ return logMsg(les) + ": it is ACK, skipping"
+ })
+ continue
+ }
if err = ctx.TxACK(node, nice, pktName, minSize); err != nil {
log.Fatalln(err)
}
}
- } else {
- if err = ctx.TxACK(node, nice, flag.Arg(1), minSize); err != nil {
- log.Fatalln(err)
- }
+ }
+ if isBad {
+ os.Exit(1)
}
}