Added Client.StartSession().
--- a/structs.go Wed Dec 28 16:10:20 2011 -0700
+++ b/structs.go Thu Dec 29 09:48:36 2011 -0700
@@ -105,6 +105,9 @@
Type string `xml:"attr"`
Lang string `xml:"attr"`
Error *Error
+ Subject *Generic
+ Body *Generic
+ Thread *Generic
Any *Generic
}
var _ xml.Marshaler = &Message{}
@@ -118,6 +121,9 @@
Type string `xml:"attr"`
Lang string `xml:"attr"`
Error *Error
+ Show *Generic
+ Status *Generic
+ Priority *Generic
Any *Generic
}
var _ xml.Marshaler = &Presence{}
@@ -144,6 +150,7 @@
Any *Generic
}
var _ xml.Marshaler = &Error{}
+var _ os.Error = &Error{}
// Holds an XML element not described by the more specific types.
type Generic struct {
@@ -302,6 +309,11 @@
return buf.Bytes(), nil
}
+func (er *Error) String() string {
+ bytes, _ := er.MarshalXML()
+ return string(bytes)
+}
+
func (m *Message) XName() string {
return "message"
}
--- a/xmpp.go Wed Dec 28 16:10:20 2011 -0700
+++ b/xmpp.go Thu Dec 29 09:48:36 2011 -0700
@@ -13,9 +13,11 @@
"bytes"
"fmt"
"io"
+ "log"
"net"
"os"
"sync"
+ "xml"
)
const (
@@ -28,6 +30,7 @@
nsTLS = "urn:ietf:params:xml:ns:xmpp-tls"
nsSASL = "urn:ietf:params:xml:ns:xmpp-sasl"
nsBind = "urn:ietf:params:xml:ns:xmpp-bind"
+ nsSession = "urn:ietf:params:xml:ns:xmpp-session"
// DNS SRV names
serverSrv = "xmpp-server"
@@ -218,6 +221,8 @@
// This convenience function may be used to generate a unique id for
// use in the Id fields of iq, message, and presence stanzas.
+// BUG(cjyar) This should be replaced with a goroutine that feeds a
+// channel.
func (cl *Client) NextId() string {
cl.idMutex.Lock()
defer cl.idMutex.Unlock()
@@ -225,3 +230,32 @@
cl.nextId++
return fmt.Sprintf("id_%d", id)
}
+
+// Start an XMPP session. This should typically be done immediately
+// after creating the new Client. Once the session has been
+// established, pr will be sent as an initial presence; nil means
+// don't send initial presence. The initial presence can be a
+// newly-initialized Presence struct. See RFC 3921, Section 3.
+func (cl *Client) StartSession(pr *Presence) os.Error {
+ id := cl.NextId()
+ iq := &Iq{To: cl.Jid.Domain, Id: id, Type: "set", Any:
+ &Generic{XMLName: xml.Name{Space: nsSession, Local:
+ "session"}}}
+ ch := make(chan os.Error)
+ f := func(st Stanza) bool {
+ if st.XType() == "error" {
+ log.Printf("Can't start session: %v", st)
+ ch <- st.XError()
+ return false
+ }
+ if pr != nil {
+ cl.Out <- pr
+ }
+ ch <- nil
+ return false
+ }
+ cl.HandleStanza(id, f)
+ cl.Out <- iq
+ // Now wait until the callback is called.
+ return <-ch
+}