143 if err != nil { |
143 if err != nil { |
144 log.Printf("unmarshal: %v", err) |
144 log.Printf("unmarshal: %v", err) |
145 break |
145 break |
146 } |
146 } |
147 |
147 |
148 // If it's a Stanza, we check its "Any" element for a |
148 // If it's a Stanza, we try to unmarshal its innerxml |
149 // namespace that's registered with one of our |
149 // into objects of the appropriate respective |
150 // extensions. If so, we need to re-unmarshal into an |
150 // types. This is specified by our extensions. |
151 // object of the correct type. |
151 if st, ok := obj.(Stanza) ; ok { |
152 if st, ok := obj.(Stanza) ; ok && st.generic() != nil { |
152 err = parseExtended(st, extStanza) |
153 name := st.generic().XMLName |
153 if err != nil { |
154 ns := name.Space |
154 log.Printf("ext unmarshal: %v", |
155 con := extStanza[ns] |
155 err) |
156 if con != nil { |
156 break |
157 err = parseExtended(st, con) |
|
158 if err != nil { |
|
159 log.Printf("ext unmarshal: %v", |
|
160 err) |
|
161 break |
|
162 } |
|
163 } |
157 } |
164 } |
158 } |
165 |
159 |
166 // Put it on the channel. |
160 // Put it on the channel. |
167 ch <- obj |
161 ch <- obj |
168 } |
162 } |
169 } |
163 } |
170 |
164 |
171 func parseExtended(st Stanza, con func(*xml.Name) interface{}) os.Error { |
165 func parseExtended(st Stanza, extStanza map[string] func(*xml.Name) interface{}) os.Error { |
172 name := st.generic().XMLName |
|
173 nested := con(&name) |
|
174 |
|
175 // Now parse the stanza's innerxml to find the string that we |
166 // Now parse the stanza's innerxml to find the string that we |
176 // can unmarshal this nested element from. |
167 // can unmarshal this nested element from. |
177 reader := strings.NewReader(st.innerxml()) |
168 reader := strings.NewReader(st.innerxml()) |
178 p := xml.NewParser(reader) |
169 p := xml.NewParser(reader) |
179 var start *xml.StartElement |
|
180 for { |
170 for { |
181 t, err := p.Token() |
171 t, err := p.Token() |
|
172 if err == os.EOF { |
|
173 break |
|
174 } |
182 if err != nil { |
175 if err != nil { |
183 return err |
176 return err |
184 } |
177 } |
185 if se, ok := t.(xml.StartElement) ; ok { |
178 if se, ok := t.(xml.StartElement) ; ok { |
186 if se.Name.Space == name.Space { |
179 if con, ok := extStanza[se.Name.Space] ; ok { |
187 start = &se |
180 // Call the indicated constructor. |
188 break |
181 nested := con(&se.Name) |
189 } |
182 |
190 } |
183 // Unmarshal the nested element and |
191 } |
184 // stuff it back into the stanza. |
192 |
185 err := p.Unmarshal(nested, &se) |
193 // Unmarshal the nested element and stuff it back into the |
186 if err != nil { |
194 // stanza. |
187 return err |
195 err := p.Unmarshal(nested, start) |
188 } |
196 if err != nil { |
189 st.addNested(nested) |
197 return err |
190 } |
198 } |
191 } |
199 st.setNested(nested) |
192 } |
|
193 |
200 return nil |
194 return nil |
201 } |
195 } |
202 |
196 |
203 func writeXml(w io.Writer, ch <-chan interface{}) { |
197 func writeXml(w io.Writer, ch <-chan interface{}) { |
204 if debug { |
198 if debug { |
592 res := cl.Jid.Resource |
586 res := cl.Jid.Resource |
593 bindReq := &bindIq{} |
587 bindReq := &bindIq{} |
594 if res != "" { |
588 if res != "" { |
595 bindReq.Resource = &res |
589 bindReq.Resource = &res |
596 } |
590 } |
597 msg := &Iq{Type: "set", Id: <- Id, Nested: &bindReq} |
591 msg := &Iq{Type: "set", Id: <- Id, Nested: []interface{}{bindReq}} |
598 f := func(st Stanza) bool { |
592 f := func(st Stanza) bool { |
599 if st.GetType() == "error" { |
593 if st.GetType() == "error" { |
600 log.Println("Resource binding failed") |
594 log.Println("Resource binding failed") |
601 return false |
595 return false |
602 } |
596 } |
603 bindRepl, ok := st.GetNested().(*bindIq) |
597 var bindRepl *bindIq |
604 if !ok { |
598 for _, ele := range(st.GetNested()) { |
605 log.Printf("bad bind reply: %v", bindRepl) |
599 if b, ok := ele.(*bindIq) ; ok { |
|
600 bindRepl = b |
|
601 break |
|
602 } |
|
603 } |
|
604 if bindRepl == nil { |
|
605 log.Printf("bad bind reply: %v", st) |
606 return false |
606 return false |
607 } |
607 } |
608 jidStr := bindRepl.Jid |
608 jidStr := bindRepl.Jid |
609 if jidStr == nil || *jidStr == "" { |
609 if jidStr == nil || *jidStr == "" { |
610 log.Println("empty resource") |
610 log.Println("empty resource") |