/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2022 Sergey Matveev <stargrave@stargrave.org>
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
)
const (
- SeenSuffix = ".seen"
+ SeenDir = "seen"
)
+func jobPath2Seen(jobPath string) string {
+ return filepath.Join(filepath.Dir(jobPath), SeenDir, filepath.Base(jobPath))
+}
+
func newNotification(fromTo *FromToJSON, subject string, body []byte) io.Reader {
lines := []string{
"From: " + fromTo.From,
}
argsStr := strings.Join(append([]string{handle}, args...), " ")
les = append(les, LE{"Type", "exec"}, LE{"Dst", argsStr})
- cmdline, exists := sender.Exec[handle]
- if !exists || len(cmdline) == 0 {
+ cmdline := sender.Exec[handle]
+ if len(cmdline) == 0 {
err = errors.New("No handle found")
ctx.LogE(
"rx-no-handle", les, err,
} else {
cmd.Stdin = pipeR
}
- output, err := cmd.Output()
+ output, err := cmd.CombinedOutput()
if err != nil {
- ctx.LogE("rx-hande", les, err, func(les LEs) string {
+ les = append(les, LE{"Output", strings.Split(
+ strings.Trim(string(output), "\n"), "\n"),
+ })
+ ctx.LogE("rx-handle", les, err, func(les LEs) string {
return fmt.Sprintf(
"Tossing exec %s/%s (%s): %s: handling",
sender.Name, pktName,
return err
}
if len(sendmail) > 0 && ctx.NotifyExec != nil {
- notify, exists := ctx.NotifyExec[sender.Name+"."+handle]
- if !exists {
- notify, exists = ctx.NotifyExec["*."+handle]
+ notify := ctx.NotifyExec[sender.Name+"."+handle]
+ if notify == nil {
+ notify = ctx.NotifyExec["*."+handle]
}
- if exists {
+ if notify != nil {
cmd := exec.Command(
sendmail[0],
append(sendmail[1:], notify.To)...,
})
if !dryRun && jobPath != "" {
if doSeen {
- if fd, err := os.Create(jobPath + SeenSuffix); err == nil {
+ if err := ensureDir(filepath.Dir(jobPath), SeenDir); err != nil {
+ return err
+ }
+ if fd, err := os.Create(jobPath2Seen(jobPath)); err == nil {
fd.Close()
if err = DirSync(filepath.Dir(jobPath)); err != nil {
ctx.LogE("rx-dirsync", les, err, func(les LEs) string {
})
return err
} else if ctx.HdrUsage {
- os.Remove(jobPath + HdrSuffix)
+ os.Remove(JobPath2Hdr(jobPath))
}
}
return err
}
if err = bufW.Flush(); err != nil {
- tmp.Close() // #nosec G104
+ tmp.Close()
ctx.LogE("rx-flush", les, err, func(les LEs) string {
return fmt.Sprintf(
"Tossing file %s/%s (%s): %s: flushing",
})
return err
}
- if err = tmp.Sync(); err != nil {
- tmp.Close() // #nosec G104
- ctx.LogE("rx-sync", les, err, func(les LEs) string {
- return fmt.Sprintf(
- "Tossing file %s/%s (%s): %s: syncing",
- sender.Name, pktName,
- humanize.IBytes(pktSize), dst,
- )
- })
- return err
+ if !NoSync {
+ if err = tmp.Sync(); err != nil {
+ tmp.Close()
+ ctx.LogE("rx-sync", les, err, func(les LEs) string {
+ return fmt.Sprintf(
+ "Tossing file %s/%s (%s): %s: syncing",
+ sender.Name, pktName,
+ humanize.IBytes(pktSize), dst,
+ )
+ })
+ return err
+ }
}
if err = tmp.Close(); err != nil {
ctx.LogE("rx-close", les, err, func(les LEs) string {
if !dryRun {
if jobPath != "" {
if doSeen {
- if fd, err := os.Create(jobPath + SeenSuffix); err == nil {
+ if err := ensureDir(filepath.Dir(jobPath), SeenDir); err != nil {
+ return err
+ }
+ if fd, err := os.Create(jobPath2Seen(jobPath)); err == nil {
fd.Close()
if err = DirSync(filepath.Dir(jobPath)); err != nil {
ctx.LogE("rx-dirsync", les, err, func(les LEs) string {
})
return err
} else if ctx.HdrUsage {
- os.Remove(jobPath + HdrSuffix)
+ os.Remove(JobPath2Hdr(jobPath))
}
}
if len(sendmail) > 0 && ctx.NotifyFile != nil {
if !dryRun {
if jobPath != "" {
if doSeen {
- if fd, err := os.Create(jobPath + SeenSuffix); err == nil {
+ if err := ensureDir(filepath.Dir(jobPath), SeenDir); err != nil {
+ return err
+ }
+ if fd, err := os.Create(jobPath2Seen(jobPath)); err == nil {
fd.Close()
if err = DirSync(filepath.Dir(jobPath)); err != nil {
ctx.LogE("rx-dirsync", les, err, func(les LEs) string {
})
return err
} else if ctx.HdrUsage {
- os.Remove(jobPath + HdrSuffix)
+ os.Remove(JobPath2Hdr(jobPath))
}
}
if len(sendmail) > 0 && ctx.NotifyFreq != nil {
}
ctx.LogD("rx-tx", les, logMsg)
if !dryRun {
- if err = ctx.TxTrns(node, nice, int64(pktSize), pipeR); err != nil {
- ctx.LogE("rx", les, err, func(les LEs) string {
- return logMsg(les) + ": txing"
- })
- return err
+ if len(node.Via) == 0 {
+ if err = ctx.TxTrns(node, nice, int64(pktSize), pipeR); err != nil {
+ ctx.LogE("rx", les, err, func(les LEs) string {
+ return logMsg(les) + ": txing"
+ })
+ return err
+ }
+ } else {
+ via := node.Via[:len(node.Via)-1]
+ node = ctx.Neigh[*node.Via[len(node.Via)-1]]
+ node = &Node{Id: node.Id, Via: via, ExchPub: node.ExchPub}
+ pktTrns, err := NewPkt(PktTypeTrns, 0, nodeId[:])
+ if err != nil {
+ panic(err)
+ }
+ if _, _, err = ctx.Tx(
+ node,
+ pktTrns,
+ nice,
+ int64(pktSize), 0, MaxFileSize,
+ pipeR,
+ pktName,
+ nil,
+ ); err != nil {
+ ctx.LogE("rx", les, err, func(les LEs) string {
+ return logMsg(les) + ": txing"
+ })
+ return err
+ }
}
}
ctx.LogI("rx", les, func(les LEs) string {
})
if !dryRun && jobPath != "" {
if doSeen {
- if fd, err := os.Create(jobPath + SeenSuffix); err == nil {
+ if err := ensureDir(filepath.Dir(jobPath), SeenDir); err != nil {
+ return err
+ }
+ if fd, err := os.Create(jobPath2Seen(jobPath)); err == nil {
fd.Close()
if err = DirSync(filepath.Dir(jobPath)); err != nil {
ctx.LogE("rx-dirsync", les, err, func(les LEs) string {
})
return err
} else if ctx.HdrUsage {
- os.Remove(jobPath + HdrSuffix)
+ os.Remove(JobPath2Hdr(jobPath))
}
}
seenDir := filepath.Join(
ctx.Spool, nodeId.String(), AreaDir, area.Id.String(),
)
- seenPath := filepath.Join(seenDir, msgHash+SeenSuffix)
+ seenPath := filepath.Join(seenDir, msgHash)
logMsgNode := func(les LEs) string {
return fmt.Sprintf(
"%s: echoing to: %s", logMsg(les), node.Name,
seenDir := filepath.Join(
ctx.Spool, nodeId.String(), AreaDir, area.Id.String(),
)
- seenPath := filepath.Join(seenDir, msgHash+SeenSuffix)
+ seenPath := filepath.Join(seenDir, msgHash)
logMsgNode := func(les LEs) string {
return fmt.Sprintf("%s: echo to: %s", logMsg(les), node.Name)
}
})
continue
}
- if nodeId != sender.Id {
+ if nodeId != sender.Id && nodeId != pktEnc.Sender {
ctx.LogI("rx-area-echo", lesEcho, logMsgNode)
- if _, err = ctx.Tx(
- node, &pkt, nice, int64(pktSize), 0, fullPipeR, pktName, nil,
+ if _, _, err = ctx.Tx(
+ node,
+ &pkt,
+ nice,
+ int64(pktSize), 0, MaxFileSize,
+ fullPipeR,
+ pktName,
+ nil,
); err != nil {
ctx.LogE("rx-area", lesEcho, err, logMsgNode)
return err
seenDir := filepath.Join(
ctx.Spool, ctx.SelfId.String(), AreaDir, area.Id.String(),
)
- seenPath := filepath.Join(seenDir, msgHash+SeenSuffix)
+ seenPath := filepath.Join(seenDir, msgHash)
if _, err := os.Stat(seenPath); err == nil {
ctx.LogD("rx-area-seen", les, func(les LEs) string {
return logMsg(les) + ": already seen"
})
return err
} else if ctx.HdrUsage {
- os.Remove(jobPath + HdrSuffix)
+ os.Remove(JobPath2Hdr(jobPath))
}
}
return nil
nil,
)
if err != nil {
+ ctx.LogE("rx-area-pkt-enc-read2", les, err, logMsg)
pipeW.CloseWithError(err)
<-errs
return err
})
return err
} else if ctx.HdrUsage {
- os.Remove(jobPath + HdrSuffix)
+ os.Remove(JobPath2Hdr(jobPath))
}
}
isBad = true
continue
}
+ sender := ctx.Neigh[*job.PktEnc.Sender]
+ if sender == nil {
+ err := errors.New("unknown node")
+ ctx.LogE("rx-open", les, err, func(les LEs) string {
+ return fmt.Sprintf(
+ "Tossing %s/%s",
+ ctx.NodeName(job.PktEnc.Sender), pktName,
+ )
+ })
+ isBad = true
+ continue
+ }
errs := make(chan error, 1)
var sharedKey []byte
Retry:
pipeR,
pktName,
les,
- ctx.Neigh[*job.PktEnc.Sender],
+ sender,
job.PktEnc.Nice,
uint64(pktSizeWithoutEnc(job.Size)),
job.Path,
nice uint8,
doSeen, noFile, noFreq, noExec, noTrns, noArea bool,
) (chan struct{}, chan bool) {
+ dw, err := ctx.NewDirWatcher(
+ filepath.Join(ctx.Spool, nodeId.String(), string(TRx)),
+ time.Second,
+ )
+ if err != nil {
+ log.Fatalln(err)
+ }
finish := make(chan struct{})
badCode := make(chan bool)
go func() {
for {
select {
case <-finish:
+ dw.Close()
badCode <- bad
- break
- default:
+ return
+ case <-dw.C:
+ bad = !ctx.Toss(
+ nodeId, TRx, nice, false,
+ doSeen, noFile, noFreq, noExec, noTrns, noArea) || bad
}
- time.Sleep(time.Second)
- bad = !ctx.Toss(
- nodeId, TRx, nice, false,
- doSeen, noFile, noFreq, noExec, noTrns, noArea) || bad
}
}()
return finish, badCode