xmpp.go
author Chris Jones <christian.jones@sri.com>
Sun, 16 Dec 2012 14:37:43 -0700
changeset 101 5d721a565503
parent 100 24231ff0016c
child 102 872e936f9f3f
permissions -rw-r--r--
Use the new logging setup from the example program.
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
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"
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
    11
	"encoding/xml"
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
    12
	"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
    13
	"fmt"
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
    14
	"io"
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    15
	"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
    16
	"net"
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    17
	"sync"
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.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    22
	Version = "1.0"
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
62
6e2eea62ccca Added global variables for logging.
Chris Jones <chris@cjones.org>
parents: 61
diff changeset
    39
var (
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    40
	// If any of these are non-nil when NewClient() is called,
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    41
	// they will be used to log messages of the indicated
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    42
	// severity.
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    43
	Warn *log.Logger
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    44
	Info *log.Logger
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
    45
	Debug *log.Logger
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
57
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    48
// This channel may be used as a convenient way to generate a unique
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    49
// id for an iq, message, or presence stanza.
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    50
var Id <-chan string
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    51
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    52
func init() {
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    53
	// Start the unique id generator.
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    54
	idCh := make(chan string)
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    55
	Id = idCh
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    56
	go func(ch chan<- string) {
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    57
		id := int64(1)
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    58
		for {
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    59
			str := fmt.Sprintf("id_%d", id)
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    60
			ch <- str
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    61
			id++
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    62
		}
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    63
	}(idCh)
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    64
}
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    65
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    66
// 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
    67
type Extension struct {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    68
	StanzaHandlers map[string]func(*xml.Name) interface{}
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    69
	Start          func(*Client)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    70
}
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    71
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    72
// 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
    73
type Client struct {
57
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    74
	// This client's unique ID. It's unique within the context of
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    75
	// this process, so if multiple Client objects exist, each
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    76
	// will be distinguishable by its Uid.
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    77
	Uid string
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
    78
	// 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
    79
	// the time StartSession() returns.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    80
	Jid          JID
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    81
	password     string
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    82
	socket       net.Conn
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    83
	socketSync   sync.WaitGroup
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
    84
	saslExpected string
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    85
	authDone     bool
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    86
	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
    87
	inputControl chan int
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    88
	// Incoming XMPP stanzas from the server will be published on
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    89
	// this channel. Information which is only used by this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    90
	// 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
    91
	In <-chan Stanza
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    92
	// Outgoing XMPP stanzas to the server should be sent to this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    93
	// channel.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    94
	Out    chan<- Stanza
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    95
	xmlOut chan<- interface{}
32
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    96
	// 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
    97
	// 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
    98
	// 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
    99
	// StartSession() returns.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   100
	Features  *Features
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   101
	filterOut chan<- <-chan Stanza
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   102
	filterIn  <-chan <-chan Stanza
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   103
}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   104
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   105
// Connect to the appropriate server and authenticate as the given JID
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
   106
// 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
   107
// connection has been established, but before XMPP stream negotiation
27
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   108
// has completed. The negotiation will occur asynchronously, and any
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   109
// send operation to Client.Out will block until negotiation (resource
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   110
// binding) is complete.
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   111
func NewClient(jid *JID, password string, exts []Extension) (*Client, error) {
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   112
	// Include the mandatory extensions.
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   113
	exts = append(exts, rosterExt)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   114
	exts = append(exts, bindExt)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   115
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   116
	// 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
   117
	_, 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
   118
	if err != nil {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   119
		return nil, errors.New("LookupSrv " + jid.Domain +
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   120
			": " + 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
   121
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   122
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   123
	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
   124
	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
   125
		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
   126
		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
   127
		if err != nil {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   128
			err = fmt.Errorf("ResolveTCPAddr(%s): %s",
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   129
				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
   130
			continue
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   131
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   132
		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
   133
		if err != nil {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   134
			err = fmt.Errorf("DialTCP(%s): %s",
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   135
				addr, err)
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   136
			continue
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   137
		}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   138
	}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   139
	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
   140
		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
   141
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   142
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   143
	cl := new(Client)
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   144
	cl.Uid = <-Id
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   145
	cl.password = password
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   146
	cl.Jid = *jid
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   147
	cl.socket = tcp
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   148
	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
   149
	cl.inputControl = make(chan int)
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   150
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   151
	extStanza := make(map[string]func(*xml.Name) interface{})
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   152
	for _, ext := range exts {
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   153
		for k, v := range ext.StanzaHandlers {
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   154
			extStanza[k] = v
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   155
		}
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   156
	}
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   157
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   158
	// Start the transport handler, initially unencrypted.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   159
	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
   160
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   161
	// 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
   162
	xmlIn := startXmlReader(tlsr, extStanza)
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   163
	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
   164
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   165
	// 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
   166
	// events and responds to them.
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   167
	stIn := 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
   168
	clOut := cl.startStreamWriter(cl.xmlOut)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   169
	cl.Out = clOut
5
faef59c8db05 Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents: 4
diff changeset
   170
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   171
	// 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
   172
	// app sees.
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   173
	clIn := cl.startFilter(stIn)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   174
	cl.In = clIn
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   175
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   176
	// Add filters for our extensions.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   177
	for _, ext := range exts {
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   178
		ext.Start(cl)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   179
	}
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   180
8
30a7752cf8f7 Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents: 6
diff changeset
   181
	// Initial handshake.
22
d6b7b4cbf50d Made the stream type non-public.
Chris Jones <chris@cjones.org>
parents: 20
diff changeset
   182
	hsOut := &stream{To: jid.Domain, Version: Version}
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   183
	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
   184
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   185
	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
   186
}
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   187
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   188
func (cl *Client) startTransport() (io.Reader, io.WriteCloser) {
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   189
	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
   190
	outr, outw := io.Pipe()
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   191
	go cl.readTransport(inw)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   192
	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
   193
	return inr, outw
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   194
}
5
faef59c8db05 Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents: 4
diff changeset
   195
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   196
func startXmlReader(r io.Reader,
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   197
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
   198
	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
   199
	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
   200
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   201
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   202
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   203
func startXmlWriter(w io.WriteCloser) 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
   204
	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
   205
	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
   206
	return ch
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   207
}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   208
23
b5de44679389 Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents: 22
diff changeset
   209
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
   210
	ch := make(chan Stanza)
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   211
	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
   212
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   213
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   214
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   215
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
   216
	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
   217
	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
   218
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   219
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   220
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   221
func (cl *Client) startFilter(srvIn <-chan Stanza) <-chan Stanza {
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   222
	cliIn := make(chan Stanza)
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   223
	filterOut := make(chan (<-chan Stanza))
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   224
	filterIn := make(chan (<-chan Stanza))
51
1af366d10d32 Nil checks and a greatly simplified filter manager which is less buggy.
Chris Jones <chris@cjones.org>
parents: 48
diff changeset
   225
	nullFilter := make(chan Stanza)
1af366d10d32 Nil checks and a greatly simplified filter manager which is less buggy.
Chris Jones <chris@cjones.org>
parents: 48
diff changeset
   226
	go filterBottom(srvIn, nullFilter)
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   227
	go filterTop(filterOut, filterIn, nullFilter, cliIn)
46
4a4530b8f622 Added roster updating.
Chris Jones <chris@cjones.org>
parents: 45
diff changeset
   228
	cl.filterOut = filterOut
4a4530b8f622 Added roster updating.
Chris Jones <chris@cjones.org>
parents: 45
diff changeset
   229
	cl.filterIn = filterIn
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   230
	return cliIn
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   231
}
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   232
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   233
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
   234
	defer func(w io.Writer) {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   235
		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
   236
			c.Close()
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   237
		}
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   238
	}(w)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   239
62
6e2eea62ccca Added global variables for logging.
Chris Jones <chris@cjones.org>
parents: 61
diff changeset
   240
	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
   241
	for {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   242
		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
   243
		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
   244
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   245
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   246
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   247
		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
   248
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   249
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   250
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   251
		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
   252
		if c[0] == '\n' || c[0] == '>' {
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   253
			Debug.Print(buf)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   254
			buf.Reset()
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   255
		}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   256
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   257
	leftover := buf.String()
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   258
	if leftover != "" {
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   259
		Debug.Print(buf)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   260
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   261
}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   262
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   263
// 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
   264
// 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
   265
// 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
   266
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
   267
	cl.inputControl <- 1
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   268
}
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   269
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   270
// 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
   271
// 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
   272
// session, retrieve the roster, and broadcast an initial
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   273
// 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
   274
// Presence struct.  See RFC 3921, Section 3.
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   275
func (cl *Client) StartSession(getRoster bool, pr *Presence) error {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   276
	id := <-Id
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   277
	iq := &Iq{To: cl.Jid.Domain, Id: id, Type: "set", 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
   278
	ch := make(chan error)
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   279
	f := func(st Stanza) bool {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   280
		iq, ok := st.(*Iq)
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   281
		if !ok {
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   282
			Warnf("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
   283
			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
   284
			return false
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   285
		}
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   286
		if iq.Type == "error" {
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   287
			Warnf("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
   288
			ch <- iq.Error
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   289
			return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   290
		}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   291
		ch <- nil
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   292
		return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   293
	}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   294
	cl.HandleStanza(id, f)
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   295
	cl.Out <- iq
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   296
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   297
	// Now wait until the callback is called.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   298
	if err := <-ch; err != nil {
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   299
		return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   300
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   301
	if getRoster {
57
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
   302
		err := fetchRoster(cl)
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   303
		if err != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   304
			return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   305
		}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   306
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   307
	if pr != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   308
		cl.Out <- pr
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   309
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   310
	return nil
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   311
}
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   312
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   313
// AddFilter adds a new filter to the top of the stack through which
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   314
// incoming stanzas travel on their way up to the client. The new
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   315
// filter's output channel is given to this function, and it returns a
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   316
// new input channel which the filter should read from. When its input
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   317
// channel closes, the filter should close its output channel.
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   318
func (cl *Client) AddFilter(out <-chan Stanza) <-chan Stanza {
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   319
	cl.filterOut <- out
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   320
	return <-cl.filterIn
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   321
}
100
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   322
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   323
func Warnf(msg string, args ...interface{}) {
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   324
	if Warn != nil {
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   325
		Warn.Printf(msg, args)
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   326
	}
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   327
}
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   328
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   329
func Infof(msg string, args ...interface{}) {
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   330
	if Info != nil {
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   331
		Info.Printf(msg, args)
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   332
	}
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   333
}
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   334
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   335
func Debugf(msg string, args ...interface{}) {
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   336
	if Debug != nil {
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   337
		Debug.Printf(msg, args)
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   338
	}
24231ff0016c Reworked logging.
Chris Jones <christian.jones@sri.com>
parents: 98
diff changeset
   339
}