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