author | Chris Jones <christian.jones@sri.com> |
Sun, 16 Dec 2012 15:15:59 -0700 | |
changeset 102 | 872e936f9f3f |
parent 100 | 24231ff0016c |
child 105 | aa895dfae3f6 |
permissions | -rw-r--r-- |
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" |
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
15 |
"net" |
10 | 16 |
"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
|
17 |
) |
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 |
const ( |
10 | 20 |
// Version of RFC 3920 that we implement. |
21 |
Version = "1.0" |
|
22 |
||
23 |
// Various XML namespaces. |
|
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
24 |
NsClient = "jabber:client" |
34
7b1f924c75e2
Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents:
33
diff
changeset
|
25 |
NsStreams = "urn:ietf:params:xml:ns:xmpp-streams" |
72 | 26 |
NsStream = "http://etherx.jabber.org/streams" |
27 |
NsTLS = "urn:ietf:params:xml:ns:xmpp-tls" |
|
28 |
NsSASL = "urn:ietf:params:xml:ns:xmpp-sasl" |
|
29 |
NsBind = "urn:ietf:params:xml:ns:xmpp-bind" |
|
34
7b1f924c75e2
Made the namespace constants public.
Chris Jones <chris@cjones.org>
parents:
33
diff
changeset
|
30 |
NsSession = "urn:ietf:params:xml:ns:xmpp-session" |
72 | 31 |
NsRoster = "jabber:iq:roster" |
10 | 32 |
|
33 |
// 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
|
34 |
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
|
35 |
clientSrv = "xmpp-client" |
62
6e2eea62ccca
Added global variables for logging.
Chris Jones <chris@cjones.org>
parents:
61
diff
changeset
|
36 |
) |
10 | 37 |
|
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
|
38 |
// 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
|
39 |
// 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
|
40 |
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
|
41 |
|
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 |
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
|
43 |
// 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
|
44 |
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
|
45 |
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
|
46 |
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
|
47 |
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
|
48 |
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
|
49 |
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
|
50 |
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
|
51 |
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
|
52 |
} |
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 |
}(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
|
54 |
} |
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 |
|
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
56 |
// 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
|
57 |
type Extension struct { |
72 | 58 |
StanzaHandlers map[string]func(*xml.Name) interface{} |
59 |
Start func(*Client) |
|
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
60 |
} |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
61 |
|
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
62 |
// 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
|
63 |
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
|
64 |
// 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
|
65 |
// 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
|
66 |
// 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
|
67 |
Uid string |
29
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
68 |
// 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
|
69 |
// the time StartSession() returns. |
72 | 70 |
Jid JID |
71 |
password string |
|
72 |
socket net.Conn |
|
73 |
socketSync sync.WaitGroup |
|
11
48be1ae93fd4
Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents:
10
diff
changeset
|
74 |
saslExpected string |
72 | 75 |
authDone bool |
76 |
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
|
77 |
inputControl chan int |
17 | 78 |
// Incoming XMPP stanzas from the server will be published on |
79 |
// this channel. Information which is only used by this |
|
80 |
// 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
|
81 |
In <-chan Stanza |
17 | 82 |
// Outgoing XMPP stanzas to the server should be sent to this |
83 |
// channel. |
|
72 | 84 |
Out chan<- Stanza |
10 | 85 |
xmlOut chan<- interface{} |
32
4e68d8f89dc3
Make the server's advertised features available to the app.
Chris Jones <chris@cjones.org>
parents:
30
diff
changeset
|
86 |
// 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
|
87 |
// 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
|
88 |
// 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
|
89 |
// StartSession() returns. |
72 | 90 |
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
|
91 |
filterOut chan<- <-chan Stanza |
72 | 92 |
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
|
93 |
} |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
94 |
|
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
95 |
// Connect to the appropriate server and authenticate as the given JID |
17 | 96 |
// with the given password. This function will return as soon as a TCP |
97 |
// connection has been established, but before XMPP stream negotiation |
|
27 | 98 |
// has completed. The negotiation will occur asynchronously, and any |
99 |
// send operation to Client.Out will block until negotiation (resource |
|
100 |
// binding) is complete. |
|
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
101 |
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
|
102 |
// Include the mandatory extensions. |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
103 |
exts = append(exts, rosterExt) |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
104 |
exts = append(exts, bindExt) |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
105 |
|
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
106 |
// 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
|
107 |
_, 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
|
108 |
if err != nil { |
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
109 |
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
|
110 |
": " + 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
|
111 |
} |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
112 |
|
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
113 |
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
|
114 |
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
|
115 |
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
|
116 |
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
|
117 |
if err != nil { |
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
118 |
err = fmt.Errorf("ResolveTCPAddr(%s): %s", |
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
119 |
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
|
120 |
continue |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
121 |
} |
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
122 |
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
|
123 |
if err != nil { |
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
124 |
err = fmt.Errorf("DialTCP(%s): %s", |
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
125 |
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
|
126 |
continue |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
127 |
} |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
128 |
} |
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
129 |
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
|
130 |
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
|
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 |
|
10 | 133 |
cl := new(Client) |
72 | 134 |
cl.Uid = <-Id |
11
48be1ae93fd4
Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents:
10
diff
changeset
|
135 |
cl.password = password |
10 | 136 |
cl.Jid = *jid |
137 |
cl.socket = tcp |
|
33
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
138 |
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
|
139 |
cl.inputControl = make(chan int) |
30
a77fc342e013
Replaced Client.NextId() with a channel named Id.
Chris Jones <chris@cjones.org>
parents:
29
diff
changeset
|
140 |
|
72 | 141 |
extStanza := make(map[string]func(*xml.Name) interface{}) |
142 |
for _, ext := range exts { |
|
143 |
for k, v := range ext.StanzaHandlers { |
|
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
144 |
extStanza[k] = v |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
145 |
} |
36
9fe022261dcc
Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents:
34
diff
changeset
|
146 |
} |
9fe022261dcc
Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents:
34
diff
changeset
|
147 |
|
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
148 |
// Start the transport handler, initially unencrypted. |
10 | 149 |
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
|
150 |
|
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
151 |
// 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
|
152 |
xmlIn := startXmlReader(tlsr, extStanza) |
10 | 153 |
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
|
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 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
|
156 |
// 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
|
157 |
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
|
158 |
clOut := cl.startStreamWriter(cl.xmlOut) |
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
159 |
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
|
160 |
|
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 |
// 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
|
162 |
// 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
|
163 |
clIn := cl.startFilter(stIn) |
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
164 |
cl.In = clIn |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
165 |
|
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
166 |
// Add filters for our extensions. |
72 | 167 |
for _, ext := range exts { |
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
168 |
ext.Start(cl) |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
169 |
} |
45
abf958bcc201
Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents:
44
diff
changeset
|
170 |
|
8
30a7752cf8f7
Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents:
6
diff
changeset
|
171 |
// Initial handshake. |
22
d6b7b4cbf50d
Made the stream type non-public.
Chris Jones <chris@cjones.org>
parents:
20
diff
changeset
|
172 |
hsOut := &stream{To: jid.Domain, Version: Version} |
10 | 173 |
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
|
174 |
|
6
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
175 |
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
|
176 |
} |
4
a8fbec71a194
Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents:
2
diff
changeset
|
177 |
|
64
ac0639692317
Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents:
63
diff
changeset
|
178 |
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
|
179 |
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
|
180 |
outr, outw := io.Pipe() |
10 | 181 |
go cl.readTransport(inw) |
182 |
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
|
183 |
return inr, outw |
4
a8fbec71a194
Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents:
2
diff
changeset
|
184 |
} |
5
faef59c8db05
Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents:
4
diff
changeset
|
185 |
|
36
9fe022261dcc
Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents:
34
diff
changeset
|
186 |
func startXmlReader(r io.Reader, |
72 | 187 |
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
|
188 |
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
|
189 |
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
|
190 |
return ch |
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
191 |
} |
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
192 |
|
64
ac0639692317
Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents:
63
diff
changeset
|
193 |
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
|
194 |
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
|
195 |
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
|
196 |
return ch |
6
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
197 |
} |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
198 |
|
23
b5de44679389
Made the input and output channels of type Stanza rather than
Chris Jones <chris@cjones.org>
parents:
22
diff
changeset
|
199 |
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
|
200 |
ch := make(chan Stanza) |
11
48be1ae93fd4
Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents:
10
diff
changeset
|
201 |
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
|
202 |
return ch |
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
203 |
} |
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
204 |
|
29
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
205 |
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
|
206 |
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
|
207 |
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
|
208 |
return ch |
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
209 |
} |
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
210 |
|
45
abf958bcc201
Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents:
44
diff
changeset
|
211 |
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
|
212 |
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
|
213 |
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
|
214 |
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
|
215 |
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
|
216 |
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
|
217 |
go filterTop(filterOut, filterIn, nullFilter, cliIn) |
46 | 218 |
cl.filterOut = filterOut |
219 |
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
|
220 |
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
|
221 |
} |
abf958bcc201
Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents:
44
diff
changeset
|
222 |
|
6
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
223 |
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
|
224 |
defer func(w io.Writer) { |
72 | 225 |
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
|
226 |
c.Close() |
ac0639692317
Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents:
63
diff
changeset
|
227 |
} |
ac0639692317
Properly close all the channels and writers if Client.Out is close.
Chris Jones <chris@cjones.org>
parents:
63
diff
changeset
|
228 |
}(w) |
6
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
229 |
|
62
6e2eea62ccca
Added global variables for logging.
Chris Jones <chris@cjones.org>
parents:
61
diff
changeset
|
230 |
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
|
231 |
for { |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
232 |
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
|
233 |
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
|
234 |
if n == 0 { |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
235 |
break |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
236 |
} |
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
237 |
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
|
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 |
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
|
242 |
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
|
243 |
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
|
244 |
buf.Reset() |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
245 |
} |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
246 |
} |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
247 |
leftover := buf.String() |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
248 |
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
|
249 |
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
|
250 |
} |
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
251 |
} |
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
252 |
|
29
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
253 |
// bindDone is called when we've finished resource binding (and all |
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
254 |
// the negotiations that precede it). Now we can start accepting |
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
255 |
// traffic from the app. |
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
256 |
func (cl *Client) bindDone() { |
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
257 |
cl.inputControl <- 1 |
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
258 |
} |
a456133ed0ac
Don't accept data on Client.Out until resource binding is
Chris Jones <chris@cjones.org>
parents:
28
diff
changeset
|
259 |
|
33
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
260 |
// Start an XMPP session. A typical XMPP client should call this |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
261 |
// immediately after creating the Client in order to start the |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
262 |
// session, retrieve the roster, and broadcast an initial |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
263 |
// presence. The presence can be as simple as a newly-initialized |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
264 |
// Presence struct. See RFC 3921, Section 3. |
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
265 |
func (cl *Client) StartSession(getRoster bool, pr *Presence) error { |
72 | 266 |
id := <-Id |
267 |
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
|
268 |
ch := make(chan error) |
28 | 269 |
f := func(st Stanza) bool { |
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
270 |
iq, ok := st.(*Iq) |
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
271 |
if !ok { |
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
|
272 |
Warn.Logf("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
|
273 |
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
|
274 |
return false |
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
275 |
} |
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
276 |
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
|
277 |
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
|
278 |
ch <- iq.Error |
28 | 279 |
return false |
280 |
} |
|
281 |
ch <- nil |
|
282 |
return false |
|
283 |
} |
|
284 |
cl.HandleStanza(id, f) |
|
285 |
cl.Out <- iq |
|
33
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
286 |
|
28 | 287 |
// Now wait until the callback is called. |
72 | 288 |
if err := <-ch; err != nil { |
33
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
289 |
return err |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
290 |
} |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
291 |
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
|
292 |
err := fetchRoster(cl) |
33
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
293 |
if err != nil { |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
294 |
return err |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
295 |
} |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
296 |
} |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
297 |
if pr != nil { |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
298 |
cl.Out <- pr |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
299 |
} |
571713f49494
Added roster retrieval to StartSession().
Chris Jones <chris@cjones.org>
parents:
32
diff
changeset
|
300 |
return nil |
28 | 301 |
} |
45
abf958bcc201
Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents:
44
diff
changeset
|
302 |
|
abf958bcc201
Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents:
44
diff
changeset
|
303 |
// 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
|
304 |
// 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
|
305 |
// 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
|
306 |
// 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
|
307 |
// 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
|
308 |
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
|
309 |
cl.filterOut <- out |
72 | 310 |
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
|
311 |
} |