stream.go
changeset 38 2839fece923e
parent 37 fbda8e925fdf
child 40 33e7f25f1fd2
equal deleted inserted replaced
37:fbda8e925fdf 38:2839fece923e
    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