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()
71 Neigh: make(map[NodeId]*Node),
72 Alias: make(map[string]*NodeId),
73 LogPath: filepath.Join(spool, "log.log"),
76 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
77 privates := make(map[uint8]*NodeOur)
78 for _, recipient := range recipients {
79 if _, exists := privates[recipient]; exists {
82 our, err := NewNodeGenerate()
86 privates[recipient] = our
87 ctx.Neigh[*our.Id] = our.Their()
89 for _, recipient := range recipients {
91 ctx.Neigh[*privates[recipient].Id],
100 for _, recipient := range recipients {
101 ctx.Self = privates[recipient]
102 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
103 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
104 if len(dirFiles(rxPath)) == 0 {
107 ctx.Toss(ctx.Self.Id, DefaultNiceMail-1, false)
108 if len(dirFiles(rxPath)) == 0 {
111 ctx.Neigh[*nodeOur.Id].Sendmail = []string{"/bin/sh", "-c", "false"}
112 ctx.Toss(ctx.Self.Id, DefaultNiceMail, false)
113 if len(dirFiles(rxPath)) == 0 {
116 ctx.Neigh[*nodeOur.Id].Sendmail = []string{
118 fmt.Sprintf("cat >> %s", filepath.Join(spool, "mbox")),
120 ctx.Toss(ctx.Self.Id, DefaultNiceMail, false)
121 if len(dirFiles(rxPath)) != 0 {
125 mbox, err := ioutil.ReadFile(filepath.Join(spool, "mbox"))
129 expected := make([]byte, 0, 16)
130 for i := 0; i < 16; i++ {
131 expected = append(expected, 123)
133 return bytes.Compare(mbox, expected) == 0
135 if err := quick.Check(f, nil); err != nil {
140 func TestTossFile(t *testing.T) {
141 f := func(fileSizes []uint8) bool {
142 if len(fileSizes) == 0 {
145 files := make(map[string][]byte)
146 for i, fileSize := range fileSizes {
147 data := make([]byte, fileSize)
148 if _, err := io.ReadFull(rand.Reader, data); err != nil {
151 files[strconv.Itoa(i)] = data
153 spool, err := ioutil.TempDir("", "testtoss")
157 defer os.RemoveAll(spool)
158 nodeOur, err := NewNodeGenerate()
165 Neigh: make(map[NodeId]*Node),
166 Alias: make(map[string]*NodeId),
167 LogPath: filepath.Join(spool, "log.log"),
170 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
171 incomingPath := filepath.Join(spool, "incoming")
172 for _, fileData := range files {
173 checksum := blake2b.Sum256(fileData)
174 fileName := ToBase32(checksum[:])
175 src := filepath.Join(spool, fileName)
176 if err := ioutil.WriteFile(src, fileData, os.FileMode(0600)); err != nil {
179 if err := ctx.TxFile(
180 ctx.Neigh[*nodeOur.Id],
189 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
190 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
191 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false)
192 if len(dirFiles(rxPath)) == 0 {
195 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
196 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false)
197 if len(dirFiles(rxPath)) != 0 {
200 for _, fileData := range files {
201 checksum := blake2b.Sum256(fileData)
202 fileName := ToBase32(checksum[:])
203 data, err := ioutil.ReadFile(filepath.Join(incomingPath, fileName))
207 if bytes.Compare(data, fileData) != 0 {
213 if err := quick.Check(f, nil); err != nil {
218 func TestTossFileSameName(t *testing.T) {
219 f := func(filesRaw uint8) bool {
220 files := int(filesRaw)%8 + 1
221 spool, err := ioutil.TempDir("", "testtoss")
225 defer os.RemoveAll(spool)
226 nodeOur, err := NewNodeGenerate()
233 Neigh: make(map[NodeId]*Node),
234 Alias: make(map[string]*NodeId),
235 LogPath: filepath.Join(spool, "log.log"),
238 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
239 srcPath := filepath.Join(spool, "junk")
240 if err = ioutil.WriteFile(
242 []byte("doesnotmatter"),
247 incomingPath := filepath.Join(spool, "incoming")
248 for i := 0; i < files; i++ {
249 if err := ctx.TxFile(
250 ctx.Neigh[*nodeOur.Id],
259 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
260 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
261 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
262 ctx.Toss(ctx.Self.Id, DefaultNiceFile, false)
263 expected := make(map[string]struct{})
264 expected["samefile"] = struct{}{}
265 for i := 0; i < files-1; i++ {
266 expected["samefile"+strconv.Itoa(i)] = struct{}{}
268 for _, filename := range dirFiles(incomingPath) {
269 if _, exists := expected[filename]; !exists {
272 delete(expected, filename)
274 if len(expected) != 0 {
279 if err := quick.Check(f, nil); err != nil {
284 func TestTossFreq(t *testing.T) {
285 f := func(fileSizes []uint8) bool {
286 if len(fileSizes) == 0 {
289 spool, err := ioutil.TempDir("", "testtoss")
293 defer os.RemoveAll(spool)
294 nodeOur, err := NewNodeGenerate()
301 Neigh: make(map[NodeId]*Node),
302 Alias: make(map[string]*NodeId),
303 LogPath: filepath.Join(spool, "log.log"),
306 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
307 files := make(map[string][]byte)
308 for i, fileSize := range fileSizes {
309 fileData := make([]byte, fileSize)
310 if _, err := io.ReadFull(rand.Reader, fileData); err != nil {
313 fileName := strconv.Itoa(i)
314 files[fileName] = fileData
315 if err := ctx.TxFreq(
316 ctx.Neigh[*nodeOur.Id],
325 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
326 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
327 os.Rename(txPath, rxPath)
328 os.MkdirAll(txPath, os.FileMode(0700))
329 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false)
330 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
333 ctx.Neigh[*nodeOur.Id].Freq = &spool
334 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false)
335 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
338 for fileName, fileData := range files {
339 if err := ioutil.WriteFile(
340 filepath.Join(spool, fileName),
347 ctx.Toss(ctx.Self.Id, DefaultNiceFreq, false)
348 if len(dirFiles(txPath)) == 0 || len(dirFiles(rxPath)) != 0 {
351 for job := range ctx.Jobs(ctx.Self.Id, TTx) {
353 _, _, err := PktEncRead(ctx.Self, ctx.Neigh, job.Fd, &buf)
358 if _, err = xdr.Unmarshal(&buf, &pkt); err != nil {
361 dst := string(pkt.Path[:int(pkt.PathLen)])
362 if bytes.Compare(buf.Bytes(), files[dst]) != 0 {
368 if err := quick.Check(f, nil); err != nil {
373 func TestTossTrns(t *testing.T) {
374 f := func(datumLens []uint8) bool {
375 if len(datumLens) == 0 {
378 datum := make(map[int][]byte)
379 for i, datumLen := range datumLens {
381 data := make([]byte, datumLen)
382 if _, err := io.ReadFull(rand.Reader, data); err != nil {
387 spool, err := ioutil.TempDir("", "testtoss")
391 defer os.RemoveAll(spool)
392 nodeOur, err := NewNodeGenerate()
399 Neigh: make(map[NodeId]*Node),
400 Alias: make(map[string]*NodeId),
401 LogPath: filepath.Join(spool, "log.log"),
404 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
405 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
406 os.MkdirAll(rxPath, os.FileMode(0700))
407 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
408 os.MkdirAll(txPath, os.FileMode(0700))
409 for _, data := range datum {
413 PathLen: blake2b.Size256,
414 Path: new([MaxPathSize]byte),
416 copy(pktTrans.Path[:], nodeOur.Id[:])
418 if err := PktEncWrite(
420 ctx.Neigh[*nodeOur.Id],
425 bytes.NewReader(data),
430 checksum := blake2b.Sum256(dst.Bytes())
431 if err := ioutil.WriteFile(
432 filepath.Join(rxPath, ToBase32(checksum[:])),
439 ctx.Toss(ctx.Self.Id, 123, false)
440 if len(dirFiles(rxPath)) != 0 {
443 for _, filename := range dirFiles(txPath) {
444 dataRead, err := ioutil.ReadFile(filepath.Join(txPath, filename))
448 for k, data := range datum {
449 if bytes.Compare(dataRead, data) == 0 {
460 if err := quick.Check(f, nil); err != nil {