# HG changeset patch # User Chris Jones # Date 1355724414 25200 # Node ID bee6cc13179864b8de757f38a29f9ffd3c7bac2a # Parent bd56fb741f69e13eba06ff5c0b6d6d5d368f6acc Step 3 of converting to interface Stanza and embedded struct Header. diff -r bd56fb741f69 -r bee6cc131798 examples/interact.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{} diff -r bd56fb741f69 -r bee6cc131798 roster.go --- 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) diff -r bd56fb741f69 -r bee6cc131798 stream.go --- 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 } diff -r bd56fb741f69 -r bee6cc131798 xmpp.go --- 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 }