// 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 } } }
/* 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 } } } }
// 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), "") }
// 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) } } } }