Step 3 of converting to interface Stanza and embedded struct Header.
authorChris Jones <chris@cjones.org>
Sun, 16 Dec 2012 23:06:54 -0700
changeset 113 bee6cc131798
parent 112 bd56fb741f69
child 114 a058e33c1666
Step 3 of converting to interface Stanza and embedded struct Header.
examples/interact.go
roster.go
stream.go
xmpp.go
--- a/examples/interact.go	Sun Dec 16 22:37:57 2012 -0700
+++ b/examples/interact.go	Sun Dec 16 23:06:54 2012 -0700
@@ -63,7 +63,7 @@
 		fmt.Printf("%d: %v\n", i, entry)
 	}
 
-	go func(ch <-chan interface{}) {
+	go func(ch <-chan xmpp.Stanza) {
 		for obj := range ch {
 			fmt.Printf("s: %v\n", obj)
 		}
@@ -89,7 +89,7 @@
 			fmt.Println("Couldn't find start element")
 			break
 		}
-		var stan interface{}
+		var stan xmpp.Stanza
 		switch se.Name.Local {
 		case "iq":
 			stan = &xmpp.Iq{}
--- a/roster.go	Sun Dec 16 22:37:57 2012 -0700
+++ b/roster.go	Sun Dec 16 23:06:54 2012 -0700
@@ -51,7 +51,7 @@
 	iq := &Iq{Header: Header{From: client.Jid.String(), Type: "get",
 		Id: <-Id, Nested: []interface{}{RosterQuery{}}}}
 	ch := make(chan error)
-	f := func(v interface{}) bool {
+	f := func(v Stanza) bool {
 		defer close(ch)
 		iq, ok := v.(*Iq)
 		if !ok {
@@ -91,9 +91,9 @@
 // the roster feeder, which is the goroutine that provides data on
 // client.Roster.
 func startRosterFilter(client *Client) {
-	out := make(chan interface{})
+	out := make(chan Stanza)
 	in := client.AddFilter(out)
-	go func(in <-chan interface{}, out chan<- interface{}) {
+	go func(in <-chan Stanza, out chan<- Stanza) {
 		defer close(out)
 		for st := range in {
 			maybeUpdateRoster(client, st)
--- a/stream.go	Sun Dec 16 22:37:57 2012 -0700
+++ b/stream.go	Sun Dec 16 23:06:54 2012 -0700
@@ -29,7 +29,7 @@
 type stanzaHandler struct {
 	id string
 	// Return true means pass this to the application
-	f func(interface{}) bool
+	f func(Stanza) bool
 }
 
 // BUG(cjyar) Review all these *Client receiver methods. They should
@@ -225,10 +225,10 @@
 	}
 }
 
-func (cl *Client) readStream(srvIn <-chan interface{}, cliOut chan<- interface{}) {
+func (cl *Client) readStream(srvIn <-chan interface{}, cliOut chan<- Stanza) {
 	defer close(cliOut)
 
-	handlers := make(map[string]func(interface{}) bool)
+	handlers := make(map[string]func(Stanza) bool)
 Loop:
 	for {
 		select {
@@ -238,7 +238,6 @@
 			if !ok {
 				break Loop
 			}
-			var st *Header
 			switch obj := x.(type) {
 			case *stream:
 				handleStream(obj)
@@ -251,24 +250,19 @@
 			case *auth:
 				cl.handleSasl(obj)
 			case Stanza:
-				st = obj.GetHeader()
+				send := true
+				id := obj.GetHeader().Id
+				if handlers[id] != nil {
+					f := handlers[id]
+					delete(handlers, id)
+					send = f(obj)
+				}
+				if send {
+					cliOut <- obj
+				}
 			default:
 				Warn.Logf("Unhandled non-stanza: %T %#v", x, x)
 			}
-
-			if st == nil {
-				continue
-			}
-
-			send := true
-			if handlers[st.Id] != nil {
-				f := handlers[st.Id]
-				delete(handlers, st.Id)
-				send = f(x)
-			}
-			if send {
-				cliOut <- x
-			}
 		}
 	}
 }
@@ -277,11 +271,11 @@
 // the app might inject something inappropriate into our negotiations
 // with the server. The control channel controls this loop's
 // activity.
-func writeStream(srvOut chan<- interface{}, cliIn <-chan interface{},
+func writeStream(srvOut chan<- interface{}, cliIn <-chan Stanza,
 control <-chan int) {
 	defer close(srvOut)
 
-	var input <-chan interface{}
+	var input <-chan Stanza
 Loop:
 	for {
 		select {
@@ -309,8 +303,8 @@
 
 // Stanzas from the remote go up through a stack of filters to the
 // app. This function manages the filters.
-func filterTop(filterOut <-chan <-chan interface{}, filterIn chan<- <-chan interface{},
-topFilter <-chan interface{}, app chan<- interface{}) {
+func filterTop(filterOut <-chan <-chan Stanza, filterIn chan<- <-chan Stanza,
+topFilter <-chan Stanza, app chan<- Stanza) {
 	defer close(app)
 Loop:
 	for {
@@ -333,7 +327,7 @@
 	}
 }
 
-func filterBottom(from <-chan interface{}, to chan<- interface{}) {
+func filterBottom(from <-chan Stanza, to chan<- Stanza) {
 	defer close(to)
 	for data := range from {
 		to <- data
@@ -598,7 +592,7 @@
 	}
 	msg := &Iq{Header: Header{Type: "set", Id: <-Id,
 		Nested: []interface{}{bindReq}}}
-	f := func(st interface{}) bool {
+	f := func(st Stanza) bool {
 		iq, ok := st.(*Iq)
 		if !ok {
 			Warn.Log("non-iq response")
@@ -643,7 +637,7 @@
 // available on the normal Client.In channel. The stanza handler
 // must not read from that channel, as deliveries on it cannot proceed
 // until the handler returns true or false.
-func (cl *Client) HandleStanza(id string, f func(interface{}) bool) {
+func (cl *Client) HandleStanza(id string, f func(Stanza) bool) {
 	h := &stanzaHandler{id: id, f: f}
 	cl.handlers <- h
 }
--- a/xmpp.go	Sun Dec 16 22:37:57 2012 -0700
+++ b/xmpp.go	Sun Dec 16 23:06:54 2012 -0700
@@ -82,18 +82,18 @@
 	// Incoming XMPP stanzas from the server will be published on
 	// this channel. Information which is only used by this
 	// library to set up the XMPP stream will not appear here.
-	In <-chan interface{}
+	In <-chan Stanza
 	// Outgoing XMPP stanzas to the server should be sent to this
 	// channel.
-	Out    chan<- interface{}
+	Out    chan<- Stanza
 	xmlOut chan<- interface{}
 	// Features advertised by the remote. This will be updated
 	// asynchronously as new features are received throughout the
 	// connection process. It should not be updated once
 	// StartSession() returns.
 	Features  *Features
-	filterOut chan<- <-chan interface{}
-	filterIn  <-chan <-chan interface{}
+	filterOut chan<- <-chan Stanza
+	filterIn  <-chan <-chan Stanza
 }
 
 // Connect to the appropriate server and authenticate as the given JID
@@ -200,23 +200,23 @@
 	return ch
 }
 
-func (cl *Client) startStreamReader(xmlIn <-chan interface{}, srvOut chan<- interface{}) <-chan interface{} {
-	ch := make(chan interface{})
+func (cl *Client) startStreamReader(xmlIn <-chan interface{}, srvOut chan<- interface{}) <-chan Stanza {
+	ch := make(chan Stanza)
 	go cl.readStream(xmlIn, ch)
 	return ch
 }
 
-func (cl *Client) startStreamWriter(xmlOut chan<- interface{}) chan<- interface{} {
-	ch := make(chan interface{})
+func (cl *Client) startStreamWriter(xmlOut chan<- interface{}) chan<- Stanza {
+	ch := make(chan Stanza)
 	go writeStream(xmlOut, ch, cl.inputControl)
 	return ch
 }
 
-func (cl *Client) startFilter(srvIn <-chan interface{}) <-chan interface{} {
-	cliIn := make(chan interface{})
-	filterOut := make(chan (<-chan interface{}))
-	filterIn := make(chan (<-chan interface{}))
-	nullFilter := make(chan interface{})
+func (cl *Client) startFilter(srvIn <-chan Stanza) <-chan Stanza {
+	cliIn := make(chan Stanza)
+	filterOut := make(chan (<-chan Stanza))
+	filterIn := make(chan (<-chan Stanza))
+	nullFilter := make(chan Stanza)
 	go filterBottom(srvIn, nullFilter)
 	go filterTop(filterOut, filterIn, nullFilter, cliIn)
 	cl.filterOut = filterOut
@@ -272,7 +272,7 @@
 		Nested: []interface{}{Generic{XMLName:
 			xml.Name{Space: NsSession, Local: "session"}}}}}
 	ch := make(chan error)
-	f := func(st interface{}) bool {
+	f := func(st Stanza) bool {
 		iq, ok := st.(*Iq)
 		if !ok {
 			Warn.Log("iq reply not iq; can't start session")
@@ -311,7 +311,7 @@
 // filter's output channel is given to this function, and it returns a
 // new input channel which the filter should read from. When its input
 // channel closes, the filter should close its output channel.
-func (cl *Client) AddFilter(out <-chan interface{}) <-chan interface{} {
+func (cl *Client) AddFilter(out <-chan Stanza) <-chan Stanza {
 	cl.filterOut <- out
 	return <-cl.filterIn
 }