equal
deleted
inserted
replaced
10 |
10 |
11 package xmpp |
11 package xmpp |
12 |
12 |
13 import ( |
13 import ( |
14 "big" |
14 "big" |
15 "bytes" |
|
16 "crypto/md5" |
15 "crypto/md5" |
17 "crypto/rand" |
16 "crypto/rand" |
18 "crypto/tls" |
17 "crypto/tls" |
19 "encoding/base64" |
18 "encoding/base64" |
20 "fmt" |
19 "fmt" |
80 } |
79 } |
81 } |
80 } |
82 } |
81 } |
83 |
82 |
84 func readXml(r io.Reader, ch chan<- interface{}, |
83 func readXml(r io.Reader, ch chan<- interface{}, |
85 extStanza map[string] func(*xml.Name) ExtendedStanza) { |
84 extStanza map[string] func(*xml.Name) interface{}) { |
86 if debug { |
85 if debug { |
87 pr, pw := io.Pipe() |
86 pr, pw := io.Pipe() |
88 go tee(r, pw, "S: ") |
87 go tee(r, pw, "S: ") |
89 r = pr |
88 r = pr |
90 } |
89 } |
148 |
147 |
149 // If it's a Stanza, we check its "Any" element for a |
148 // If it's a Stanza, we check its "Any" element for a |
150 // namespace that's registered with one of our |
149 // namespace that's registered with one of our |
151 // extensions. If so, we need to re-unmarshal into an |
150 // extensions. If so, we need to re-unmarshal into an |
152 // object of the correct type. |
151 // object of the correct type. |
153 if st, ok := obj.(Stanza) ; ok && st.XChild() != nil { |
152 if st, ok := obj.(Stanza) ; ok && st.generic() != nil { |
154 name := st.XChild().XMLName |
153 name := st.generic().XMLName |
155 ns := name.Space |
154 ns := name.Space |
156 con := extStanza[ns] |
155 con := extStanza[ns] |
157 if con != nil { |
156 if con != nil { |
158 obj = con(&name) |
157 err = parseExtended(st, con) |
159 xmlStr, _ := marshalXML(st) |
|
160 r := bytes.NewBuffer(xmlStr) |
|
161 err = xml.Unmarshal(r, obj) |
|
162 if err != nil { |
158 if err != nil { |
163 log.Printf("ext unmarshal: %v", |
159 log.Printf("ext unmarshal: %v", |
164 err) |
160 err) |
165 break |
161 break |
166 } |
162 } |
168 } |
164 } |
169 |
165 |
170 // Put it on the channel. |
166 // Put it on the channel. |
171 ch <- obj |
167 ch <- obj |
172 } |
168 } |
|
169 } |
|
170 |
|
171 func parseExtended(st Stanza, con 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 |
|
176 // can unmarshal this nested element from. |
|
177 reader := strings.NewReader(st.innerxml()) |
|
178 p := xml.NewParser(reader) |
|
179 var start *xml.StartElement |
|
180 for { |
|
181 t, err := p.Token() |
|
182 if err != nil { |
|
183 return err |
|
184 } |
|
185 if se, ok := t.(xml.StartElement) ; ok { |
|
186 if se.Name.Space == name.Space { |
|
187 start = &se |
|
188 break |
|
189 } |
|
190 } |
|
191 } |
|
192 |
|
193 // Unmarshal the nested element and stuff it back into the |
|
194 // stanza. |
|
195 err := p.Unmarshal(nested, start) |
|
196 if err != nil { |
|
197 return err |
|
198 } |
|
199 st.setNested(nested) |
|
200 return nil |
173 } |
201 } |
174 |
202 |
175 func writeXml(w io.Writer, ch <-chan interface{}) { |
203 func writeXml(w io.Writer, ch <-chan interface{}) { |
176 if debug { |
204 if debug { |
177 pr, pw := io.Pipe() |
205 pr, pw := io.Pipe() |
525 nonceCountStr + ":" + cnonceStr + ":auth:" + |
553 nonceCountStr + ":" + cnonceStr + ":auth:" + |
526 hex(h(a2)))) |
554 hex(h(a2)))) |
527 return response |
555 return response |
528 } |
556 } |
529 |
557 |
|
558 // BUG(cjyar) This should use iq.nested rather than iq.generic. |
530 // Send a request to bind a resource. RFC 3920, section 7. |
559 // Send a request to bind a resource. RFC 3920, section 7. |
531 func (cl *Client) bind(bind *Generic) { |
560 func (cl *Client) bind(bind *Generic) { |
532 res := cl.Jid.Resource |
561 res := cl.Jid.Resource |
533 msg := &Iq{Type: "set", Id: <- cl.Id, Any: |
562 msg := &Iq{Type: "set", Id: <- cl.Id, Any: |
534 &Generic{XMLName: xml.Name{Space: NsBind, Local: |
563 &Generic{XMLName: xml.Name{Space: NsBind, Local: |
540 f := func(st Stanza) bool { |
569 f := func(st Stanza) bool { |
541 if st.XType() == "error" { |
570 if st.XType() == "error" { |
542 log.Println("Resource binding failed") |
571 log.Println("Resource binding failed") |
543 return false |
572 return false |
544 } |
573 } |
545 bind := st.XChild() |
574 bind := st.generic() |
546 if bind == nil { |
575 if bind == nil { |
547 log.Println("nil resource bind") |
576 log.Println("nil resource bind") |
548 return false |
577 return false |
549 } |
578 } |
550 jidEle := bind.Any |
579 jidEle := bind.Any |