Nil checks and a greatly simplified filter manager which is less buggy.
authorChris Jones <chris@cjones.org>
Mon, 02 Jan 2012 13:18:48 -0700
changeset 51 1af366d10d32
parent 50 08d2b9deb710
child 52 9b664fde0ec3
Nil checks and a greatly simplified filter manager which is less buggy.
stream.go
structs.go
xmpp.go
--- a/stream.go	Mon Jan 02 10:01:41 2012 -0700
+++ b/stream.go	Mon Jan 02 13:18:48 2012 -0700
@@ -286,6 +286,10 @@
 				break
 			}
 		case x := <- input:
+			if x == nil {
+				log.Println("Refusing to send nil stanza")
+				continue
+			}
 			srvOut <- x
 		}
 	}
@@ -293,50 +297,32 @@
 
 // Stanzas from the remote go up through a stack of filters to the
 // app. This function manages the filters.
-func filter(srvIn2 <-chan Stanza, cliOut2 chan<- Stanza,
-	filterOut <-chan <-chan Stanza, filterIn chan<- <-chan Stanza) {
-	defer close(cliOut2)
-	var srvIn1, topFilterOut1, topFilterOut2 <-chan Stanza
-	var cliOut1, botFilterIn1, botFilterIn2 chan<- Stanza
-	ch := make(chan Stanza, 1)
-	topFilterOut2 = ch
-	botFilterIn2 = ch
-	topFilterOut1 = topFilterOut2
-	srvIn1 = srvIn2
-	var botItem Stanza
-	var topItem Stanza
-	var ok bool
+func filterTop(filterOut <-chan <-chan Stanza, filterIn chan<- <-chan Stanza,
+	topFilter <-chan Stanza, app chan<- Stanza) {
+	defer close(app)
 	for {
 		select {
 		case newFilterOut := <- filterOut:
-			filterIn <- topFilterOut2
-			topFilterOut2 = newFilterOut
-			if topFilterOut1 != nil {
-				topFilterOut1 = topFilterOut2
+			if newFilterOut == nil {
+				log.Println("Received nil filter")
+				filterIn <- nil
+				continue
 			}
+			filterIn <- topFilter
 
-		case topItem, ok = <-topFilterOut1:
+		case data, ok := <-topFilter:
 			if !ok {
 				break
 			}
-			topFilterOut1 = nil
-			cliOut1 = cliOut2
-		case cliOut1 <- topItem:
-			topFilterOut1 = topFilterOut2
-			cliOut1 = nil
+			app <- data
+		}
+	}
+}
 
-		case botItem, ok = <-srvIn1:
-			if !ok {
-				close(botFilterIn2)
-				srvIn1 = nil
-				continue
-			}
-			srvIn1 = nil
-			botFilterIn1 = botFilterIn2
-		case botFilterIn1 <- botItem:
-			srvIn1 = srvIn2
-			botFilterIn1 = nil
-		}
+func filterBottom(from <-chan Stanza, to chan<- Stanza) {
+	defer close(to)
+	for data := range(from) {
+		to <- data
 	}
 }
 
--- a/structs.go	Mon Jan 02 10:01:41 2012 -0700
+++ b/structs.go	Mon Jan 02 13:18:48 2012 -0700
@@ -271,6 +271,9 @@
 }
 
 func (u *Generic) String() string {
+	if u == nil {
+		return "nil"
+	}
 	var sub string
 	if u.Any != nil {
 		sub = u.Any.String()
--- a/xmpp.go	Mon Jan 02 10:01:41 2012 -0700
+++ b/xmpp.go	Mon Jan 02 13:18:48 2012 -0700
@@ -200,7 +200,9 @@
 	cliOut := make(chan Stanza)
 	filterOut := make(chan (<-chan Stanza))
 	filterIn := make(chan (<-chan Stanza))
-	go filter(srvIn, cliOut, filterOut, filterIn)
+	nullFilter := make(chan Stanza)
+	go filterBottom(srvIn, nullFilter)
+	go filterTop(filterOut, filterIn, nullFilter, cliOut)
 	cl.filterOut = filterOut
 	cl.filterIn = filterIn
 	return cliOut