2 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
3 Copyright (C) 2016-2018 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()
73 Neigh: make(map[NodeId]*Node),
74 Alias: make(map[string]*NodeId),
75 LogPath: filepath.Join(spool, "log.log"),
78 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
79 privates := make(map[uint8]*NodeOur)
80 for _, recipient := range recipients {
81 if _, exists := privates[recipient]; exists {
84 our, err := NewNodeGenerate()
89 privates[recipient] = our
90 ctx.Neigh[*our.Id] = our.Their()
92 for _, recipient := range recipients {
94 ctx.Neigh[*privates[recipient].Id],
104 for _, recipient := range recipients {
105 ctx.Self = privates[recipient]
106 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
107 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
108 if len(dirFiles(rxPath)) == 0 {
111 ctx.Toss(ctx.Self.Id, DefaultNiceMail-1, false, false, false, false, false, false)
112 if len(dirFiles(rxPath)) == 0 {
115 ctx.Neigh[*nodeOur.Id].Sendmail = []string{"/bin/sh", "-c", "false"}
116 ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false, false, false, false, false)
117 if len(dirFiles(rxPath)) == 0 {
120 ctx.Neigh[*nodeOur.Id].Sendmail = []string{
122 fmt.Sprintf("cat >> %s", filepath.Join(spool, "mbox")),
124 ctx.Toss(ctx.Self.Id, DefaultNiceMail, false, false, false, false, false, false)
125 if len(dirFiles(rxPath)) != 0 {
129 mbox, err := ioutil.ReadFile(filepath.Join(spool, "mbox"))
133 expected := make([]byte, 0, 16)
134 for i := 0; i < 16; i++ {
135 expected = append(expected, 123)
137 return bytes.Compare(mbox, expected) == 0
139 if err := quick.Check(f, nil); err != nil {
144 func TestTossFile(t *testing.T) {
145 f := func(fileSizes []uint8) bool {
146 if len(fileSizes) == 0 {
149 files := make(map[string][]byte)
150 for i, fileSize := range fileSizes {
151 data := make([]byte, fileSize)
152 if _, err := io.ReadFull(rand.Reader, data); err != nil {
155 files[strconv.Itoa(i)] = data
157 spool, err := ioutil.TempDir("", "testtoss")
161 defer os.RemoveAll(spool)
162 nodeOur, err := NewNodeGenerate()
171 Neigh: make(map[NodeId]*Node),
172 Alias: make(map[string]*NodeId),
173 LogPath: filepath.Join(spool, "log.log"),
176 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
177 incomingPath := filepath.Join(spool, "incoming")
178 for _, fileData := range files {
179 checksum := blake2b.Sum256(fileData)
180 fileName := ToBase32(checksum[:])
181 src := filepath.Join(spool, fileName)
182 if err := ioutil.WriteFile(src, fileData, os.FileMode(0600)); err != nil {
185 if err := ctx.TxFile(
186 ctx.Neigh[*nodeOur.Id],
196 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
197 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
198 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false)
199 if len(dirFiles(rxPath)) == 0 {
202 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
203 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false)
204 if len(dirFiles(rxPath)) != 0 {
207 for _, fileData := range files {
208 checksum := blake2b.Sum256(fileData)
209 fileName := ToBase32(checksum[:])
210 data, err := ioutil.ReadFile(filepath.Join(incomingPath, fileName))
214 if bytes.Compare(data, fileData) != 0 {
220 if err := quick.Check(f, nil); err != nil {
225 func TestTossFileSameName(t *testing.T) {
226 f := func(filesRaw uint8) bool {
227 files := int(filesRaw)%8 + 1
228 spool, err := ioutil.TempDir("", "testtoss")
232 defer os.RemoveAll(spool)
233 nodeOur, err := NewNodeGenerate()
242 Neigh: make(map[NodeId]*Node),
243 Alias: make(map[string]*NodeId),
244 LogPath: filepath.Join(spool, "log.log"),
247 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
248 srcPath := filepath.Join(spool, "junk")
249 if err = ioutil.WriteFile(
251 []byte("doesnotmatter"),
257 incomingPath := filepath.Join(spool, "incoming")
258 for i := 0; i < files; i++ {
259 if err := ctx.TxFile(
260 ctx.Neigh[*nodeOur.Id],
270 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
271 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
272 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
273 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false, false, false, false, false, false)
274 expected := make(map[string]struct{})
275 expected["samefile"] = struct{}{}
276 for i := 0; i < files-1; i++ {
277 expected["samefile"+strconv.Itoa(i)] = struct{}{}
279 for _, filename := range dirFiles(incomingPath) {
280 if _, exists := expected[filename]; !exists {
283 delete(expected, filename)
285 if len(expected) != 0 {
290 if err := quick.Check(f, nil); err != nil {
295 func TestTossFreq(t *testing.T) {
296 f := func(fileSizes []uint8, replyNice uint8) bool {
297 if len(fileSizes) == 0 {
300 spool, err := ioutil.TempDir("", "testtoss")
304 defer os.RemoveAll(spool)
305 nodeOur, err := NewNodeGenerate()
314 Neigh: make(map[NodeId]*Node),
315 Alias: make(map[string]*NodeId),
316 LogPath: filepath.Join(spool, "log.log"),
319 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
320 files := make(map[string][]byte)
321 for i, fileSize := range fileSizes {
322 fileData := make([]byte, fileSize)
323 if _, err := io.ReadFull(rand.Reader, fileData); err != nil {
326 fileName := strconv.Itoa(i)
327 files[fileName] = fileData
328 if err := ctx.TxFreq(
329 ctx.Neigh[*nodeOur.Id],
340 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
341 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
342 os.Rename(txPath, rxPath)
343 os.MkdirAll(txPath, os.FileMode(0700))
344 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false)
345 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
348 ctx.Neigh[*nodeOur.Id].Freq = &spool
349 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false)
350 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
353 for fileName, fileData := range files {
354 if err := ioutil.WriteFile(
355 filepath.Join(spool, fileName),
362 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false, false, false, false, false, false)
363 if len(dirFiles(txPath)) == 0 || len(dirFiles(rxPath)) != 0 {
366 for job := range ctx.Jobs(ctx.Self.Id, TTx) {
368 _, _, err := PktEncRead(ctx.Self, ctx.Neigh, job.Fd, &buf)
374 if _, err = xdr.Unmarshal(&buf, &pkt); err != nil {
378 if pkt.Nice != replyNice {
381 dst := string(pkt.Path[:int(pkt.PathLen)])
382 if bytes.Compare(buf.Bytes(), files[dst]) != 0 {
388 if err := quick.Check(f, nil); err != nil {
393 func TestTossTrns(t *testing.T) {
394 f := func(datumLens []uint8) bool {
395 if len(datumLens) == 0 {
398 datum := make(map[int][]byte)
399 for i, datumLen := range datumLens {
401 data := make([]byte, datumLen)
402 if _, err := io.ReadFull(rand.Reader, data); err != nil {
407 spool, err := ioutil.TempDir("", "testtoss")
411 defer os.RemoveAll(spool)
412 nodeOur, err := NewNodeGenerate()
421 Neigh: make(map[NodeId]*Node),
422 Alias: make(map[string]*NodeId),
423 LogPath: filepath.Join(spool, "log.log"),
426 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
427 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
428 os.MkdirAll(rxPath, os.FileMode(0700))
429 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
430 os.MkdirAll(txPath, os.FileMode(0700))
431 for _, data := range datum {
435 PathLen: blake2b.Size256,
436 Path: new([MaxPathSize]byte),
438 copy(pktTrans.Path[:], nodeOur.Id[:])
440 if err := PktEncWrite(
442 ctx.Neigh[*nodeOur.Id],
447 bytes.NewReader(data),
453 checksum := blake2b.Sum256(dst.Bytes())
454 if err := ioutil.WriteFile(
455 filepath.Join(rxPath, ToBase32(checksum[:])),
462 ctx.Toss(ctx.Self.Id, 123, false, false, false, false, false, false)
463 if len(dirFiles(rxPath)) != 0 {
466 for _, filename := range dirFiles(txPath) {
467 dataRead, err := ioutil.ReadFile(filepath.Join(txPath, filename))
471 for k, data := range datum {
472 if bytes.Compare(dataRead, data) == 0 {
483 if err := quick.Check(f, nil); err != nil {