Beispiel #1
0
func TestPingerSetDF(t *testing.T) {
	if skipRawSocketTests() {
		t.Skip("Test skipped due to non-root")
	}

	pinger := &Pinger{
		DF:   true,
		Size: 1800,
	}
	pinger.AddIPs([]string{"8.8.8.8"})

	res, err := pinger.Start()
	require.NoError(t, err)
	require.NotNil(t, res)

	go func() {
		for pr := range res {
			glog.Debugf("%v", pr)
		}
	}()

	select {
	case <-time.Tick(time.Duration(len(pinger.IPs())) * time.Second):
	}

	pinger.Stop()
}
Beispiel #2
0
func TestPingerStartMultiple(t *testing.T) {
	if skipRawSocketTests() {
		t.Skip("Test skipped due to non-root")
	}

	pinger := &Pinger{}
	pinger.AddIPs([]string{"127.0.0.1"})

	for i := 0; i < 5; i++ {
		done := make(chan struct{})
		cnt := 0

		res, err := pinger.Start()
		require.NoError(t, err)
		require.NotNil(t, res)

		go func() {
			for pr := range res {
				glog.Debugf("%v", pr)
				cnt++
			}
			close(done)
		}()

		select {
		case <-time.Tick(time.Duration(len(pinger.IPs())) * time.Second):
			require.FailNow(t, "Test timed out")

		case <-done:
			require.Equal(t, len(pinger.IPs()), cnt)
		}

		pinger.Stop()
	}
}
Beispiel #3
0
func TestPingerPing(t *testing.T) {
	if skipRawSocketTests() {
		t.Skip("Test skipped due to non-root")
	}

	pr, err := Ping("127.0.0.1")
	require.NoError(t, err)
	glog.Debugf("%v", pr)
}
Beispiel #4
0
func TestParseIPv4Success(t *testing.T) {
	for i, ip := range ips {
		glog.Debugf("Parsing %d %s", i, ip)
		res, err := ParseIP(ip)
		require.NoError(t, err)

		m := make(map[[4]byte]bool)

		for _, ip2 := range res {
			var tmp [4]byte
			copy(tmp[:], ip2.To4())
			m[tmp] = true
		}

		require.Equal(t, results[i], m)
	}
}
Beispiel #5
0
func TestEnglishVocOutput(t *testing.T) {
	inscan, infile := openFile("voc.txt")
	outscan, outfile := openFile("output.txt")
	defer infile.Close()
	defer outfile.Close()

	for inscan.Scan() {
		if !outscan.Scan() {
			break
		}

		word := inscan.Text()
		expect := outscan.Text()
		//glog.Debugf("word=%q, expect=%q", word, expect)
		actual := Stem(word)
		if actual != expect {
			glog.Debugf("word=%q, actual=%q != expect=%q", word, actual, expect)
		}
		assert.Equal(t, expect, actual)
	}
}
Beispiel #6
0
func (this *Pinger) sendMessage(m *icmp.Message, wh *ipv4.Header) error {
	select {
	case <-this.done:
		return nil

	default:
	}

	var (
		wb        []byte
		tempDelay time.Duration // how long to sleep on accept failure
		ticker    = time.NewTicker(this.Interval)
	)

	for i, dst := range this.IPs() {
		if i != 0 {
			<-ticker.C
		}

		binary.BigEndian.PutUint64(this.payload, uint64(time.Now().UnixNano()))

		wb, err := this.marshalMessage(m, wb)
		if err != nil {
			glog.Errorf("Error creating ICMP payload: %v", err)
			continue
		}

		wh.TotalLen = ipv4.HeaderLen + len(wb)
		wh.Dst = dst

		glog.Debugf("Pinging %s", wh.Dst)
		this.mu.Lock()
		this.results[wh.Dst.String()] = nil
		this.mu.Unlock()

		if err := this.rconn.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
			return err
		}

		if err := this.rconn.WriteTo(wh, wb, nil); err != nil {
			select {
			case <-this.done:
				return nil

			default:
			}

			// Borrowed from go1.3.3/src/pkg/net/http/server.go:1699
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}

				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}

				glog.Errorf("write error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue // out of the IP list, wait for next tick
			}

			return err
		}
	}

	if err := this.rconn.SetReadDeadline(time.Now().Add(this.MaxRTT)); err != nil {
		return err
	}

	return nil
}
Beispiel #7
0
func (this *Pinger) receiver() {
	defer func() {
		// Let's recover from panic
		if r := recover(); r != nil {
			glog.Errorf("Recovering from panic: %v", r)
		}

		this.wg.Done()
		close(this.reschan)
		this.Stop()
	}()

	rb := make([]byte, ipv4.HeaderLen+icmpHeaderSize+this.Size)

	var tempDelay time.Duration // how long to sleep on accept failure

loop:
	for {
		rh, b, _, err := this.rconn.ReadFrom(rb)
		if err != nil {
			select {
			case <-this.done:
				break loop

			default:
			}

			// Borrowed from go1.3.3/src/pkg/net/http/server.go:1699
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := this.MaxRTT; tempDelay > max {
					tempDelay = max
				}
				glog.Errorf("Accept error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue
			}

			break loop
		}

		m, err := icmp.ParseMessage(ProtocolICMP, b)
		if err != nil {
			// Hm...bad message?
			continue
		}

		if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
			// On Linux we must handle own sent packets.
			continue
		}

		if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
			glog.Errorf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
			continue
		}

		// Echo Reply
		er, ok := m.Body.(*icmp.Echo)
		if !ok {
			glog.Errorf("Error type requireing m.Body to *icmp.Echo")
			continue
		}

		if er.ID != int(this.pid) || er.Seq > int(this.seqnum) {
			glog.Debugf("%d != %d, %d != %d", er.ID, this.pid, er.Seq, this.seqnum)
			continue
		}

		rtt := time.Since(time.Unix(0, int64(binary.BigEndian.Uint64(er.Data))))

		src := make(net.IP, len(rh.Src))
		copy(src, rh.Src)

		dst := make(net.IP, len(rh.Dst))
		copy(dst, rh.Dst)

		pr := &PingResult{
			TOS:  rh.TOS,
			TTL:  rh.TTL,
			Type: m.Type,
			Code: m.Code,
			ID:   er.ID,
			Seq:  er.Seq,
			RTT:  rtt,
			Src:  src,
			Dst:  dst,
			Size: len(er.Data),
		}
		this.mu.Lock()
		this.results[src.String()] = pr
		this.mu.Unlock()

		this.reschan <- pr
	}

	for ip, pr := range this.results {
		if pr == nil {
			this.reschan <- &PingResult{
				Src: net.ParseIP(ip),
				ID:  int(this.pid),
				Seq: int(this.seqnum),
				Err: fmt.Errorf("%s: Request timed out for seq %d", ip, this.seqnum),
			}
		}
	}
}