xmpp/xmpp.go
author Chris Jones <christian.jones@sri.com>
Sun, 15 Sep 2013 16:41:02 -0600
changeset 150 fa7f6ff10c67
parent 148 b1b4900eee5b
child 153 bbd4166df95d
permissions -rw-r--r--
Code reorder and doc cleanup.
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
// This package implements a simple XMPP client according to RFCs 3920
119
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
     2
// and 3921, plus the various XEPs at http://xmpp.org/protocols/. The
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
     3
// implementation is structured as a stack of layers, with TCP at the
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
     4
// bottom and the application at the top. The application receives and
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
     5
// sends structures representing XMPP stanzas. Additional stanza
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
     6
// parsers can be inserted into the stack of layers as extensions.
2
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
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
     9
import (
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
    10
	"bytes"
105
aa895dfae3f6 Allow the user to override the TLS config. Also fixed up some log statements.
Chris Jones <christian.jones@sri.com>
parents: 102
diff changeset
    11
	"crypto/tls"
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
    12
	"encoding/xml"
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
    13
	"errors"
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"
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    16
	"net"
128
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
    17
	"reflect"
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    18
)
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    19
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    20
const (
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    21
	// Version of RFC 3920 that we implement.
118
fb9bb98a8d70 Code cleanup: Renamed the Version constant. Moved the unique-ID generator into its own file.
Chris Jones <christian.jones@sri.com>
parents: 116
diff changeset
    22
	XMPPVersion = "1.0"
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    23
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    24
	// Various XML namespaces.
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
    25
	NsClient  = "jabber:client"
34
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    26
	NsStreams = "urn:ietf:params:xml:ns:xmpp-streams"
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    27
	NsStream  = "http://etherx.jabber.org/streams"
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    28
	NsTLS     = "urn:ietf:params:xml:ns:xmpp-tls"
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    29
	NsSASL    = "urn:ietf:params:xml:ns:xmpp-sasl"
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    30
	NsBind    = "urn:ietf:params:xml:ns:xmpp-bind"
34
7b1f924c75e2 Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents: 33
diff changeset
    31
	NsSession = "urn:ietf:params:xml:ns:xmpp-session"
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    32
	NsRoster  = "jabber:iq:roster"
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    33
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    34
	// 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
    35
	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
    36
	clientSrv = "xmpp-client"
62
6e2eea62ccca Added global variables for logging.
Chris Jones <chris@cjones.org>
parents: 61
diff changeset
    37
)
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    38
146
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    39
// Flow control for preventing sending stanzas until negotiation has
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    40
// completed.
148
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    41
type sendCmd int
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    42
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    43
const (
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    44
	sendAllowConst = iota
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    45
	sendDenyConst
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    46
	sendAbortConst
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    47
)
146
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    48
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    49
var (
148
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    50
	sendAllow sendCmd = sendAllowConst
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    51
	sendDeny  sendCmd = sendDenyConst
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    52
	sendAbort sendCmd = sendAbortConst
146
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    53
)
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    54
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    55
// A filter can modify the XMPP traffic to or from the remote
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    56
// server. It's part of an Extension. The filter function will be
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    57
// called in a new goroutine, so it doesn't need to return. The filter
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    58
// should close its output when its input is closed.
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    59
type Filter func(in <-chan Stanza, out chan<- Stanza)
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    60
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    61
// Extensions can add stanza filters and/or new XML element types.
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    62
type Extension struct {
119
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
    63
	// Maps from an XML namespace to a function which constructs a
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
    64
	// structure to hold the contents of stanzas in that
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
    65
	// namespace.
128
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
    66
	StanzaHandlers map[xml.Name]reflect.Type
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    67
	// If non-nil, will be called once to start the filter
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    68
	// running. RecvFilter intercepts incoming messages on their
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    69
	// way from the remote server to the application; SendFilter
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    70
	// intercepts messages going the other direction.
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    71
	RecvFilter Filter
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    72
	SendFilter Filter
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    73
}
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    74
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    75
// 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
    76
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
    77
	// 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
    78
	// the time StartSession() returns.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    79
	Jid          JID
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    80
	password     string
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
    81
	saslExpected string
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    82
	authDone     bool
144
9d7fdb1d2fc1 Renamed HandleStanza to SetCallback.
Chris Jones <christian.jones@sri.com>
parents: 142
diff changeset
    83
	handlers     chan *callback
146
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
    84
	inputControl chan sendCmd
119
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
    85
	// Incoming XMPP stanzas from the remote will be published on
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
    86
	// this channel. Information which is used by this library to
712aa5780660 Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents: 118
diff changeset
    87
	// set up the XMPP stream will not appear here.
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
    88
	Recv <-chan Stanza
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    89
	// Outgoing XMPP stanzas to the server should be sent to this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    90
	// channel.
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
    91
	Send    chan<- Stanza
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
    92
	sendXml chan<- interface{}
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    93
	// The client's roster is also known as the buddy list. It's
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    94
	// the set of contacts which are known to this JID, or which
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    95
	// this JID is known to.
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
    96
	Roster Roster
32
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    97
	// 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
    98
	// 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
    99
	// 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
   100
	// StartSession() returns.
128
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
   101
	Features                     *Features
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   102
	sendFilterAdd, recvFilterAdd chan Filter
129
cccf2b2fe34d Moved the tls.Config from a package-level variable to a client instance variable.
Chris Jones <christian.jones@sri.com>
parents: 128
diff changeset
   103
	// Allows the user to override the TLS configuration.
130
da6f37ae3ffe Pass the TLS config as a parameter to the Client constructor. Updated the example program.
Chris Jones <christian.jones@sri.com>
parents: 129
diff changeset
   104
	tlsConfig tls.Config
148
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
   105
	layer1    *layer1
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   106
}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   107
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   108
// Connect to the appropriate server and authenticate as the given JID
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
   109
// 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
   110
// connection has been established, but before XMPP stream negotiation
27
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   111
// has completed. The negotiation will occur asynchronously, and any
138
065f54e291c7 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 135
diff changeset
   112
// send operation to Client.Send will block until negotiation
065f54e291c7 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 135
diff changeset
   113
// (resource binding) is complete. The caller must immediately start
065f54e291c7 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 135
diff changeset
   114
// reading from Client.Recv.
130
da6f37ae3ffe Pass the TLS config as a parameter to the Client constructor. Updated the example program.
Chris Jones <christian.jones@sri.com>
parents: 129
diff changeset
   115
func NewClient(jid *JID, password string, tlsconf tls.Config, exts []Extension) (*Client, error) {
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   116
	// Include the mandatory extensions.
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   117
	roster := newRosterExt()
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   118
	exts = append(exts, roster.Extension)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   119
	exts = append(exts, bindExt)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   120
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   121
	// 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
   122
	_, 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
   123
	if err != nil {
131
f9ccfaf672ed Address a bug that can happen if no SRV records can be found.
Chris Jones <christian.jones@sri.com>
parents: 130
diff changeset
   124
		return nil, fmt.Errorf("LookupSrv %s: %v", jid.Domain, err)
f9ccfaf672ed Address a bug that can happen if no SRV records can be found.
Chris Jones <christian.jones@sri.com>
parents: 130
diff changeset
   125
	}
f9ccfaf672ed Address a bug that can happen if no SRV records can be found.
Chris Jones <christian.jones@sri.com>
parents: 130
diff changeset
   126
	if len(srvs) == 0 {
f9ccfaf672ed Address a bug that can happen if no SRV records can be found.
Chris Jones <christian.jones@sri.com>
parents: 130
diff changeset
   127
		return nil, fmt.Errorf("LookupSrv %s: no results", jid.Domain)
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   128
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   129
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   130
	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
   131
	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
   132
		addrStr := fmt.Sprintf("%s:%d", srv.Target, srv.Port)
135
a4755a42af19 Fixed another logic error, caused by a shadowed variable name.
Chris Jones <christian.jones@sri.com>
parents: 134
diff changeset
   133
		var addr *net.TCPAddr
a4755a42af19 Fixed another logic error, caused by a shadowed variable name.
Chris Jones <christian.jones@sri.com>
parents: 134
diff changeset
   134
		addr, err = net.ResolveTCPAddr("tcp", addrStr)
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   135
		if err != nil {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   136
			err = fmt.Errorf("ResolveTCPAddr(%s): %s",
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   137
				addrStr, err.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
   138
			continue
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   139
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   140
		tcp, err = net.DialTCP("tcp", nil, addr)
135
a4755a42af19 Fixed another logic error, caused by a shadowed variable name.
Chris Jones <christian.jones@sri.com>
parents: 134
diff changeset
   141
		if tcp != nil {
120
9d7e8333948b Fix a bug causing us to open a TCP connection to every server and use the last one.
Chris Jones <christian.jones@sri.com>
parents: 119
diff changeset
   142
			break
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   143
		}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   144
	}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   145
	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
   146
		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
   147
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   148
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   149
	cl := new(Client)
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   150
	cl.Roster = *roster
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   151
	cl.password = password
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   152
	cl.Jid = *jid
144
9d7fdb1d2fc1 Renamed HandleStanza to SetCallback.
Chris Jones <christian.jones@sri.com>
parents: 142
diff changeset
   153
	cl.handlers = make(chan *callback, 100)
146
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
   154
	cl.inputControl = make(chan sendCmd)
130
da6f37ae3ffe Pass the TLS config as a parameter to the Client constructor. Updated the example program.
Chris Jones <christian.jones@sri.com>
parents: 129
diff changeset
   155
	cl.tlsConfig = tlsconf
134
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   156
	cl.sendFilterAdd = make(chan Filter)
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   157
	cl.recvFilterAdd = make(chan Filter)
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   158
128
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
   159
	extStanza := make(map[xml.Name]reflect.Type)
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   160
	for _, ext := range exts {
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   161
		for k, v := range ext.StanzaHandlers {
132
feaa24de9597 Fixed reversed-logic error in checking for duplicate stanza extension types.
Chris Jones <christian.jones@sri.com>
parents: 131
diff changeset
   162
			if _, ok := extStanza[k]; ok {
128
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
   163
				return nil, fmt.Errorf("duplicate handler %s",
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
   164
					k)
8342afcffc92 Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents: 127
diff changeset
   165
			}
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   166
			extStanza[k] = v
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
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
	}
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   169
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   170
	// Start the transport handler, initially unencrypted.
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   171
	recvReader, recvWriter := io.Pipe()
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   172
	sendReader, sendWriter := io.Pipe()
148
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
   173
	cl.layer1 = startLayer1(tcp, recvWriter, sendReader)
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   174
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   175
	// Start the reader and writer that convert to and from XML.
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   176
	recvXmlCh := make(chan interface{})
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   177
	go recvXml(recvReader, recvXmlCh, extStanza)
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   178
	sendXmlCh := make(chan interface{})
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   179
	cl.sendXml = sendXmlCh
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   180
	go sendXml(sendWriter, sendXmlCh)
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   181
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   182
	// Start the reader and writer that convert between XML and
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   183
	// XMPP stanzas.
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   184
	recvRawXmpp := make(chan Stanza)
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   185
	go cl.recvStream(recvXmlCh, recvRawXmpp)
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   186
	sendRawXmpp := make(chan Stanza)
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
   187
	go sendStream(sendXmlCh, sendRawXmpp, cl.inputControl)
5
faef59c8db05 Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents: 4
diff changeset
   188
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   189
	// Start the manager for the filters that can modify what the
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   190
	// app sees.
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   191
	recvFiltXmpp := make(chan Stanza)
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
   192
	cl.Recv = recvFiltXmpp
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   193
	go filterMgr(cl.recvFilterAdd, recvRawXmpp, recvFiltXmpp)
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   194
	sendFiltXmpp := make(chan Stanza)
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
   195
	cl.Send = sendFiltXmpp
134
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   196
	go filterMgr(cl.sendFilterAdd, sendFiltXmpp, sendRawXmpp)
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   197
	// Set up the initial filters.
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   198
	for _, ext := range exts {
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   199
		cl.AddRecvFilter(ext.RecvFilter)
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   200
		cl.AddSendFilter(ext.SendFilter)
80b764fa2f08 Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents: 132
diff changeset
   201
	}
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   202
8
30a7752cf8f7 Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents: 6
diff changeset
   203
	// Initial handshake.
118
fb9bb98a8d70 Code cleanup: Renamed the Version constant. Moved the unique-ID generator into its own file.
Chris Jones <christian.jones@sri.com>
parents: 116
diff changeset
   204
	hsOut := &stream{To: jid.Domain, Version: XMPPVersion}
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
   205
	cl.sendXml <- hsOut
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   206
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   207
	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
   208
}
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   209
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   210
func tee(r io.Reader, w io.Writer, prefix string) {
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   211
	defer func(w io.Writer) {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   212
		if c, ok := w.(io.Closer); ok {
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   213
			c.Close()
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   214
		}
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   215
	}(w)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   216
62
6e2eea62ccca Added global variables for logging.
Chris Jones <chris@cjones.org>
parents: 61
diff changeset
   217
	buf := bytes.NewBuffer([]uint8(prefix))
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   218
	for {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   219
		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
   220
		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
   221
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   222
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   223
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   224
		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
   225
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   226
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   227
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   228
		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
   229
		if c[0] == '\n' || c[0] == '>' {
102
872e936f9f3f Reworked the logging again, and also added namespaces to a couple of fields on Features.
Chris Jones <christian.jones@sri.com>
parents: 100
diff changeset
   230
			Debug.Log(buf)
106
ffb9d27fea79 Fixed up the client/server traffic logging.
Chris Jones <christian.jones@sri.com>
parents: 105
diff changeset
   231
			buf = bytes.NewBuffer([]uint8(prefix))
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   232
		}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   233
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   234
	leftover := buf.String()
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   235
	if leftover != "" {
102
872e936f9f3f Reworked the logging again, and also added namespaces to a couple of fields on Features.
Chris Jones <christian.jones@sri.com>
parents: 100
diff changeset
   236
		Debug.Log(buf)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   237
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   238
}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   239
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   240
// 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
   241
// 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
   242
// 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
   243
func (cl *Client) bindDone() {
146
aa9a0ae8f875 Changed the inputControl channel to send a custom type.
Chris Jones <christian.jones@sri.com>
parents: 144
diff changeset
   244
	cl.inputControl <- sendAllow
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   245
}
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   246
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   247
// Start an XMPP session. A typical XMPP client should call this
141
f0d0f3b941a6 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 138
diff changeset
   248
// immediately after creating the Client in order to start the session
f0d0f3b941a6 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 138
diff changeset
   249
// and broadcast an initial presence. The presence can be as simple as
f0d0f3b941a6 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 138
diff changeset
   250
// a newly-initialized Presence struct.  See RFC 3921, Section
f0d0f3b941a6 Doc update.
Chris Jones <christian.jones@sri.com>
parents: 138
diff changeset
   251
// 3. After calling this, a normal client should call Roster.Update().
121
ebb86cbdd218 Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents: 120
diff changeset
   252
func (cl *Client) StartSession(pr *Presence) error {
118
fb9bb98a8d70 Code cleanup: Renamed the Version constant. Moved the unique-ID generator into its own file.
Chris Jones <christian.jones@sri.com>
parents: 116
diff changeset
   253
	id := NextId()
111
36287f2cf06e Step 1 of moving to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 110
diff changeset
   254
	iq := &Iq{Header: Header{To: cl.Jid.Domain, Id: id, Type: "set",
116
Chris Jones <christian.jones@sri.com>
parents: 113
diff changeset
   255
		Nested: []interface{}{Generic{XMLName: xml.Name{Space: NsSession, Local: "session"}}}}}
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   256
	ch := make(chan error)
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   257
	f := func(st Stanza) bool {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   258
		iq, ok := st.(*Iq)
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   259
		if !ok {
105
aa895dfae3f6 Allow the user to override the TLS config. Also fixed up some log statements.
Chris Jones <christian.jones@sri.com>
parents: 102
diff changeset
   260
			Warn.Log("iq reply not iq; can't start session")
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   261
			ch <- errors.New("bad session start reply")
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   262
			return false
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   263
		}
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   264
		if iq.Type == "error" {
102
872e936f9f3f Reworked the logging again, and also added namespaces to a couple of fields on Features.
Chris Jones <christian.jones@sri.com>
parents: 100
diff changeset
   265
			Warn.Logf("Can't start session: %v", iq)
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   266
			ch <- iq.Error
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   267
			return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   268
		}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   269
		ch <- nil
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   270
		return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   271
	}
144
9d7fdb1d2fc1 Renamed HandleStanza to SetCallback.
Chris Jones <christian.jones@sri.com>
parents: 142
diff changeset
   272
	cl.SetCallback(id, f)
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
   273
	cl.Send <- iq
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   274
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   275
	// Now wait until the callback is called.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   276
	if err := <-ch; err != nil {
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   277
		return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   278
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   279
	if pr != nil {
127
a8f9a0c07fc8 Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents: 126
diff changeset
   280
		cl.Send <- pr
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   281
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   282
	return nil
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   283
}