2 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
3 Copyright (C) 2016-2017 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
33 "github.com/davecgh/go-xdr/xdr2"
34 "golang.org/x/crypto/blake2b"
41 func dirFiles(path string) []string {
42 dir, err := os.Open(path)
47 names, err := dir.Readdirnames(0)
54 func TestTossEmail(t *testing.T) {
55 f := func(recipients [16]uint8) bool {
56 for i, recipient := range recipients {
57 recipients[i] = recipient % 8
59 spool, err := ioutil.TempDir("", "testtoss")
63 defer os.RemoveAll(spool)
64 nodeOur, err := NewNodeGenerate()
72 Neigh: make(map[NodeId]*Node),
73 Alias: make(map[string]*NodeId),
74 LogPath: filepath.Join(spool, "log.log"),
77 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
78 privates := make(map[uint8]*NodeOur)
79 for _, recipient := range recipients {
80 if _, exists := privates[recipient]; exists {
83 our, err := NewNodeGenerate()
87 privates[recipient] = our
88 ctx.Neigh[*our.Id] = our.Their()
90 for _, recipient := range recipients {
92 ctx.Neigh[*privates[recipient].Id],
101 for _, recipient := range recipients {
102 ctx.Self = privates[recipient]
103 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
104 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
105 if len(dirFiles(rxPath)) == 0 {
108 ctx.Toss(ctx.Self.Id, DefaultNiceMail-1, false, false)
109 if len(dirFiles(rxPath)) == 0 {
112 ctx.Neigh[*nodeOur.Id].Sendmail = []string{"/bin/sh", "-c", "false"}
113 ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false)
114 if len(dirFiles(rxPath)) == 0 {
117 ctx.Neigh[*nodeOur.Id].Sendmail = []string{
119 fmt.Sprintf("cat >> %s", filepath.Join(spool, "mbox")),
121 ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false)
122 if len(dirFiles(rxPath)) != 0 {
126 mbox, err := ioutil.ReadFile(filepath.Join(spool, "mbox"))
130 expected := make([]byte, 0, 16)
131 for i := 0; i < 16; i++ {
132 expected = append(expected, 123)
134 return bytes.Compare(mbox, expected) == 0
136 if err := quick.Check(f, nil); err != nil {
141 func TestTossFile(t *testing.T) {
142 f := func(fileSizes []uint8) bool {
143 if len(fileSizes) == 0 {
146 files := make(map[string][]byte)
147 for i, fileSize := range fileSizes {
148 data := make([]byte, fileSize)
149 if _, err := io.ReadFull(rand.Reader, data); err != nil {
152 files[strconv.Itoa(i)] = data
154 spool, err := ioutil.TempDir("", "testtoss")
158 defer os.RemoveAll(spool)
159 nodeOur, err := NewNodeGenerate()
167 Neigh: make(map[NodeId]*Node),
168 Alias: make(map[string]*NodeId),
169 LogPath: filepath.Join(spool, "log.log"),
172 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
173 incomingPath := filepath.Join(spool, "incoming")
174 for _, fileData := range files {
175 checksum := blake2b.Sum256(fileData)
176 fileName := ToBase32(checksum[:])
177 src := filepath.Join(spool, fileName)
178 if err := ioutil.WriteFile(src, fileData, os.FileMode(0600)); err != nil {
181 if err := ctx.TxFile(
182 ctx.Neigh[*nodeOur.Id],
191 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
192 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
193 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false)
194 if len(dirFiles(rxPath)) == 0 {
197 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
198 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false)
199 if len(dirFiles(rxPath)) != 0 {
202 for _, fileData := range files {
203 checksum := blake2b.Sum256(fileData)
204 fileName := ToBase32(checksum[:])
205 data, err := ioutil.ReadFile(filepath.Join(incomingPath, fileName))
209 if bytes.Compare(data, fileData) != 0 {
215 if err := quick.Check(f, nil); err != nil {
220 func TestTossFileSameName(t *testing.T) {
221 f := func(filesRaw uint8) bool {
222 files := int(filesRaw)%8 + 1
223 spool, err := ioutil.TempDir("", "testtoss")
227 defer os.RemoveAll(spool)
228 nodeOur, err := NewNodeGenerate()
236 Neigh: make(map[NodeId]*Node),
237 Alias: make(map[string]*NodeId),
238 LogPath: filepath.Join(spool, "log.log"),
241 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
242 srcPath := filepath.Join(spool, "junk")
243 if err = ioutil.WriteFile(
245 []byte("doesnotmatter"),
250 incomingPath := filepath.Join(spool, "incoming")
251 for i := 0; i < files; i++ {
252 if err := ctx.TxFile(
253 ctx.Neigh[*nodeOur.Id],
262 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
263 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
264 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
265 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false)
266 expected := make(map[string]struct{})
267 expected["samefile"] = struct{}{}
268 for i := 0; i < files-1; i++ {
269 expected["samefile"+strconv.Itoa(i)] = struct{}{}
271 for _, filename := range dirFiles(incomingPath) {
272 if _, exists := expected[filename]; !exists {
275 delete(expected, filename)
277 if len(expected) != 0 {
282 if err := quick.Check(f, nil); err != nil {
287 func TestTossFreq(t *testing.T) {
288 f := func(fileSizes []uint8) bool {
289 if len(fileSizes) == 0 {
292 spool, err := ioutil.TempDir("", "testtoss")
296 defer os.RemoveAll(spool)
297 nodeOur, err := NewNodeGenerate()
305 Neigh: make(map[NodeId]*Node),
306 Alias: make(map[string]*NodeId),
307 LogPath: filepath.Join(spool, "log.log"),
310 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
311 files := make(map[string][]byte)
312 for i, fileSize := range fileSizes {
313 fileData := make([]byte, fileSize)
314 if _, err := io.ReadFull(rand.Reader, fileData); err != nil {
317 fileName := strconv.Itoa(i)
318 files[fileName] = fileData
319 if err := ctx.TxFreq(
320 ctx.Neigh[*nodeOur.Id],
329 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
330 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
331 os.Rename(txPath, rxPath)
332 os.MkdirAll(txPath, os.FileMode(0700))
333 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false)
334 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
337 ctx.Neigh[*nodeOur.Id].Freq = &spool
338 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false)
339 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
342 for fileName, fileData := range files {
343 if err := ioutil.WriteFile(
344 filepath.Join(spool, fileName),
351 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false)
352 if len(dirFiles(txPath)) == 0 || len(dirFiles(rxPath)) != 0 {
355 for job := range ctx.Jobs(ctx.Self.Id, TTx) {
357 _, _, err := PktEncRead(ctx.Self, ctx.Neigh, job.Fd, &buf)
362 if _, err = xdr.Unmarshal(&buf, &pkt); err != nil {
365 dst := string(pkt.Path[:int(pkt.PathLen)])
366 if bytes.Compare(buf.Bytes(), files[dst]) != 0 {
372 if err := quick.Check(f, nil); err != nil {
377 func TestTossTrns(t *testing.T) {
378 f := func(datumLens []uint8) bool {
379 if len(datumLens) == 0 {
382 datum := make(map[int][]byte)
383 for i, datumLen := range datumLens {
385 data := make([]byte, datumLen)
386 if _, err := io.ReadFull(rand.Reader, data); err != nil {
391 spool, err := ioutil.TempDir("", "testtoss")
395 defer os.RemoveAll(spool)
396 nodeOur, err := NewNodeGenerate()
404 Neigh: make(map[NodeId]*Node),
405 Alias: make(map[string]*NodeId),
406 LogPath: filepath.Join(spool, "log.log"),
409 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
410 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
411 os.MkdirAll(rxPath, os.FileMode(0700))
412 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
413 os.MkdirAll(txPath, os.FileMode(0700))
414 for _, data := range datum {
418 PathLen: blake2b.Size256,
419 Path: new([MaxPathSize]byte),
421 copy(pktTrans.Path[:], nodeOur.Id[:])
423 if err := PktEncWrite(
425 ctx.Neigh[*nodeOur.Id],
430 bytes.NewReader(data),
435 checksum := blake2b.Sum256(dst.Bytes())
436 if err := ioutil.WriteFile(
437 filepath.Join(rxPath, ToBase32(checksum[:])),
444 ctx.Toss(ctx.Self.Id, 123, false, false)
445 if len(dirFiles(rxPath)) != 0 {
448 for _, filename := range dirFiles(txPath) {
449 dataRead, err := ioutil.ReadFile(filepath.Join(txPath, filename))
453 for k, data := range datum {
454 if bytes.Compare(dataRead, data) == 0 {
465 if err := quick.Check(f, nil); err != nil {