diff --git a/example/example.go b/example/example.go index f69099f..3981192 100644 --- a/example/example.go +++ b/example/example.go @@ -15,6 +15,7 @@ var username = flag.String("username", "", "username") var password = flag.String("password", "", "password") var notls = flag.Bool("notls", false, "No TLS") var debug = flag.Bool("debug", false, "debug output") +var session = flag.Bool("session", false, "use server session") func main() { flag.Usage = func() { @@ -29,11 +30,15 @@ func main() { var talk *xmpp.Client var err error - if *notls { - talk, err = xmpp.NewClientNoTLS(*server, *username, *password, *debug) - } else { - talk, err = xmpp.NewClient(*server, *username, *password, *debug) - } + options := xmpp.Options{Host: *server, + User: *username, + Password: *password, + NoTLS: *notls, + Debug: *debug, + Session: *session} + + talk, err = options.NewClient() + if err != nil { log.Fatal(err) } diff --git a/xmpp.go b/xmpp.go index 65f0841..6515fcc 100644 --- a/xmpp.go +++ b/xmpp.go @@ -19,6 +19,7 @@ import ( "crypto/rand" "crypto/tls" "encoding/base64" + "encoding/binary" "encoding/xml" "errors" "fmt" @@ -32,15 +33,26 @@ import ( ) const ( - nsStream = "http://etherx.jabber.org/streams" - nsTLS = "urn:ietf:params:xml:ns:xmpp-tls" - nsSASL = "urn:ietf:params:xml:ns:xmpp-sasl" - nsBind = "urn:ietf:params:xml:ns:xmpp-bind" - nsClient = "jabber:client" + nsStream = "http://etherx.jabber.org/streams" + nsTLS = "urn:ietf:params:xml:ns:xmpp-tls" + nsSASL = "urn:ietf:params:xml:ns:xmpp-sasl" + nsBind = "urn:ietf:params:xml:ns:xmpp-bind" + nsClient = "jabber:client" + NsSession = "urn:ietf:params:xml:ns:xmpp-session" ) var DefaultConfig tls.Config +type Cookie uint64 + +func getCookie() Cookie { + var buf [8]byte + if _, err := rand.Reader.Read(buf[:]); err != nil { + panic("Failed to read random bytes: " + err.Error()) + } + return Cookie(binary.LittleEndian.Uint64(buf[:])) +} + type Client struct { conn net.Conn // connection to server jid string // Jabber ID for our connection @@ -117,6 +129,9 @@ type Options struct { // Debug output Debug bool + + //Use server sessions + Session bool } // NewClient establishes a new Client connection based on a set of Options. @@ -161,6 +176,7 @@ func NewClient(host, user, passwd string, debug bool) (*Client, error) { User: user, Password: passwd, Debug: debug, + Session: false, } return opts.NewClient() } @@ -172,6 +188,7 @@ func NewClientNoTLS(host, user, passwd string, debug bool) (*Client, error) { Password: passwd, NoTLS: true, Debug: debug, + Session: false, } return opts.NewClient() } @@ -343,14 +360,17 @@ func (c *Client) init(o *Options) error { } if err = c.p.DecodeElement(&f, nil); err != nil { // TODO: often stream stop. - //return os.NewError("unmarshal : " + err.String()) + //return errors.New("unmarshal : " + err.Error()) } + //Generate uniq cookie + cookie := getCookie() + // Send IQ message asking to bind to the local user name. if o.Resource == "" { - fmt.Fprintf(c.conn, "\n", nsBind) + fmt.Fprintf(c.conn, "\n", cookie, nsBind) } else { - fmt.Fprintf(c.conn, "%s\n", nsBind, o.Resource) + fmt.Fprintf(c.conn, "%s\n", cookie, nsBind, o.Resource) } var iq clientIQ if err = c.p.DecodeElement(&iq, nil); err != nil { @@ -361,6 +381,11 @@ func (c *Client) init(o *Options) error { } c.jid = iq.Bind.Jid // our local id + if o.Session { + //if server support session, open it + fmt.Fprintf(c.conn, "", xmlEscape(domain), cookie, NsSession) + } + // We're connected and can now receive and send messages. fmt.Fprintf(c.conn, "xaI for one welcome our new codebot overlords.") return nil