xmpp.go
author Chris Jones <christian.jones@sri.com>
Fri, 28 Dec 2012 17:07:20 -0700
changeset 114 a058e33c1666
parent 113 bee6cc131798
child 116 5c6d6d51d3ba
permissions -rw-r--r--
Updated for the latest revision of the encoding/xml fixes: The context object owned by Encoder and Decoder isn't directly accessible. Also improved the output from the two assert functions to show the info of the caller rather than the assert function itself.
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"
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"
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
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
    39
// 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
    40
// 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
    41
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
    42
e6cb3f049137 Revamped how the roster works. We're now using a channel to transmit snapshots
Chris Jones <chris@cjones.org>
parents: 51
diff changeset
    43
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
    44
	// 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
    45
	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
    46
	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
    47
	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
    48
		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
    49
		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
    50
			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
    51
			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
    52
			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
    53
		}
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)
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
}
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
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    57
// 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
    58
type Extension struct {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    59
	StanzaHandlers map[string]func(*xml.Name) interface{}
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    60
	Start          func(*Client)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    61
}
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
    62
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
    63
// Allows the user to override the TLS configuration.
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
    64
var TlsConfig tls.Config
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
    65
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    66
// 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
    67
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
    68
	// 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
    69
	// 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
    70
	// 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
    71
	Uid string
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
    72
	// 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
    73
	// the time StartSession() returns.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    74
	Jid          JID
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    75
	password     string
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    76
	socket       net.Conn
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    77
	socketSync   sync.WaitGroup
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
    78
	saslExpected string
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    79
	authDone     bool
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    80
	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
    81
	inputControl chan int
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    82
	// Incoming XMPP stanzas from the server will be published on
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    83
	// this channel. Information which is only used by this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    84
	// library to set up the XMPP stream will not appear here.
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
    85
	In <-chan Stanza
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    86
	// Outgoing XMPP stanzas to the server should be sent to this
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
    87
	// channel.
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
    88
	Out    chan<- Stanza
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
    89
	xmlOut chan<- interface{}
32
4e68d8f89dc3 Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents: 30
diff changeset
    90
	// 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
    91
	// 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
    92
	// 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
    93
	// StartSession() returns.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
    94
	Features  *Features
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
    95
	filterOut chan<- <-chan Stanza
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
    96
	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
    97
}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    98
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
    99
// Connect to the appropriate server and authenticate as the given JID
17
d269d9c0fc8e Code review.
Chris Jones <chris@cjones.org>
parents: 15
diff changeset
   100
// 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
   101
// connection has been established, but before XMPP stream negotiation
27
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   102
// has completed. The negotiation will occur asynchronously, and any
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   103
// send operation to Client.Out will block until negotiation (resource
13bcc96a5a6c Clarified a comment.
Chris Jones <chris@cjones.org>
parents: 26
diff changeset
   104
// binding) is complete.
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   105
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
   106
	// Include the mandatory extensions.
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   107
	exts = append(exts, rosterExt)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   108
	exts = append(exts, bindExt)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   109
2
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   110
	// 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
   111
	_, 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
   112
	if err != nil {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   113
		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
   114
			": " + 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
   115
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   116
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   117
	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
   118
	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
   119
		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
   120
		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
   121
		if err != nil {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   122
			err = fmt.Errorf("ResolveTCPAddr(%s): %s",
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   123
				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
   124
			continue
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   125
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   126
		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
   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("DialTCP(%s): %s",
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   129
				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
   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
		}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   132
	}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   133
	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
   134
		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
   135
	}
4dabfef08c8c Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff changeset
   136
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   137
	cl := new(Client)
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   138
	cl.Uid = <-Id
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   139
	cl.password = password
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   140
	cl.Jid = *jid
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   141
	cl.socket = tcp
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   142
	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
   143
	cl.inputControl = make(chan int)
30
a77fc342e013 Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents: 29
diff changeset
   144
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   145
	extStanza := make(map[string]func(*xml.Name) interface{})
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   146
	for _, ext := range exts {
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   147
		for k, v := range ext.StanzaHandlers {
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   148
			extStanza[k] = v
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   149
		}
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   150
	}
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   151
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   152
	// Start the transport handler, initially unencrypted.
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   153
	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
   154
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   155
	// 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
   156
	xmlIn := startXmlReader(tlsr, extStanza)
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   157
	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
   158
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   159
	// 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
   160
	// 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
   161
	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
   162
	clOut := cl.startStreamWriter(cl.xmlOut)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   163
	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
   164
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   165
	// 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
   166
	// 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
   167
	clIn := cl.startFilter(stIn)
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   168
	cl.In = clIn
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   169
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   170
	// Add filters for our extensions.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   171
	for _, ext := range exts {
60
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   172
		ext.Start(cl)
6d4f43f7dc19 Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents: 59
diff changeset
   173
	}
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   174
8
30a7752cf8f7 Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents: 6
diff changeset
   175
	// Initial handshake.
22
d6b7b4cbf50d Made the stream type non-public.
Chris Jones <chris@cjones.org>
parents: 20
diff changeset
   176
	hsOut := &stream{To: jid.Domain, Version: Version}
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   177
	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
   178
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   179
	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
   180
}
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   181
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   182
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
   183
	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
   184
	outr, outw := io.Pipe()
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   185
	go cl.readTransport(inw)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents: 9
diff changeset
   186
	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
   187
	return inr, outw
4
a8fbec71a194 Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents: 2
diff changeset
   188
}
5
faef59c8db05 Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents: 4
diff changeset
   189
36
9fe022261dcc Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents: 34
diff changeset
   190
func startXmlReader(r io.Reader,
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   191
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
   192
	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
   193
	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
   194
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   195
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   196
64
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   197
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
   198
	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
   199
	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
   200
	return ch
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   201
}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   202
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   203
func (cl *Client) startStreamReader(xmlIn <-chan interface{}, srvOut chan<- interface{}) <-chan Stanza {
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   204
	ch := make(chan Stanza)
11
48be1ae93fd4 Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents: 10
diff changeset
   205
	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
   206
	return ch
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   207
}
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   208
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   209
func (cl *Client) startStreamWriter(xmlOut chan<- interface{}) chan<- Stanza {
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   210
	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
   211
	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
   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
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   215
func (cl *Client) startFilter(srvIn <-chan Stanza) <-chan Stanza {
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   216
	cliIn := make(chan Stanza)
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   217
	filterOut := make(chan (<-chan Stanza))
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   218
	filterIn := make(chan (<-chan Stanza))
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   219
	nullFilter := make(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
   220
	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
   221
	go filterTop(filterOut, filterIn, nullFilter, cliIn)
46
4a4530b8f622 Added roster updating.
Chris Jones <chris@cjones.org>
parents: 45
diff changeset
   222
	cl.filterOut = filterOut
4a4530b8f622 Added roster updating.
Chris Jones <chris@cjones.org>
parents: 45
diff changeset
   223
	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
   224
	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
   225
}
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   226
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   227
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
   228
	defer func(w io.Writer) {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   229
		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
   230
			c.Close()
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   231
		}
ac0639692317 Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents: 63
diff changeset
   232
	}(w)
6
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   233
62
6e2eea62ccca Added global variables for logging.
Chris Jones <chris@cjones.org>
parents: 61
diff changeset
   234
	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
   235
	for {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   236
		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
   237
		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
   238
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   239
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   240
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   241
		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
   242
		if n == 0 {
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   243
			break
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   244
		}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   245
		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
   246
		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
   247
			Debug.Log(buf)
106
ffb9d27fea79 Fixed up the client/server traffic logging.
Chris Jones <christian.jones@sri.com>
parents: 105
diff changeset
   248
			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
   249
		}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   250
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   251
	leftover := buf.String()
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   252
	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
   253
		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
   254
	}
8e425e340ca1 Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents: 5
diff changeset
   255
}
9
4fe926b03827 Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents: 8
diff changeset
   256
29
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   257
// 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
   258
// 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
   259
// 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
   260
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
   261
	cl.inputControl <- 1
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   262
}
a456133ed0ac Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents: 28
diff changeset
   263
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   264
// 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
   265
// 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
   266
// session, retrieve the roster, and broadcast an initial
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   267
// 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
   268
// 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
   269
func (cl *Client) StartSession(getRoster bool, pr *Presence) error {
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   270
	id := <-Id
111
36287f2cf06e Step 1 of moving to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 110
diff changeset
   271
	iq := &Iq{Header: Header{To: cl.Jid.Domain, Id: id, Type: "set",
110
7696e6a01709 Instead of making Stanza an interface that Iq, Message, and Presence implement, change it to an embedded struct.
Chris Jones <chris@cjones.org>
parents: 106
diff changeset
   272
		Nested: []interface{}{Generic{XMLName:
7696e6a01709 Instead of making Stanza an interface that Iq, Message, and Presence implement, change it to an embedded struct.
Chris Jones <chris@cjones.org>
parents: 106
diff changeset
   273
			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
   274
	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
   275
	f := func(st Stanza) bool {
98
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   276
		iq, ok := st.(*Iq)
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   277
		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
   278
			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
   279
			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
   280
			return false
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   281
		}
c9cc4eda6dce Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents: 72
diff changeset
   282
		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
   283
			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
   284
			ch <- iq.Error
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   285
			return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   286
		}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   287
		ch <- nil
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   288
		return false
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   289
	}
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   290
	cl.HandleStanza(id, f)
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   291
	cl.Out <- iq
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   292
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   293
	// Now wait until the callback is called.
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   294
	if err := <-ch; err != nil {
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   295
		return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   296
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   297
	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
   298
		err := fetchRoster(cl)
33
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   299
		if err != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   300
			return err
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   301
		}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   302
	}
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   303
	if pr != nil {
571713f49494 Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents: 32
diff changeset
   304
		cl.Out <- pr
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
	return nil
28
78961db80bae Added Client.StartSession().
Chris Jones <chris@cjones.org>
parents: 27
diff changeset
   307
}
45
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   308
abf958bcc201 Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents: 44
diff changeset
   309
// 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
   310
// 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
   311
// 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
   312
// 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
   313
// channel closes, the filter should close its output channel.
113
bee6cc131798 Step 3 of converting to interface Stanza and embedded struct Header.
Chris Jones <chris@cjones.org>
parents: 111
diff changeset
   314
func (cl *Client) AddFilter(out <-chan Stanza) <-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
   315
	cl.filterOut <- out
72
Chris Jones <christian.jones@sri.com>
parents: 67
diff changeset
   316
	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
   317
}