xmpp.go
func (c *Client) Recv() (stanza interface{}, err error) {
	for {
		_, val, err := next(c.p)
		if err != nil {
			return Chat{}, err
		}
		switch v := val.(type) {
		case *clientMessage:
			stamp, _ := time.Parse(
				"2006-01-02T15:04:05Z",
				v.Delay.Stamp,
			)
			chat := Chat{
				Remote:    v.From,
				Type:      v.Type,
				Text:      v.Body,
				Subject:   v.Subject,
				Thread:    v.Thread,
				Other:     v.OtherStrings(),
				OtherElem: v.Other,
				Stamp:     stamp,
			}
			return chat, nil
		case *clientQuery:
			var r Roster
			for _, item := range v.Item {
				r = append(r, Contact{item.Jid, item.Name, item.Group})
			}
			return Chat{Type: "roster", Roster: r}, nil
		case *clientPresence:
			return Presence{v.From, v.To, v.Type, v.Show, v.Status}, nil
		case *clientIQ:
			// TODO check more strictly
			if bytes.Equal(bytes.TrimSpace(v.Query), []byte(`<ping xmlns='urn:xmpp:ping'/>`)) || bytes.Equal(bytes.TrimSpace(v.Query), []byte(`<ping xmlns="urn:xmpp:ping"/>`)) {
				err := c.SendResultPing(v.ID, v.From)
				if err != nil {
					return Chat{}, err
				}
			}
			return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type, Query: v.Query}, nil
		}
	}
}
func (c *Client) Recv() (stanza interface{}, err error) {
	for {
		_, val, err := next(c.p)
		if err != nil {
			return Chat{}, err
		}
		switch v := val.(type) {
		case *clientMessage:
			stamp, _ := time.Parse(
				"2006-01-02T15:04:05Z",
				v.Delay.Stamp,
			)
			chat := Chat{
				Remote:    v.From,
				Type:      v.Type,
				Text:      v.Body,
				Subject:   v.Subject,
				Thread:    v.Thread,
				Other:     v.OtherStrings(),
				OtherElem: v.Other,
				Stamp:     stamp,
			}
			return chat, nil
		case *clientQuery:
			var r Roster
			for _, item := range v.Item {
				r = append(r, Contact{item.Jid, item.Name, item.Group})
			}
			return Chat{Type: "roster", Roster: r}, nil
		case *clientPresence:
			return Presence{v.From, v.To, v.Type, v.Show, v.Status}, nil
		case *clientIQ:
			// TODO check more strictly
			if bytes.Equal(bytes.TrimSpace(v.Query), []byte(`<ping xmlns='urn:xmpp:ping'/>`)) || bytes.Equal(bytes.TrimSpace(v.Query), []byte(`<ping xmlns="urn:xmpp:ping"/>`)) {
				err := c.SendResultPing(v.ID, v.From)
				if err != nil {
					return Chat{}, err
				}
			}
			return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type, Query: v.Query}, nil
		}
	}
}
// Recv waits to receive the next XMPP stanza.
// Return type is either a presence notification or a chat message.