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],
99 for _, recipient := range recipients {
100 ctx.Self = privates[recipient]
101 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
102 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
103 if len(dirFiles(rxPath)) == 0 {
106 ctx.Toss(ctx.Self.Id, DefaultNiceMail-1)
107 if len(dirFiles(rxPath)) == 0 {
110 ctx.Neigh[*nodeOur.Id].Sendmail = []string{"/bin/sh", "-c", "false"}
111 ctx.Toss(ctx.Self.Id, DefaultNiceMail)
112 if len(dirFiles(rxPath)) == 0 {
115 ctx.Neigh[*nodeOur.Id].Sendmail = []string{
117 fmt.Sprintf("cat >> %s", filepath.Join(spool, "mbox")),
119 ctx.Toss(ctx.Self.Id, DefaultNiceMail)
120 if len(dirFiles(rxPath)) != 0 {
124 mbox, err := ioutil.ReadFile(filepath.Join(spool, "mbox"))
128 expected := make([]byte, 0, 16)
129 for i := 0; i < 16; i++ {
130 expected = append(expected, 123)
132 return bytes.Compare(mbox, expected) == 0
134 if err := quick.Check(f, nil); err != nil {
139 func TestTossFile(t *testing.T) {
140 f := func(fileSizes []uint8) bool {
141 if len(fileSizes) == 0 {
144 files := make(map[string][]byte)
145 for i, fileSize := range fileSizes {
146 data := make([]byte, fileSize)
147 if _, err := io.ReadFull(rand.Reader, data); err != nil {
150 files[strconv.Itoa(i)] = data
152 spool, err := ioutil.TempDir("", "testtoss")
156 defer os.RemoveAll(spool)
157 nodeOur, err := NewNodeGenerate()
164 Neigh: make(map[NodeId]*Node),
165 Alias: make(map[string]*NodeId),
166 LogPath: filepath.Join(spool, "log.log"),
169 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
170 incomingPath := filepath.Join(spool, "incoming")
171 for _, fileData := range files {
172 checksum := blake2b.Sum256(fileData)
173 fileName := ToBase32(checksum[:])
174 src := filepath.Join(spool, fileName)
175 if err := ioutil.WriteFile(src, fileData, os.FileMode(0600)); err != nil {
178 if err := ctx.TxFile(
179 ctx.Neigh[*nodeOur.Id],
187 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
188 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
189 ctx.Toss(ctx.Self.Id, DefaultNiceFile)
190 if len(dirFiles(rxPath)) == 0 {
193 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
194 ctx.Toss(ctx.Self.Id, DefaultNiceFile)
195 if len(dirFiles(rxPath)) != 0 {
198 for _, fileData := range files {
199 checksum := blake2b.Sum256(fileData)
200 fileName := ToBase32(checksum[:])
201 data, err := ioutil.ReadFile(filepath.Join(incomingPath, fileName))
205 if bytes.Compare(data, fileData) != 0 {
211 if err := quick.Check(f, nil); err != nil {
216 func TestTossFileSameName(t *testing.T) {
217 f := func(filesRaw uint8) bool {
218 files := int(filesRaw)%8 + 1
219 spool, err := ioutil.TempDir("", "testtoss")
223 defer os.RemoveAll(spool)
224 nodeOur, err := NewNodeGenerate()
231 Neigh: make(map[NodeId]*Node),
232 Alias: make(map[string]*NodeId),
233 LogPath: filepath.Join(spool, "log.log"),
236 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
237 srcPath := filepath.Join(spool, "junk")
238 if err = ioutil.WriteFile(
240 []byte("doesnotmatter"),
245 incomingPath := filepath.Join(spool, "incoming")
246 for i := 0; i < files; i++ {
247 if err := ctx.TxFile(
248 ctx.Neigh[*nodeOur.Id],
256 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
257 os.Rename(filepath.Join(spool, ctx.Self.Id.String(), string(TTx)), rxPath)
258 ctx.Neigh[*nodeOur.Id].Incoming = &incomingPath
259 ctx.Toss(ctx.Self.Id, DefaultNiceFile)
260 expected := make(map[string]struct{})
261 expected["samefile"] = struct{}{}
262 for i := 0; i < files-1; i++ {
263 expected["samefile"+strconv.Itoa(i)] = struct{}{}
265 for _, filename := range dirFiles(incomingPath) {
266 if _, exists := expected[filename]; !exists {
269 delete(expected, filename)
271 if len(expected) != 0 {
276 if err := quick.Check(f, nil); err != nil {
281 func TestTossFreq(t *testing.T) {
282 f := func(fileSizes []uint8) bool {
283 if len(fileSizes) == 0 {
286 spool, err := ioutil.TempDir("", "testtoss")
290 defer os.RemoveAll(spool)
291 nodeOur, err := NewNodeGenerate()
298 Neigh: make(map[NodeId]*Node),
299 Alias: make(map[string]*NodeId),
300 LogPath: filepath.Join(spool, "log.log"),
303 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
304 files := make(map[string][]byte)
305 for i, fileSize := range fileSizes {
306 fileData := make([]byte, fileSize)
307 if _, err := io.ReadFull(rand.Reader, fileData); err != nil {
310 fileName := strconv.Itoa(i)
311 files[fileName] = fileData
312 if err := ctx.TxFreq(
313 ctx.Neigh[*nodeOur.Id],
321 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
322 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
323 os.Rename(txPath, rxPath)
324 os.MkdirAll(txPath, os.FileMode(0700))
325 ctx.Toss(ctx.Self.Id, DefaultNiceFreq)
326 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
329 ctx.Neigh[*nodeOur.Id].Freq = &spool
330 ctx.Toss(ctx.Self.Id, DefaultNiceFreq)
331 if len(dirFiles(txPath)) != 0 || len(dirFiles(rxPath)) == 0 {
334 for fileName, fileData := range files {
335 if err := ioutil.WriteFile(
336 filepath.Join(spool, fileName),
343 ctx.Toss(ctx.Self.Id, DefaultNiceFreq)
344 if len(dirFiles(txPath)) == 0 || len(dirFiles(rxPath)) != 0 {
347 for job := range ctx.Jobs(ctx.Self.Id, TTx) {
349 _, err := PktEncRead(ctx.Self, ctx.Neigh, job.Fd, &buf)
354 if _, err = xdr.Unmarshal(&buf, &pkt); err != nil {
357 dst := string(pkt.Path[:int(pkt.PathLen)])
358 if bytes.Compare(buf.Bytes(), files[dst]) != 0 {
364 if err := quick.Check(f, nil); err != nil {
369 func TestTossTrns(t *testing.T) {
370 f := func(datumLens []uint8) bool {
371 if len(datumLens) == 0 {
374 datum := make(map[int][]byte)
375 for i, datumLen := range datumLens {
377 data := make([]byte, datumLen)
378 if _, err := io.ReadFull(rand.Reader, data); err != nil {
383 spool, err := ioutil.TempDir("", "testtoss")
387 defer os.RemoveAll(spool)
388 nodeOur, err := NewNodeGenerate()
395 Neigh: make(map[NodeId]*Node),
396 Alias: make(map[string]*NodeId),
397 LogPath: filepath.Join(spool, "log.log"),
400 ctx.Neigh[*nodeOur.Id] = nodeOur.Their()
401 rxPath := filepath.Join(spool, ctx.Self.Id.String(), string(TRx))
402 os.MkdirAll(rxPath, os.FileMode(0700))
403 txPath := filepath.Join(spool, ctx.Self.Id.String(), string(TTx))
404 os.MkdirAll(txPath, os.FileMode(0700))
405 for _, data := range datum {
409 PathLen: blake2b.Size256,
410 Path: new([MaxPathSize]byte),
412 copy(pktTrans.Path[:], nodeOur.Id[:])
414 if err := PktEncWrite(
416 ctx.Neigh[*nodeOur.Id],
420 bytes.NewReader(data),
425 checksum := blake2b.Sum256(dst.Bytes())
426 if err := ioutil.WriteFile(
427 filepath.Join(rxPath, ToBase32(checksum[:])),
434 ctx.Toss(ctx.Self.Id, 123)
435 if len(dirFiles(rxPath)) != 0 {
438 for _, filename := range dirFiles(txPath) {
439 dataRead, err := ioutil.ReadFile(filepath.Join(txPath, filename))
443 for k, data := range datum {
444 if bytes.Compare(dataRead, data) == 0 {
455 if err := quick.Check(f, nil); err != nil {