| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- // Copyright (C) 2014 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at http://mozilla.org/MPL/2.0/.
- package discover
- import (
- "fmt"
- "net"
- "time"
- "testing"
- "github.com/syncthing/protocol"
- "github.com/syncthing/syncthing/lib/sync"
- )
- var device protocol.DeviceID
- func init() {
- device, _ = protocol.DeviceIDFromString("P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2")
- }
- type FakeAnnouncer struct {
- pkt Announce
- }
- func (f *FakeAnnouncer) Announcement() Announce {
- return f.pkt
- }
- func TestUDP4Success(t *testing.T) {
- conn, err := net.ListenUDP("udp4", nil)
- if err != nil {
- t.Fatal(err)
- }
- port := conn.LocalAddr().(*net.UDPAddr).Port
- address := fmt.Sprintf("udp4://127.0.0.1:%d", port)
- pkt := Announce{
- Magic: AnnouncementMagic,
- This: Device{
- device[:],
- []string{"tcp://123.123.123.123:1234"},
- nil,
- },
- }
- ann := &FakeAnnouncer{
- pkt: pkt,
- }
- client, err := New(address, ann)
- if err != nil {
- t.Fatal(err)
- }
- udpclient := client.(*UDPClient)
- if udpclient.errorRetryInterval != DefaultErrorRetryInternval {
- t.Fatal("Incorrect retry interval")
- }
- if udpclient.listenAddress.IP != nil || udpclient.listenAddress.Port != 0 {
- t.Fatal("Wrong listen IP or port", udpclient.listenAddress)
- }
- if client.Address() != address {
- t.Fatal("Incorrect address")
- }
- buf := make([]byte, 2048)
- // First announcement
- conn.SetDeadline(time.Now().Add(time.Millisecond * 100))
- _, err = conn.Read(buf)
- if err != nil {
- t.Fatal(err)
- }
- // Announcement verification
- conn.SetDeadline(time.Now().Add(time.Millisecond * 1100))
- _, addr, err := conn.ReadFromUDP(buf)
- if err != nil {
- t.Fatal(err)
- }
- // Reply to it.
- _, err = conn.WriteToUDP(pkt.MustMarshalXDR(), addr)
- if err != nil {
- t.Fatal(err)
- }
- // We should get nothing else
- conn.SetDeadline(time.Now().Add(time.Millisecond * 100))
- _, err = conn.Read(buf)
- if err == nil {
- t.Fatal("Expected error")
- }
- // Status should be ok
- if !client.StatusOK() {
- t.Fatal("Wrong status")
- }
- // Do a lookup in a separate routine
- addrs := []string{}
- wg := sync.NewWaitGroup()
- wg.Add(1)
- go func() {
- pkt, err := client.Lookup(device)
- if err == nil {
- for _, addr := range pkt.This.Addresses {
- addrs = append(addrs, addr)
- }
- }
- wg.Done()
- }()
- // Receive the lookup and reply
- conn.SetDeadline(time.Now().Add(time.Millisecond * 100))
- _, addr, err = conn.ReadFromUDP(buf)
- if err != nil {
- t.Fatal(err)
- }
- conn.WriteToUDP(pkt.MustMarshalXDR(), addr)
- // Wait for the lookup to arrive, verify that the number of answers is correct
- wg.Wait()
- if len(addrs) != 1 || addrs[0] != "tcp://123.123.123.123:1234" {
- t.Fatal("Wrong number of answers")
- }
- client.Stop()
- }
- func TestUDP4Failure(t *testing.T) {
- conn, err := net.ListenUDP("udp4", nil)
- if err != nil {
- t.Fatal(err)
- }
- port := conn.LocalAddr().(*net.UDPAddr).Port
- address := fmt.Sprintf("udp4://127.0.0.1:%d/?listenaddress=127.0.0.1&retry=5", port)
- pkt := Announce{
- Magic: AnnouncementMagic,
- This: Device{
- device[:],
- []string{"tcp://123.123.123.123:1234"},
- nil,
- },
- }
- ann := &FakeAnnouncer{
- pkt: pkt,
- }
- client, err := New(address, ann)
- if err != nil {
- t.Fatal(err)
- }
- udpclient := client.(*UDPClient)
- if udpclient.errorRetryInterval != time.Second*5 {
- t.Fatal("Incorrect retry interval")
- }
- if !udpclient.listenAddress.IP.Equal(net.IPv4(127, 0, 0, 1)) || udpclient.listenAddress.Port != 0 {
- t.Fatal("Wrong listen IP or port", udpclient.listenAddress)
- }
- if client.Address() != address {
- t.Fatal("Incorrect address")
- }
- buf := make([]byte, 2048)
- // First announcement
- conn.SetDeadline(time.Now().Add(time.Millisecond * 100))
- _, err = conn.Read(buf)
- if err != nil {
- t.Fatal(err)
- }
- // Announcement verification
- conn.SetDeadline(time.Now().Add(time.Millisecond * 1100))
- _, _, err = conn.ReadFromUDP(buf)
- if err != nil {
- t.Fatal(err)
- }
- // Don't reply
- // We should get nothing else
- conn.SetDeadline(time.Now().Add(time.Millisecond * 100))
- _, err = conn.Read(buf)
- if err == nil {
- t.Fatal("Expected error")
- }
- // Status should be failure
- if client.StatusOK() {
- t.Fatal("Wrong status")
- }
- // Do a lookup in a separate routine
- addrs := []string{}
- wg := sync.NewWaitGroup()
- wg.Add(1)
- go func() {
- pkt, err := client.Lookup(device)
- if err == nil {
- for _, addr := range pkt.This.Addresses {
- addrs = append(addrs, addr)
- }
- }
- wg.Done()
- }()
- // Receive the lookup and don't reply
- conn.SetDeadline(time.Now().Add(time.Millisecond * 100))
- _, _, err = conn.ReadFromUDP(buf)
- if err != nil {
- t.Fatal(err)
- }
- // Wait for the lookup to timeout, verify that the number of answers is none
- wg.Wait()
- if len(addrs) != 0 {
- t.Fatal("Wrong number of answers")
- }
- client.Stop()
- }
|