]> Cypherpunks.ru repositories - nncp.git/blob - src/check.go
Note about buildability with 1.22
[nncp.git] / src / check.go
1 // NNCP -- Node to Node copy, utilities for store-and-forward data exchange
2 // Copyright (C) 2016-2024 Sergey Matveev <stargrave@stargrave.org>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 package nncp
17
18 import (
19         "bufio"
20         "bytes"
21         "errors"
22         "fmt"
23         "io"
24         "os"
25         "path/filepath"
26 )
27
28 const NoCKSuffix = ".nock"
29
30 func Check(
31         src io.Reader,
32         size int64,
33         checksum []byte,
34         les LEs,
35         showPrgrs bool,
36 ) (bool, error) {
37         hsh := MTHNew(size, 0)
38         if _, err := CopyProgressed(
39                 hsh,
40                 bufio.NewReaderSize(src, MTHBlockSize),
41                 "check", les, showPrgrs,
42         ); err != nil {
43                 return false, err
44         }
45         return bytes.Equal(hsh.Sum(nil), checksum), nil
46 }
47
48 func (ctx *Ctx) checkXxIsBad(nodeId *NodeId, xx TRxTx) bool {
49         isBad := false
50         for job := range ctx.Jobs(nodeId, xx) {
51                 pktName := Base32Codec.EncodeToString(job.HshValue[:])
52                 les := LEs{
53                         {"XX", string(xx)},
54                         {"Node", nodeId},
55                         {"Pkt", pktName},
56                         {"FullSize", job.Size},
57                 }
58                 logMsg := func(les LEs) string {
59                         return fmt.Sprintf("Checking: %s/%s/%s", nodeId, string(xx), pktName)
60                 }
61                 fd, err := os.Open(job.Path)
62                 if err != nil {
63                         ctx.LogE("checking", les, err, logMsg)
64                         return true
65                 }
66                 gut, err := Check(fd, job.Size, job.HshValue[:], les, ctx.ShowPrgrs)
67                 fd.Close()
68                 if err != nil {
69                         ctx.LogE("checking", les, err, logMsg)
70                         return true
71                 }
72                 if !gut {
73                         isBad = true
74                         ctx.LogE("checking", les, errors.New("bad"), logMsg)
75                 }
76         }
77         return isBad
78 }
79
80 func (ctx *Ctx) Check(nodeId *NodeId) bool {
81         return !(ctx.checkXxIsBad(nodeId, TRx) || ctx.checkXxIsBad(nodeId, TTx))
82 }
83
84 func (ctx *Ctx) CheckNoCK(nodeId *NodeId, hshValue *[MTHSize]byte, mth MTH) (int64, error) {
85         dirToSync := filepath.Join(ctx.Spool, nodeId.String(), string(TRx))
86         pktName := Base32Codec.EncodeToString(hshValue[:])
87         pktPath := filepath.Join(dirToSync, pktName)
88         fd, err := os.Open(pktPath + NoCKSuffix)
89         if err != nil {
90                 return 0, err
91         }
92         defer fd.Close()
93         fi, err := fd.Stat()
94         if err != nil {
95                 return 0, err
96         }
97         size := fi.Size()
98         les := LEs{
99                 {"XX", string(TRx)},
100                 {"Node", nodeId},
101                 {"Pkt", pktName},
102                 {"FullSize", size},
103         }
104         var gut bool
105         if mth == nil {
106                 gut, err = Check(fd, size, hshValue[:], les, ctx.ShowPrgrs)
107         } else {
108                 if _, err = mth.PreaddFrom(
109                         bufio.NewReaderSize(fd, MTHBlockSize),
110                         pktName, ctx.ShowPrgrs,
111                 ); err != nil {
112                         return 0, err
113                 }
114                 if bytes.Equal(mth.Sum(nil), hshValue[:]) {
115                         gut = true
116                 }
117         }
118         if err != nil || !gut {
119                 return 0, errors.New("checksum mismatch")
120         }
121         if err = os.Rename(pktPath+NoCKSuffix, pktPath); err != nil {
122                 return 0, err
123         }
124         if err = DirSync(dirToSync); err != nil {
125                 return size, err
126         }
127         if ctx.HdrUsage {
128                 if _, err = fd.Seek(0, io.SeekStart); err != nil {
129                         return size, err
130                 }
131                 _, pktEncRaw, err := ctx.HdrRead(fd)
132                 if err != nil {
133                         return size, err
134                 }
135                 ctx.HdrWrite(pktEncRaw, pktPath)
136         }
137         return size, err
138 }