xmpp.go
author Chris Jones <chris@cjones.org>
Sun, 01 Jan 2012 17:27:21 -0700
changeset 43 82e90aa25dad
parent 42 f6bb47ca12f2
child 44 dd6f5cc27d52
permissions -rw-r--r--
Making a little more use of XMLName for marshaling instead of having a custom MarshalXML function.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     1
// Copyright 2011 The Go Authors.  All rights reserved.
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     2
// Use of this source code is governed by a BSD-style
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     3
// license that can be found in the LICENSE file.
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     4
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     5
// This package implements a simple XMPP client according to RFCs 3920
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     6
// and 3921, plus the various XEPs at http://xmpp.org/protocols/.
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     7
package xmpp
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     8
20
e119444a1119 Replaced TODO comments with Go-style BUG(me) comments.
Chris Jones <chris@cjones.org>
parents: 17
diff changeset
     9
// BUG(cjyar) Figure out why the library doesn't exit when the server
e119444a1119 Replaced TODO comments with Go-style BUG(me) comments.
Chris Jones <chris@cjones.org>
parents: 17
diff changeset
    10
// closes its stream to us.
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    11
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    12
import (
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
    13
	"bytes"
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    14
	"fmt"
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
    15
	"io"
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
    16
	"log"
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    17
	"net"
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    18
	"os"
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    19
	"sync"
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
    20
	"xml"
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    21
)
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    22
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    23
const (
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    24
	// Version of RFC 3920 that we implement.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    25
	Version = "1.0"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    26
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
    27
	// BUG(cjyar) These should be public.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    28
	// Various XML namespaces.
34
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    29
	NsStreams = "urn:ietf:params:xml:ns:xmpp-streams"
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    30
	NsStream = "http://etherx.jabber.org/streams"
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    31
	NsTLS = "urn:ietf:params:xml:ns:xmpp-tls"
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    32
	NsSASL = "urn:ietf:params:xml:ns:xmpp-sasl"
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    33
	NsBind = "urn:ietf:params:xml:ns:xmpp-bind"
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    34
	NsSession = "urn:ietf:params:xml:ns:xmpp-session"
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
    35
	NsRoster = "jabber:iq:roster"
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    36
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    37
	// DNS SRV names
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    38
	serverSrv = "xmpp-server"
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    39
	clientSrv = "xmpp-client"
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    40
20
e119444a1119 Replaced TODO comments with Go-style BUG(me) comments.
Chris Jones <chris@cjones.org>
parents: 17
diff changeset
    41
	// BUG(cjyar) Make this a parameter to NewClient, not a
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    42
	// constant. We should have both a log level and a
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    43
	// syslog.Writer, so the app can control how much time we
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    44
	// spend generating log messages, as well as where they go.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    45
	debug = true
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    46
)
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    47
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    48
// The client in a client-server XMPP connection.
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    49
type Client struct {
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
    50
	// This client's JID. This will be updated asynchronously by
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
    51
	// the time StartSession() returns.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    52
	Jid JID
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
    53
	password string
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    54
	socket net.Conn
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    55
	socketSync sync.WaitGroup
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
    56
	saslExpected string
12
122ab6208c3c Added resource binding and structures for <iq>, <message>, and <presence>.
Chris Jones <chris@cjones.org>
parents: 11
diff changeset
    57
	authDone bool
13
c9527bbe99a6 Added a callback handler which will handle a stanza with a particular id.
Chris Jones <chris@cjones.org>
parents: 12
diff changeset
    58
	handlers chan *stanzaHandler
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
    59
	inputControl chan int
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
    60
	// This channel may be used as a convenient way to generate a
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
    61
	// unique id for an iq, message, or presence stanza.
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
    62
	Id <-chan string
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    63
	// Incoming XMPP stanzas from the server will be published on
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    64
	// this channel. Information which is only used by this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    65
	// library to set up the XMPP stream will not appear here.
23
b5de44679389 Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents: 22
diff changeset
    66
	In <-chan Stanza
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    67
	// Outgoing XMPP stanzas to the server should be sent to this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    68
	// channel.
23
b5de44679389 Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents: 22
diff changeset
    69
	Out chan<- Stanza
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    70
	xmlOut chan<- interface{}
32
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    71
	// Features advertised by the remote. This will be updated
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    72
	// asynchronously as new features are received throughout the
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    73
	// connection process. It should not be updated once
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    74
	// StartSession() returns.
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    75
	Features *Features
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
    76
	roster map[string] *RosterItem
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    77
}
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
    78
var _ io.Closer = &Client{}
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    79
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    80
// Connect to the appropriate server and authenticate as the given JID
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    81
// with the given password. This function will return as soon as a TCP
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    82
// connection has been established, but before XMPP stream negotiation
27
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
    83
// has completed. The negotiation will occur asynchronously, and any
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
    84
// send operation to Client.Out will block until negotiation (resource
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
    85
// binding) is complete.
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
    86
func NewClient(jid *JID, password string,
38
2839fece923e Extended stanzas work now.
Chris Jones <chris@cjones.org>
parents: 36
diff changeset
    87
	extStanza map[string] func(*xml.Name) interface{}) (*Client, os.Error) {
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    88
	// Resolve the domain in the JID.
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    89
	_, srvs, err := net.LookupSRV(clientSrv, "tcp", jid.Domain)
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    90
	if err != nil {
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    91
		return nil, os.NewError("LookupSrv " + jid.Domain +
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    92
			": " + err.String())
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    93
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    94
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
    95
	var tcp *net.TCPConn
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    96
	for _, srv := range srvs {
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    97
		addrStr := fmt.Sprintf("%s:%d", srv.Target, srv.Port)
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    98
		addr, err := net.ResolveTCPAddr("tcp", addrStr)
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    99
		if err != nil {
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   100
			err = os.NewError(fmt.Sprintf("ResolveTCPAddr(%s): %s",
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   101
				addrStr, err.String()))
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   102
			continue
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   103
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   104
		tcp, err = net.DialTCP("tcp", nil, addr)
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   105
		if err != nil {
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   106
			err = os.NewError(fmt.Sprintf("DialTCP(%s): %s",
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   107
				addr, err.String()))
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   108
			continue
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   109
		}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   110
	}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   111
	if tcp == nil {
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   112
		return nil, err
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   113
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   114
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   115
	cl := new(Client)
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   116
	cl.password = password
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   117
	cl.Jid = *jid
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   118
	cl.socket = tcp
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   119
	cl.handlers = make(chan *stanzaHandler, 100)
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   120
	cl.inputControl = make(chan int)
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   121
	idCh := make(chan string)
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   122
	cl.Id = idCh
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   123
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   124
	if extStanza == nil {
38
2839fece923e Extended stanzas work now.
Chris Jones <chris@cjones.org>
parents: 36
diff changeset
   125
		extStanza = make(map[string] func(*xml.Name) interface{})
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   126
	}
38
2839fece923e Extended stanzas work now.
Chris Jones <chris@cjones.org>
parents: 36
diff changeset
   127
	extStanza[NsRoster] = newRosterQuery
41
c8c9e6a7e6c9 Made a special-purpose bind structure for resource binding.
Chris Jones <chris@cjones.org>
parents: 38
diff changeset
   128
	extStanza[NsBind] = newBind
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   129
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   130
	// Start the unique id generator.
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   131
	go makeIds(idCh)
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   132
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   133
	// Start the transport handler, initially unencrypted.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   134
	tlsr, tlsw := cl.startTransport()
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   135
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   136
	// Start the reader and writers that convert to and from XML.
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   137
	xmlIn := startXmlReader(tlsr, extStanza)
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   138
	cl.xmlOut = startXmlWriter(tlsw)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   139
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   140
	// Start the XMPP stream handler which filters stream-level
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   141
	// events and responds to them.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   142
	clIn := cl.startStreamReader(xmlIn, cl.xmlOut)
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   143
	clOut := cl.startStreamWriter(cl.xmlOut)
5
faef59c8db05 Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents: 4
diff changeset
   144
8
30a7752cf8f7 Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents: 6
diff changeset
   145
	// Initial handshake.
22
d6b7b4cbf50d Made the stream type non-public.
Chris Jones <chris@cjones.org>
parents: 20
diff changeset
   146
	hsOut := &stream{To: jid.Domain, Version: Version}
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   147
	cl.xmlOut <- hsOut
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   148
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   149
	cl.In = clIn
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   150
	cl.Out = clOut
8
30a7752cf8f7 Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents: 6
diff changeset
   151
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   152
	return cl, nil
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   153
}
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   154
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   155
func (c *Client) Close() os.Error {
26
4d0a369079ce Removed the TextOut channel.
Chris Jones <chris@cjones.org>
parents: 23
diff changeset
   156
	tryClose(c.In, c.Out)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   157
	return nil
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   158
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   159
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   160
func (cl *Client) startTransport() (io.Reader, io.Writer) {
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   161
	inr, inw := io.Pipe()
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   162
	outr, outw := io.Pipe()
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   163
	go cl.readTransport(inw)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   164
	go cl.writeTransport(outr)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   165
	return inr, outw
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   166
}
5
faef59c8db05 Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents: 4
diff changeset
   167
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   168
func startXmlReader(r io.Reader,
38
2839fece923e Extended stanzas work now.
Chris Jones <chris@cjones.org>
parents: 36
diff changeset
   169
	extStanza map[string] func(*xml.Name) interface{}) <-chan interface{} {
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   170
	ch := make(chan interface{})
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   171
	go readXml(r, ch, extStanza)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   172
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   173
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   174
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   175
func startXmlWriter(w io.Writer) chan<- interface{} {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   176
	ch := make(chan interface{})
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   177
	go writeXml(w, ch)
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   178
	return ch
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   179
}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   180
23
b5de44679389 Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents: 22
diff changeset
   181
func (cl *Client) startStreamReader(xmlIn <-chan interface{}, srvOut chan<- interface{}) <-chan Stanza {
b5de44679389 Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents: 22
diff changeset
   182
	ch := make(chan Stanza)
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   183
	go cl.readStream(xmlIn, ch)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   184
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   185
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   186
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   187
func (cl *Client) startStreamWriter(xmlOut chan<- interface{}) chan<- Stanza {
23
b5de44679389 Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents: 22
diff changeset
   188
	ch := make(chan Stanza)
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   189
	go writeStream(xmlOut, ch, cl.inputControl)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   190
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   191
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   192
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   193
func tee(r io.Reader, w io.Writer, prefix string) {
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   194
	defer tryClose(r, w)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   195
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   196
	buf := bytes.NewBuffer(nil)
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   197
	for {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   198
		var c [1]byte
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   199
		n, _ := r.Read(c[:])
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   200
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   201
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   202
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   203
		n, _ = w.Write(c[:n])
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   204
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   205
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   206
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   207
		buf.Write(c[:n])
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   208
		if c[0] == '\n' || c[0] == '>' {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   209
			fmt.Printf("%s%s\n", prefix, buf.String())
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   210
			buf.Reset()
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   211
		}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   212
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   213
	leftover := buf.String()
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   214
	if leftover != "" {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   215
		fmt.Printf("%s%s\n", prefix, leftover)
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   216
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   217
}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   218
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   219
func tryClose(xs ...interface{}) {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   220
	f1 := func(ch chan<- interface{}) {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   221
		defer func() {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   222
			recover()
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   223
		}()
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   224
		close(ch)
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   225
	}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   226
	f2 := func(ch <-chan interface{}) {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   227
		defer func() {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   228
			recover()
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   229
		}()
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   230
		close(ch)
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   231
	}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   232
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   233
	for _, x := range xs {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   234
		if c, ok := x.(io.Closer) ; ok {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   235
			c.Close()
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   236
		} else if ch, ok := x.(chan<- interface{}) ; ok {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   237
			f1(ch)
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   238
		} else if ch, ok := x.(<-chan interface{}) ; ok {
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   239
			f2(ch)
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   240
		}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   241
	}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   242
}
12
122ab6208c3c Added resource binding and structures for <iq>, <message>, and <presence>.
Chris Jones <chris@cjones.org>
parents: 11
diff changeset
   243
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   244
func makeIds(ch chan<- string) {
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   245
	id := int64(1)
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   246
	for {
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   247
		str := fmt.Sprintf("id_%d", id)
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   248
		ch <- str
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   249
		id++
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   250
	}
12
122ab6208c3c Added resource binding and structures for <iq>, <message>, and <presence>.
Chris Jones <chris@cjones.org>
parents: 11
diff changeset
   251
}
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   252
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   253
// bindDone is called when we've finished resource binding (and all
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   254
// the negotiations that precede it). Now we can start accepting
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   255
// traffic from the app.
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   256
func (cl *Client) bindDone() {
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   257
	cl.inputControl <- 1
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   258
}
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   259
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   260
// Start an XMPP session. A typical XMPP client should call this
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   261
// immediately after creating the Client in order to start the
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   262
// session, retrieve the roster, and broadcast an initial
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   263
// presence. The presence can be as simple as a newly-initialized
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   264
// Presence struct.  See RFC 3921, Section 3.
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   265
func (cl *Client) StartSession(getRoster bool, pr *Presence) os.Error {
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   266
	id := <- cl.Id
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   267
	iq := &Iq{To: cl.Jid.Domain, Id: id, Type: "set", Any:
34
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
   268
		&Generic{XMLName: xml.Name{Space: NsSession, Local:
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   269
				"session"}}}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   270
	ch := make(chan os.Error)
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   271
	f := func(st Stanza) bool {
42
f6bb47ca12f2 Renamed the somewhat obscure XTo(), etc. to GetTo(), etc.
Chris Jones <chris@cjones.org>
parents: 41
diff changeset
   272
		if st.GetType() == "error" {
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   273
			log.Printf("Can't start session: %v", st)
42
f6bb47ca12f2 Renamed the somewhat obscure XTo(), etc. to GetTo(), etc.
Chris Jones <chris@cjones.org>
parents: 41
diff changeset
   274
			ch <- st.GetError()
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   275
			return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   276
		}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   277
		ch <- nil
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   278
		return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   279
	}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   280
	cl.HandleStanza(id, f)
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   281
	cl.Out <- iq
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   282
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   283
	// Now wait until the callback is called.
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   284
	if err := <- ch ; err != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   285
		return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   286
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   287
	if getRoster {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   288
		err := cl.fetchRoster()
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   289
		if err != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   290
			return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   291
		}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   292
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   293
	if pr != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   294
		cl.Out <- pr
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   295
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   296
	return nil
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   297
}