Ejemplo n.º 1
0
// Reads from connection tcpConn, logs any data received as an error and signals
// actual network errors by closing the connection and pinging the queue.
// This function returns when the first error is encountered on tcpConn.
func monitorConnection(tcpConn net.Conn, queue *deque.Deque) {
	buf := make([]byte, 65536)
	for {
		n, err := tcpConn.Read(buf)
		if n > 0 {
			util.Log(0, "ERROR! Received %v bytes of unexpected data on Tell() channel to %v", n, tcpConn.RemoteAddr())
		}

		if err != nil {
			util.Log(2, "DEBUG! monitorConnection terminating: %v", err)
			tcpConn.Close() // make sure the connection is closed in case the error didn't
			queue.Push("")  // ping to wake up handleConnection() if it's blocked
			return
		}
	}
}
Ejemplo n.º 2
0
/*
  Reads and returns the next DER encoded SEQUENCE from r,
  which may optionally be base64 encoded and may be preceded
  by "garbage". The returned data will always be DER bytes
  without preceding garbage and NOT base64 encoded.
  The SEQUENCE will only be recognized as valid if
  it does not contain APPLICATION or PRIVATE tags or
  tags >= 31.
  This function takes care not to read more bytes than
  necessary which allows the function to be called
  multiple times on a stream of concatenated SEQUENCEs.
*/
func ReadNextSEQUENCE(r io.Reader) ([]byte, error) {
	b := []byte{0}
	var err error
	var n int
	space := true
	var eaters deque.Deque
	for {
		n, err = r.Read(b)
		if err != nil {
			return nil, err
		}
		if n == 0 {
			return nil, io.EOF
		}
		if b[0] == 0x30 { // SEQUENCE
			eaters.Push(newRawEater())
		}
		if b[0] > ' ' {
			if space {
				eaters.Push(newBase64Eater())
			}
			space = false
		} else {
			space = true
		}

		for i := 0; i < eaters.Count(); {
			result := eaters.At(i).(eater).Eat(b[0])
			switch result {
			case -1: // error
				eaters.RemoveAt(i)
			case 0: // ok, need more data
				i++
			case 1: // done
				return eaters.At(i).(eater).Data(), nil
			}
		}
	}
}
Ejemplo n.º 3
0
// Unit tests for the package github.com/mbenkmann/golib/deque.
func Deque_test() {
	fmt.Printf("\n==== deque ===\n\n")

	whatever := []uint{0, 1, 2, 3, 4, 5, 21, 127, 200}
	zero := []uint{0}
	one := []uint{1}
	check(Growth(deque.Double, zero, zero, whatever, one), "")
	check(Growth(deque.Double, zero, one, whatever, one), "")
	check(Growth(deque.Double, []uint{1, 2, 3, 4, 8, 16, 32, 111}, one, []uint{11}, []uint{1, 2, 3, 4, 8, 16, 32, 111}), "")
	check(Growth(deque.Double, []uint{1, 2, 3, 4, 8, 16, 32, 111}, []uint{11}, []uint{11}, []uint{15, 14, 21, 12, 24, 16, 32, 111}), "")

	deque.GrowthFactor = 0
	check(Growth(deque.Exponential, whatever, zero, zero, one), "")
	check(Growth(deque.Exponential, whatever, one, zero, one), "")
	check(Growth(deque.Exponential, whatever, one, one, []uint{2}), "")
	check(Growth(deque.Exponential, whatever, one, []uint{2}, []uint{4}), "")
	deque.GrowthFactor = 7
	check(Growth(deque.Exponential, []uint{666}, one, []uint{0, 1, 2, 3, 4}, []uint{7, 14, 28, 56, 112}), "")
	check(Growth(deque.Exponential, []uint{666}, []uint{30}, []uint{0, 1, 2, 3, 4}, []uint{56, 56, 56, 56, 112}), "")

	deque.GrowthFactor = 0
	var i uint
	for i = 0; i < 5; i++ {
		check(Growth(deque.Accelerated, whatever, []uint{i}, whatever, []uint{i}), "")
	}

	deque.GrowthFactor = 7
	check(Growth(deque.Accelerated, []uint{111}, one, []uint{0, 1, 2, 3, 4}, []uint{7, 14, 21, 28, 35}), "")

	check(Growth(deque.GrowBy(0), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}), "")
	check(Growth(deque.GrowBy(1), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{1, 1, 2, 3, 4, 5, 6, 7, 8}), "")
	check(Growth(deque.GrowBy(2), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{2, 2, 2, 3, 4, 5, 6, 7, 8}), "")
	check(Growth(deque.GrowBy(3), []uint{111}, []uint{0, 1, 2, 3, 4, 5, 6, 7, 8}, []uint{222}, []uint{3, 3, 3, 3, 4, 5, 6, 7, 8}), "")

	check(Growth(deque.BlockIfFull, whatever, whatever, whatever, zero), "")

	func() {
		defer func() {
			check(recover(), deque.Overflow)
		}()
		deque.PanicIfOverflow(1, 2, 3)
	}()

	d2 := deque.New(deque.GrowthFunc(deque.Exponential))
	d2.CheckInvariant()
	check(d2.Growth, deque.Exponential)

	check(deque.New(111).Capacity(), 111)
	check(deque.New(22, []interface{}{1, "foo", 2, "bar"}, 111).Capacity(), 111)
	check(deque.New([]interface{}{1, "foo", 2, "bar"}, 2).Capacity(), 4)
	d1 := deque.New([]interface{}{1, "foo", 2, "bar"}, 2, deque.Accelerated, []interface{}{3, "foobar", 10, "xxx", "yyy"})
	check(Deque(d1, 1, "foo", 2, "bar", 3, "foobar", 10, "xxx", "yyy"), "")
	check(d1.Capacity(), 9)
	check(d1.Growth, deque.Accelerated)
	d1.Init([]interface{}{"bla", "argl", "bart"}, d1, []interface{}{}, []interface{}{"mark", "susi", "karl", "peter"}, []interface{}{}, d1)
	check(Deque(d1, "bla", "argl", "bart", 1, "foo", 2, "bar", 3, "foobar", 10, "xxx", "yyy", "mark", "susi", "karl", "peter", 1, "foo", 2, "bar", 3, "foobar", 10, "xxx", "yyy"), "")
	check(d1.Capacity(), 25)
	check(d1.Count(), 25)
	check(d1.String(), "Deque[bla argl bart 1 foo 2 bar 3 foobar 10 xxx yyy mark susi karl peter 1 foo 2 bar 3 foobar 10 xxx yyy]")
	check(deque.New().String(), "Deque[]")
	check(deque.New([]interface{}{"foobar"}).String(), "Deque[foobar]")

	var stack deque.Deque
	check(Deque(&stack), "")
	check(stack.Capacity(), deque.CapacityDefault)
	stack.Push(1)
	stack.Push(2)
	stack.Push(3)
	stack.Push(4)
	stack.Push(5)
	check(Deque(&stack, 1, 2, 3, 4, 5), "")
	check(stack.Next(), 1)
	check(Deque(&stack, 2, 3, 4, 5), "")
	check(stack.Next(), 2)
	check(Deque(&stack, 3, 4, 5), "")
	check(stack.Pop(), 5)
	check(Deque(&stack, 3, 4), "")
	check(stack.Next(), 3)
	check(Deque(&stack, 4), "")
	check(stack.Pop().(int), 4)
	check(Deque(&stack), "")
	go func() {
		time.Sleep(1 * time.Second)
		stack.Insert("foo")
		time.Sleep(1 * time.Second)
		stack.Insert("bar")
	}()
	check(stack.Pop().(string), "foo")
	check(Deque(&stack), "")
	check(stack.Next(), "bar")
	check(Deque(&stack), "")

	check(Remove(11), "")
	check(Insert(11), "")

	deck := deque.New([]interface{}{1})
	check(Wait(deck, (*deque.Deque).WaitForItem, true, 0), "")
	check(Wait(deque.New(), (*deque.Deque).WaitForItem, false, 3*time.Second), "")
	deck.Init()
	go func() {
		time.Sleep(1 * time.Second)
		deck.Push(1)
	}()
	check(Wait(deck, (*deque.Deque).WaitForItem, true, 1*time.Second), "")
	deck.Init()
	go func() {
		time.Sleep(1 * time.Second)
		deck.Init()
	}()
	check(Wait(deck, (*deque.Deque).WaitForItem, false, 3*time.Second), "")
	go func() {
		time.Sleep(1 * time.Second)
		deck.Init([]interface{}{1, 2})
	}()
	check(Wait(deck, (*deque.Deque).WaitForItem, true, 1*time.Second), "")

	deck = deque.New(4, []interface{}{1, 2, 3}, deque.BlockIfFull)
	check(Wait(deck, (*deque.Deque).WaitForSpace, true, 0), "")
	deck.Push(4)
	check(Wait(deck, (*deque.Deque).WaitForSpace, false, 3*time.Second), "")
	go func() {
		time.Sleep(1 * time.Second)
		deck.Pop()
	}()
	check(Wait(deck, (*deque.Deque).WaitForSpace, true, 1*time.Second), "")
	deck.Push(1)
	go func() {
		time.Sleep(1 * time.Second)
		deck.Init(3, []interface{}{1, 2, 3})
	}()
	check(Wait(deck, (*deque.Deque).WaitForSpace, false, 3*time.Second), "")
	go func() {
		time.Sleep(1 * time.Second)
		deck.Init(4, []interface{}{1, 2, 3})
	}()
	check(Wait(deck, (*deque.Deque).WaitForSpace, true, 1*time.Second), "")

	check(Wait(deck, (*deque.Deque).WaitForEmpty, false, 3*time.Second), "")
	go func() {
		time.Sleep(1 * time.Second)
		deck.Pop()
		deck.Pop()
		deck.Pop()
	}()
	check(Wait(deck, (*deque.Deque).WaitForEmpty, true, 1*time.Second), "")
	check(Wait(deck, (*deque.Deque).WaitForEmpty, true, 0), "")
	deck.Push(1)
	go func() {
		time.Sleep(1 * time.Second)
		deck.Init(4, []interface{}{1, 2, 3})
	}()
	check(Wait(deck, (*deque.Deque).WaitForEmpty, false, 3*time.Second), "")
	go func() {
		time.Sleep(1 * time.Second)
		deck.Init(4)
	}()
	check(Wait(deck, (*deque.Deque).WaitForEmpty, true, 1*time.Second), "")

	for i := 0; i < 33; i++ {
		check(Overcapacity(i), "")
	}

	deck = deque.New(4)
	deck.Raw(2)
	check(deck.Overcapacity(0) == deck, true)
	check(Deque(deck), "")
	check(deck.Capacity(), 0)

	deck = deque.New(4)
	deck.Raw(5)
	check(deck.Overcapacity(10) == deck, true)
	check(Deque(deck), "")
	check(deck.Capacity(), 10)

	deck.Init(deque.BlockIfFull, []interface{}{1, 2, 3})
	go func() {
		time.Sleep(500 * time.Millisecond)
		check(Deque(deck, 1, 2, 3), "")
		check(deck.Capacity(), 3)
		deck.Overcapacity(1)
	}()
	deck.Push(4)
	check(Deque(deck, 1, 2, 3, 4), "")
	check(deck.Capacity(), 4)

	deck = deque.New()
	check(deck.Push(1), true)
	check(Deque(deck, 1), "")
	check(deck.Push(2), true)
	check(Deque(deck, 1, 2), "")
	check(deck.PushAt(-2, "x"), false)
	check(Deque(deck, 1, 2), "")
	check(deck.PushAt(-1, "x"), false)
	check(Deque(deck, 1, 2), "")
	check(deck.PushAt(3, "x"), false)
	check(Deque(deck, 1, 2), "")
	check(deck.PushAt(4, "x"), false)
	check(Deque(deck, 1, 2), "")
	check(deck.PushAt(0, "foo"), true)
	check(Deque(deck, 1, 2, "foo"), "")
	check(deck.PushAt(1, "bar"), true)
	check(Deque(deck, 1, 2, "bar", "foo"), "")
	check(deck.PushAt(4, "FOO"), true)
	check(Deque(deck, "FOO", 1, 2, "bar", "foo"), "")
	check(deck.PushAt(5, "BAR"), true)
	check(Deque(deck, "BAR", "FOO", 1, 2, "bar", "foo"), "")
	check(deck.PushAt(3, 1.5), true)
	check(Deque(deck, "BAR", "FOO", 1, 1.5, 2, "bar", "foo"), "")
	check(deck.Pop(), "foo")
	check(Deque(deck, "BAR", "FOO", 1, 1.5, 2, "bar"), "")
	check(deck.PopAt(0), "bar")
	check(Deque(deck, "BAR", "FOO", 1, 1.5, 2), "")
	check(deck.PopAt(5), nil)
	check(Deque(deck, "BAR", "FOO", 1, 1.5, 2), "")
	check(deck.PopAt(4), "BAR")
	check(Deque(deck, "FOO", 1, 1.5, 2), "")
	check(deck.PopAt(1), 1.5)
	check(Deque(deck, "FOO", 1, 2), "")
	deck = deque.New()
	go func() { time.Sleep(1 * time.Second); deck.Push("Yeah!") }()
	for i := -2; i <= 2; i++ {
		check(deck.PopAt(i), nil)
		check(Deque(deck), "")
	}
	check(deck.PopAt(0), nil)
	time.Sleep(2 * time.Second)
	check(deck.PopAt(0), "Yeah!")
	for i := 0; i < 50; i++ {
		go func() {
			p := deck.Pop().(string)
			if p != "MSB" {
				check(p, "MSB")
			}
		}()
	}
	for i = 0; i < 50; i++ {
		deck.Push("MSB")
		time.Sleep(100 * time.Millisecond)
	}

	deck = deque.New()
	check(deck.Insert(1), true)
	check(DequeReversed(deck, 1), "")
	check(deck.Insert(2), true)
	check(DequeReversed(deck, 1, 2), "")
	check(deck.InsertAt(-2, "x"), false)
	check(DequeReversed(deck, 1, 2), "")
	check(deck.InsertAt(-1, "x"), false)
	check(DequeReversed(deck, 1, 2), "")
	check(deck.InsertAt(3, "x"), false)
	check(DequeReversed(deck, 1, 2), "")
	check(deck.InsertAt(4, "x"), false)
	check(DequeReversed(deck, 1, 2), "")
	check(deck.InsertAt(0, "foo"), true)
	check(DequeReversed(deck, 1, 2, "foo"), "")
	check(deck.InsertAt(1, "bar"), true)
	check(DequeReversed(deck, 1, 2, "bar", "foo"), "")
	check(deck.InsertAt(4, "FOO"), true)
	check(DequeReversed(deck, "FOO", 1, 2, "bar", "foo"), "")
	check(deck.InsertAt(5, "BAR"), true)
	check(DequeReversed(deck, "BAR", "FOO", 1, 2, "bar", "foo"), "")
	check(deck.InsertAt(3, 1.5), true)
	check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2, "bar", "foo"), "")
	check(deck.Next(), "foo")
	check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2, "bar"), "")
	check(deck.RemoveAt(0), "bar")
	check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2), "")
	check(deck.RemoveAt(5), nil)
	check(DequeReversed(deck, "BAR", "FOO", 1, 1.5, 2), "")
	check(deck.RemoveAt(4), "BAR")
	check(DequeReversed(deck, "FOO", 1, 1.5, 2), "")
	check(deck.RemoveAt(1), 1.5)
	check(DequeReversed(deck, "FOO", 1, 2), "")
	deck = deque.New()
	go func() { time.Sleep(1 * time.Second); deck.Insert("Yeah!") }()
	for i := -2; i <= 2; i++ {
		check(deck.RemoveAt(i), nil)
		check(DequeReversed(deck), "")
	}
	check(deck.RemoveAt(0), nil)
	time.Sleep(2 * time.Second)
	check(deck.RemoveAt(0), "Yeah!")
	for i := 0; i < 50; i++ {
		go func() {
			p := deck.Next().(string)
			if p != "MSB" {
				check(p, "MSB")
			}
		}()
	}
	for i = 0; i < 50; i++ {
		deck.Insert("MSB")
		time.Sleep(100 * time.Millisecond)
	}

	deck.Init()
	check(deck.Remove(nil), 0)
	check(deck.Remove("foo"), 0)
	check(deck.Remove(nil, strcmp), 0)
	check(deck.Remove("foo", strcmp), 0)
	check(Deque(deck), "")
	deck.Push("foobar")
	check(deck.Remove(nil), 0)
	check(deck.Remove("foo"), 0)
	check(deck.Remove("foo", strcmp), 0)
	check(Deque(deck, "foobar"), "")
	tmp := []byte{0, 'o', 'o', 'b', 'a', 'r'}
	tmp[0] = 'f'
	check(deck.Remove(string(tmp), strcmp), 1)
	check(Deque(deck), "")
	deck.Push("foobar")
	check(deck.Remove(string(tmp)), 1)
	check(Deque(deck), "")
	deck.Init([]interface{}{"foobar", "foobar"})
	check(deck.Remove("foobar"), 2)
	check(Deque(deck), "")
	deck.Init([]interface{}{"foobar", "foobar"})
	check(deck.Remove("foobar", strcmp), 2)
	check(Deque(deck), "")
	deck.Init([]interface{}{"foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"})
	deck.Raw(5)
	check(deck.Remove("foobart"), 0)
	check(Deque(deck, "foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"), "")
	check(deck.Remove("foobar"), 4)
	check(Deque(deck, "a", "b", "c", "d", "e", "f"), "")
	deck.Init([]interface{}{"foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"})
	deck.Raw(5)
	check(deck.Remove("foobart", strcmp), 0)
	check(Deque(deck, "foobar", "a", "b", "foobar", "c", "foobar", "d", "e", "f", "foobar"), "")
	check(deck.Remove("foobar", strcmp), 4)
	check(Deque(deck, "a", "b", "c", "d", "e", "f"), "")
	var errormsg interface{}
	func() {
		defer func() { errormsg = recover() }()
		deck.Remove("foobar", strcmp, strcmp)
	}()
	check(errormsg, "Remove() takes 1 or 2 parameters")

	func() {
		defer func() { errormsg = recover() }()
		deck.Init(nil)
	}()
	check(errormsg, "Argument #1 is unsupported by deque.Init()")

	func() {
		defer func() { errormsg = recover() }()
		deck.Init(stack) // stack is not a pointer. That's why this doesn't work.
	}()
	check(errormsg, "Argument #1 is unsupported by deque.Init()")

	growth := func(uint, uint, uint) uint { return 10 }
	var uninitialized deque.Deque
	check(Deque(deque.New(&uninitialized, &uninitialized)), "")
	d1 = deque.New([]interface{}{1, 2, 3, 4, 5}, 10)
	d1.Raw(6)
	d2 = deque.New([]interface{}{6, 7, 8})
	d3 := deque.New([]interface{}{}, 4)
	deck.Init(&uninitialized, d1, d2, d3, []interface{}{"a", "b", "c", "d"}, []interface{}{"e", "f", "g", "h"}, growth)
	check(Deque(deck, 1, 2, 3, 4, 5, 6, 7, 8, "a", "b", "c", "d", "e", "f", "g", "h"), "")
	deck.Init([]interface{}{"a", "b", "c", "d"}, []interface{}{"e", "f", "g", "h"}, growth, d1, d2)
	check(Deque(deck, "a", "b", "c", "d", "e", "f", "g", "h", 1, 2, 3, 4, 5, 6, 7, 8), "")

	check(deque.New(0).Capacity(), 0)
	check(deque.New(1).Capacity(), 1)
	check(deque.New(-100).Capacity(), deque.CapacityDefault)
	check(deque.New(3, []interface{}{}).Capacity(), 3)
	check(deque.New(int64(3), []interface{}{1}).Capacity(), 3)
	check(deque.New(uint(3), []interface{}{1, 2}).Capacity(), 3)
	check(deque.New(uint64(3), []interface{}{1, 2}).Capacity(), 3)
	check(deque.New(uint64(3), []interface{}{1, 2, 3}).Capacity(), 3)
	check(deque.New(3, []interface{}{1, 2, 3, 4}).Capacity(), 4)
	check(deque.New(3, []interface{}{1, 2}, []interface{}{3, 4}).Capacity(), 4)

	deck.Init(3, []interface{}{1, 2}, []interface{}{3, 4})
	deck.Clear()
	check(deck.Capacity(), deque.CapacityDefault)
	check(deck.Count(), 0)

	deck.Init([]interface{}{0, 1, 2, 3, 4, 5})
	deck.Raw(3) // 3,4,5,[b][a]0,1,2
	check(deck.RemoveAt(-1), nil)
	check(deck.RemoveAt(deck.Count()), nil)
	check(deck.RemoveAt(3), 3) // 2,4,5,[b]_,[a]0,1
	check(Deque(deck, 0, 1, 2, 4, 5), "")
	check(deck.RemoveAt(2), 2) // 1,4,5,[b]_,_,[a]0
	check(Deque(deck, 0, 1, 4, 5), "")
	check(deck.RemoveAt(2), 4) // [a]0,1,5,[b]_,_,_
	check(Deque(deck, 0, 1, 5), "")

	deck.Init([]interface{}{0, 1, 2, 3, 4, 5})
	deck.Raw(3)                  // 3,4,5,[b][a]0,1,2
	check(deck.RemoveAt(0), "0") // 3,4,5,[b]_,[a]1,2
	check(Deque(deck, 1, 2, 3, 4, 5), "")

	deck.Init([]interface{}{0, 1, 2, 3, 4, 5})
	deck.Raw(3)                  // 3,4,5,[b][a]0,1,2
	check(deck.RemoveAt(4), "4") // 3,5,[b]_,[a]0,1,2
	check(Deque(deck, 0, 1, 2, 3, 5), "")

	deck.Init([]interface{}{0, 1, 2, 3, 4, 5, 6, 7})
	deck.Raw(2)                  // 6,7,[b][a]0,1,2,3,4,5
	check(deck.RemoveAt(7), "7") // 6,[b]_,[a]0,1,2,3,4,5
	check(Deque(deck, 0, 1, 2, 3, 4, 5, 6), "")
	check(deck.RemoveAt(4), "4") // [b]_,_,[a]0,1,2,3,5,6
	check(Deque(deck, 0, 1, 2, 3, 5, 6), "")
	check(deck.RemoveAt(5), "6") // _,_,[a]0,1,2,3,5,[b]_
	check(Deque(deck, 0, 1, 2, 3, 5), "")

	deck.Init([]interface{}{0, 1, 2, 3, 4, 5, 6, 7})
	deck.Overcapacity(4)         // [a]0,1,2,3,4,5,6,7,[b]_,_,_,_
	deck.Raw(2)                  // _,_,[a]0,1,2,3,4,5,6,7,[b]_,_
	check(deck.RemoveAt(6), "6") // _,_,[a]0,1,2,3,4,5,7,[b]_,_,_
	check(Deque(deck, 0, 1, 2, 3, 4, 5, 7), "")
	check(deck.RemoveAt(2), "2") // _,_,_,[a]0,1,3,4,5,7,[b]_,_,_
	check(Deque(deck, 0, 1, 3, 4, 5, 7), "")

	deck.Init([]interface{}{}, deque.GrowBy(1))
	check(deck.InsertAt(-1, "foo"), false)
	check(deck.InsertAt(1, "foo"), false)
	check(deck.InsertAt(0, 11), true)
	check(Deque(deck, 11), "")
	deck.Init(deck, deque.BlockIfFull)
	go func() { time.Sleep(1 * time.Second); deck.Pop() }()
	check(deck.InsertAt(0, 22), true)
	check(Deque(deck, 22), "")

	deck.Init([]interface{}{0, 1, 2}, deque.GrowBy(1))
	check(deck.InsertAt(0, -1), true)
	check(Deque(deck, -1, 0, 1, 2), "")
	deck.Init([]interface{}{0, 1, 2}, deque.GrowBy(1))
	deck.Raw(1)
	check(deck.InsertAt(0, -1), true)
	check(Deque(deck, -1, 0, 1, 2), "")
	deck.Init([]interface{}{0, 1, 2}, deque.GrowBy(1))
	deck.Raw(2)
	check(deck.InsertAt(0, -1), true)
	check(Deque(deck, -1, 0, 1, 2), "")

	deck.Init(0, deque.GrowBy(2))
	go func() {
		time.Sleep(500 * time.Millisecond)
		deck.InsertAt(0, 0)
	}()
	check(deck.Capacity(), 0)
	check(deck.WaitForSpace(2*time.Second), true)
	check(deck.Capacity(), 2)

	deck.Init([]interface{}{0, 1, 2, 3, 4, 5, 6, 7}, deque.BlockIfFull)
	go func() {
		time.Sleep(500 * time.Millisecond)
		deck.Init([]interface{}{0, 1}, 3)
	}()
	check(deck.Push(2), true)
	check(Deque(deck, 0, 1, 2), "")

	deck.Init(0, deque.DropFarEndIfOverflow)
	check(deck.Push("should be discarded"), false)
	check(Deque(deck), "")

	deck.Init([]interface{}{0}, deque.DropFarEndIfOverflow)
	check(deck.PushAt(0, 1), true)
	check(Deque(deck, 1), "")
	check(deck.PushAt(1, 2), true)
	check(Deque(deck, 2), "")

	deck.Init([]interface{}{3, 5}, deque.DropFarEndIfOverflow)
	check(deck.InsertAt(0, 1), true)
	check(Deque(deck, 1, 3), "")
	check(deck.InsertAt(1, 2), true)
	if deck.At(0).(int) == 2 {
		check(Deque(deck, 2, 3), "")
	} else {
		check(Deque(deck, 1, 2), "")
	}

	deck.Init([]interface{}{3, 5}, deque.DropFarEndIfOverflow)
	deck.Raw(1)
	check(deck.InsertAt(0, 1), true)
	check(Deque(deck, 1, 3), "")
	check(deck.InsertAt(1, 2), true)
	if deck.At(0).(int) == 2 {
		check(Deque(deck, 2, 3), "")
	} else {
		check(Deque(deck, 1, 2), "")
	}

	deck.Init([]interface{}{1, 3, 5}, deque.DropFarEndIfOverflow)
	check(deck.InsertAt(1, 2), true)
	check(Deque(deck, 1, 2, 3), "")
	check(deck.InsertAt(2, 2.5), true)
	check(Deque(deck, 2, 2.5, 3), "")

	deck.Init(0, deque.DropItemIfOverflow)
	check(deck.InsertAt(1, 2), false)
	check(deck.Insert(2), false)
	check(deck.Push(2), false)
	check(Deque(deck), "")

	deck.Init([]interface{}{1, 2, 3}, deque.DropItemIfOverflow)
	check(deck.InsertAt(1, 2), false)
	check(deck.Insert(2), false)
	check(deck.Push(2), false)
	check(Deque(deck, 1, 2, 3), "")

	deck.Init(0, deque.GrowBy(1))
	check(deck.Push(42), true)
	check(deck.Push(43), true)
	check(Deque(deck, 42, 43), "")

	deck.Init(0, deque.GrowBy(2))
	go func() {
		deck.WaitForSpace(0)
		deck.Push(2)
	}()
	time.Sleep(500 * time.Millisecond)
	check(deck.Push(1), true)
	time.Sleep(500 * time.Millisecond)
	check(deck.Push(3), true)
	check(Deque(deck, 1, 2, 3), "")
	check(deck.Capacity(), 4)

	deck.Init([]interface{}{0, 1}, 3)
	deck.Raw(2)
	check(deck.Push(2), true)
	check(Deque(deck, 0, 1, 2), "")

	deck.Init(3)
	go func() {
		deck.WaitForItem(0)
		deck.Push(2)
	}()
	time.Sleep(500 * time.Millisecond)
	check(deck.Push(1), true)
	time.Sleep(500 * time.Millisecond)
	deck.Push(3)
	deck.Push(4)
	deck.Push(5)
	check(deck.InsertAt(2, 2.5), true)
	check(Deque(deck, 1, 2, 2.5, 3, 4, 5), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5}, 7)
	check(deck.InsertAt(0, -1), true)
	check(Deque(deck, -1, 1, 2, 3, 4, 5), "")

	deck.Raw(0)
	check(deck.InsertAt(4, 3.5), true)
	check(Deque(deck, -1, 1, 2, 3, 3.5, 4, 5), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5}, 10)
	deck.Raw(8)
	check(deck.InsertAt(2, 2.5), true)
	check(Deque(deck, 1, 2, 2.5, 3, 4, 5), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7}, 10)
	deck.Raw(8)
	check(deck.InsertAt(3, 3.5), true)
	check(Deque(deck, 1, 2, 3, 3.5, 4, 5, 6, 7), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 12)
	deck.Raw(10)
	check(deck.InsertAt(4, 4.5), true)
	check(Deque(deck, 1, 2, 3, 4, 4.5, 5, 6, 7, 8, 9, 10), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 12)
	deck.Raw(10)
	check(deck.InsertAt(5, 5.5), true)
	check(Deque(deck, 1, 2, 3, 4, 5, 5.5, 6, 7, 8, 9, 10), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 12)
	deck.Raw(5)
	check(deck.InsertAt(6, 6.5), true)
	check(Deque(deck, 1, 2, 3, 4, 5, 6, 6.5, 7, 8, 9, 10), "")

	deck.Init([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11)
	deck.Raw(5)
	check(deck.InsertAt(5, 5.5), true)
	check(Deque(deck, 1, 2, 3, 4, 5, 5.5, 6, 7, 8, 9, 10), "")

	check(Search(2), 0)
	check(Search(2, 1), 1)
	check(Search(2, 2), 0)
	check(Search(2, 3), 0)
	check(Search(2, 1, 2), 1)
	check(Search(2, 2, 2), 0)
	check(Search(2, 1, 1), 2)
	check(Search(2, 3, 4), 0)
	check(Search(2, 2, 3, 4), 0)
	check(Search(2, 1, 1, 2), 2)
	check(Search(2, 1, 1, 1), 3)
	check(Search(2, 1, 2, 3), 1)
	check(Search(2, 3, 4, 5, 6), 0)
	check(Search(2, 2, 3, 4, 5), 0)
	check(Search(2, 1, 2, 3, 4), 1)
	check(Search(2, 1, 3, 4, 5), 1)
	check(Search(2, 1, 1, 4, 5), 2)
	check(Search(2, 1, 1, 2, 5), 2)
	check(Search(2, 1, 1, 1, 5), 3)
	check(Search(2, 1, 1, 1, 2), 3)
	check(Search(2, 1, 1, 1, 1), 4)
	check(Search(2, 2, 2, 2, 2), 0)

	deck.Init(deque.DropItemIfOverflow, 0)
	check(deck.InsertSorted(42, intcmp), -1)

	deck.Init(deque.BlockIfFull, 0)
	go func() {
		time.Sleep(500 * time.Millisecond)
		deck.Init([]interface{}{1, 2, 3, 4, 5, 6}, 10, deque.BlockIfFull)
	}()
	check(deck.InsertSorted(3, intcmp), 2)
	check(Deque(deck, 1, 2, 3, 3, 4, 5, 6), "")

	check(deck.InsertSorted(5, intcmp), 5)
	check(Deque(deck, 1, 2, 3, 3, 4, 5, 5, 6), "")
}
Ejemplo n.º 4
0
// Parses the relevant configuration files and sets
// the config variables accordingly.
func ReadConfig() {
	conf := map[string]map[string]string{"": map[string]string{}}

	var tftp_mappings deque.Deque

	// [general]/pxelinux-cfg-hook is deprecated and only supported for
	// backwards compatibility. It will be converted to patterns later.
	// That's why this is a local variable and not a global one.
	pxeLinuxCfgHookPath := "/usr/lib/go-susi/generate_pxelinux_cfg"

	for _, configfile := range []string{ClientConfigPath, ServerConfigPath} {
		if configfile == "" {
			continue
		}
		file, err := os.Open(configfile)
		if err != nil {
			if os.IsNotExist(err) {
				/* File does not exist is not an error that needs to be reported */
			} else {
				util.Log(0, "ERROR! ReadConfig: %v", err)
			}
			continue
		}
		defer file.Close()
		input := bufio.NewReader(file)

		current_section := ""
		for {
			var line string
			line, err = input.ReadString('\n')
			if err != nil {
				break
			}

			if comment := strings.Index(line, "#"); comment >= 0 {
				line = line[0:comment]
			}

			line = strings.TrimSpace(line)
			if len(line) > 2 && line[0] == '[' && line[len(line)-1] == ']' {
				current_section = line
				if _, ok := conf[current_section]; !ok {
					conf[current_section] = map[string]string{}
				}
			}

			i := strings.Index(line, "=")
			if i >= 0 {
				key := strings.TrimSpace(line[0:i])
				value := strings.TrimSpace(line[i+1:])
				if key != "" {
					if current_section == "[tftp]" && key[0] == '/' && len(key) >= 2 {
						tftp_mappings.Push(key[1:])
						tftp_mappings.Push(value)
					} else {
						conf[current_section][key] = value
					}
				}
			}
		}

		if err != io.EOF {
			util.Log(0, "ERROR! ReadConfig: %v", err)
			// Do not return. Try working with whatever we got out of the file.
		}
	}

	for sectionname, section := range conf {
		if sectkey, ok := section["key"]; ok {
			ModuleKeys = append(ModuleKeys, sectkey)
			ModuleKey[sectionname] = sectkey
		}
	}

	TLSRequired = len(ModuleKey) == 0

	if general, ok := conf["[general]"]; ok {
		if logfile, ok := general["log-file"]; ok {
			LogFilePath = logfile
		}
		if failogdir, ok := general["fai-log-dir"]; ok {
			FAILogPath = failogdir
		}
		if kernel_list_hook, ok := general["kernel-list-hook"]; ok {
			KernelListHookPath = kernel_list_hook
		}
		if package_list_hook, ok := general["package-list-hook"]; ok {
			PackageListHookPath = package_list_hook
		}
		if user_msg_hook, ok := general["user-msg-hook"]; ok {
			UserMessageHookPath = user_msg_hook
		}
		if pxelinux_cfg_hook, ok := general["pxelinux-cfg-hook"]; ok {
			pxeLinuxCfgHookPath = pxelinux_cfg_hook
		}
		if new_config_hook, ok := general["new-config-hook"]; ok {
			NewConfigHookPath = new_config_hook
		}
		if trigger_action_hook, ok := general["trigger-action-hook"]; ok {
			TriggerActionHookPath = trigger_action_hook
		}
		if registered_hook, ok := general["registered-hook"]; ok {
			RegisteredHookPath = registered_hook
		}
		if activated_hook, ok := general["activated-hook"]; ok {
			ActivatedHookPath = activated_hook
		}
		if detect_hardware_hook, ok := general["detect-hardware-hook"]; ok {
			DetectHardwareHookPath = detect_hardware_hook
		}
		if fai_progress, ok := general["fai-progress-hook"]; ok {
			FAIProgressHookPath = fai_progress
		}
		if fai_savelog, ok := general["fai-savelog-hook"]; ok {
			FAISavelogHookPath = fai_savelog
		}
	}

	if server, ok := conf["[server]"]; ok {

		if dnslookup, ok := server["dns-lookup"]; ok {
			dnslookup = strings.TrimSpace(dnslookup)
			if dnslookup != "false" && dnslookup != "true" {
				util.Log(0, "ERROR! ReadConfig: [server]/dns-lookup must be \"true\" or \"false\", not \"%v\"", dnslookup)
			}
			DNSLookup = (dnslookup == "true")
		}

		if port, ok := server["port"]; ok {
			port = strings.TrimSpace(port)
			i := strings.Index(ServerSourceAddress, ":")
			ServerSourceAddress = ServerSourceAddress[:i+1] + port
			i = strings.Index(ServerListenAddress, ":")
			ServerListenAddress = ServerListenAddress[:i+1] + port
		}

		if ip, ok := server["ip"]; ok {
			PreferredServer = ip
		}
		if uri, ok := server["ldap-uri"]; ok {
			LDAPURI = uri
		}
		if base, ok := server["ldap-base"]; ok {
			LDAPBase = base
		}
		if newsysbase, ok := server["new-systems-base"]; ok {
			IncomingOU = newsysbase
		}
		if IncomingOU[len(IncomingOU)-1] == ',' {
			IncomingOU += LDAPBase
		}
		if admin, ok := server["ldap-admin-dn"]; ok {
			LDAPAdmin = admin
		}
		if pw, ok := server["ldap-admin-password"]; ok {
			err := ioutil.WriteFile(LDAPAdminPasswordFile, []byte(pw), 0600)
			if err != nil {
				util.Log(0, "ERROR! Could not write admin password to file: %v", err)
			}
		}
		if user, ok := server["ldap-user-dn"]; ok {
			LDAPUser = user
		}
		if pw, ok := server["ldap-user-password"]; ok {
			err := ioutil.WriteFile(LDAPUserPasswordFile, []byte(pw), 0600)
			if err != nil {
				util.Log(0, "ERROR! Could not write user password to file: %v", err)
			}
		}
	}

	if client, ok := conf["[client]"]; ok {
		if port, ok := client["port"]; ok {
			ClientPorts = strings.Fields(strings.Replace(port, ",", " ", -1))
		}
	}

	if faimon, ok := conf["[faimon]"]; ok {
		if port, ok := faimon["port"]; ok {
			FAIMonPort = port
		}
	}

	if tftp, ok := conf["[tftp]"]; ok {
		if port, ok := tftp["port"]; ok {
			TFTPPort = port
		}
	}

	if tlsconf, ok := conf["[tls]"]; ok {
		if cacert, ok := tlsconf["ca-certificate"]; ok {
			CACertPath = []string{cacert}
		}
		if cert, ok := tlsconf["certificate"]; ok {
			CertPath = cert
		}
		if certkey, ok := tlsconf["keyfile"]; ok {
			CertKeyPath = certkey
		}
	}

	// Backwards compatibility: Convert [general]/pxelinux-cfg-hook to patterns
	// as described in manual.
	if pxeLinuxCfgHookPath != "" {
		tftp_mappings.Insert("|" + pxeLinuxCfgHookPath)
		tftp_mappings.Insert("^pxelinux.cfg/01-(?P<macaddress>[0-9a-f]{2}(-[0-9a-f]{2}){5})$")
		tftp_mappings.Insert("")
		tftp_mappings.Insert("/^pxelinux.cfg/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$")
	}

	for !tftp_mappings.IsEmpty() {
		file := tftp_mappings.Pop().(string)
		pattern := tftp_mappings.Pop().(string)
		if pattern[0] != '^' {
			pattern = "^" + regexp.QuoteMeta(pattern) + "$"
			file = strings.Replace(file, "$", "$$", -1)
		}
		re, err := regexp.Compile(pattern)
		if err != nil {
			util.Log(0, "ERROR! ReadConfig: In section [tftp]: Error compiling regex \"%v\": %v", pattern, err)
		} else {
			TFTPRegexes = append(TFTPRegexes, re)
			TFTPReplies = append(TFTPReplies, file)
		}
	}

	// The [ServerPackages] section must be evaluated AFTER the [server]
	// section, because the manual says that [ServerPackages]/dns-lookup takes
	// precedence over [server]/dns-lookup.
	if serverpackages, ok := conf["[ServerPackages]"]; ok {
		if addresses, ok := serverpackages["address"]; ok && addresses != "" {
			PeerServers = append(PeerServers, strings.Fields(strings.Replace(addresses, ",", " ", -1))...)
		}
		if dnslookup, ok := serverpackages["dns-lookup"]; ok {
			dnslookup = strings.TrimSpace(dnslookup)
			if dnslookup != "false" && dnslookup != "true" {
				util.Log(0, "ERROR! ReadConfig: [ServerPackages]/dns-lookup must be \"true\" or \"false\", not \"%v\"", dnslookup)
			}
			DNSLookup = (dnslookup == "true")
		}
		if lookupdomains, ok := serverpackages["domains"]; ok {
			for _, dom := range strings.Fields(strings.Replace(lookupdomains, ",", " ", -1)) {
				if dom[0] != '.' {
					dom = "." + dom
				}
				LookupDomains = append(LookupDomains, dom)
			}
		}
	}

	if LDAPAdmin == "" {
		RunServer = false
	}

	ClientPorts = append(ClientPorts, ServerListenAddress[strings.Index(ServerListenAddress, ":")+1:])

	if PreferredServer != "" && strings.Index(PreferredServer, ":") < 0 {
		PreferredServer += ServerListenAddress[strings.Index(ServerListenAddress, ":"):]
	}

	serversInConfigFile := make([]string, len(PeerServers))
	copy(serversInConfigFile, PeerServers)
	if PreferredServer != "" {
		serversInConfigFile = append(serversInConfigFile, PreferredServer)
	}

	for _, srv := range serversInConfigFile {
		prefhost, _, err := net.SplitHostPort(srv)
		if err == nil {
			prefip := net.ParseIP(prefhost)
			if prefip != nil {
				ServerIPsFromConfigFile = append(ServerIPsFromConfigFile, prefip)
			} else {
				ServerNamesFromConfigFile = append(ServerNamesFromConfigFile, prefhost)
			}
		}
	}

	file, err := os.Open(ServersOUConfigPath)
	if err != nil {
		if os.IsNotExist(err) {
			/* File does not exist is not an error that needs to be reported */
		} else {
			util.Log(0, "ERROR! ReadConfig: %v", err)
		}
	} else {
		defer file.Close()
		input := bufio.NewReader(file)
		for {
			var line string
			line, err = input.ReadString('\n')
			if err != nil {
				break
			}
			line = strings.TrimSpace(line)
			if line != "" {
				LDAPServerOUs = append(LDAPServerOUs, line)
			}
		}
	}
}