stream.go
changeset 61 16513974d273
parent 59 be6815a9653a
child 62 6e2eea62ccca
equal deleted inserted replaced
60:6d4f43f7dc19 61:16513974d273
   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")