author | Chris Jones <chris@cjones.org> |
Sat, 09 Nov 2013 12:37:49 -0700 | |
changeset 181 | 750bc33ccdda |
parent 180 | 3010996c1928 |
child 185 | ba8a4ae40e13 |
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 |
// This package implements a simple XMPP client according to RFCs 3920 |
119
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
2 |
// and 3921, plus the various XEPs at http://xmpp.org/protocols/. The |
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
3 |
// implementation is structured as a stack of layers, with TCP at the |
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
4 |
// bottom and the application at the top. The application receives and |
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
5 |
// sends structures representing XMPP stanzas. Additional stanza |
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
6 |
// parsers can be inserted into the stack of layers as extensions. |
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
7 |
package xmpp |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
8 |
|
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
9 |
import ( |
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
|
10 |
"crypto/tls" |
98
c9cc4eda6dce
Updated for Go 1.0 + upcoming XML fixes.
Chris Jones <chris@cjones.org>
parents:
72
diff
changeset
|
11 |
"encoding/xml" |
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
12 |
"fmt" |
4
a8fbec71a194
Added an interactive test and made Client implement io.Closer.
Chris Jones <chris@cjones.org>
parents:
2
diff
changeset
|
13 |
"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
|
14 |
"net" |
128
8342afcffc92
Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents:
127
diff
changeset
|
15 |
"reflect" |
168 | 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. |
118
fb9bb98a8d70
Code cleanup: Renamed the Version constant. Moved the unique-ID generator into its own file.
Chris Jones <christian.jones@sri.com>
parents:
116
diff
changeset
|
21 |
XMPPVersion = "1.0" |
10 | 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 |
|
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
38 |
// A filter can modify the XMPP traffic to or from the remote |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
39 |
// server. It's part of an Extension. The filter function will be |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
40 |
// called in a new goroutine, so it doesn't need to return. The filter |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
41 |
// should close its output when its input is closed. |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
42 |
type Filter func(in <-chan Stanza, out chan<- Stanza) |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
43 |
|
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
44 |
// 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
|
45 |
type Extension struct { |
158
2d948fcbb5d7
Renamed Extension.StanzaHandlers to StanzaTypes, and updated the doc comment.
Chris Jones <chris@cjones.org>
parents:
157
diff
changeset
|
46 |
// Maps from an XML name to a structure which holds stanza |
2d948fcbb5d7
Renamed Extension.StanzaHandlers to StanzaTypes, and updated the doc comment.
Chris Jones <chris@cjones.org>
parents:
157
diff
changeset
|
47 |
// contents with that name. |
2d948fcbb5d7
Renamed Extension.StanzaHandlers to StanzaTypes, and updated the doc comment.
Chris Jones <chris@cjones.org>
parents:
157
diff
changeset
|
48 |
StanzaTypes map[xml.Name]reflect.Type |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
49 |
// If non-nil, will be called once to start the filter |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
50 |
// running. RecvFilter intercepts incoming messages on their |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
51 |
// way from the remote server to the application; SendFilter |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
52 |
// intercepts messages going the other direction. |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
53 |
RecvFilter Filter |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
54 |
SendFilter Filter |
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
55 |
} |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
56 |
|
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
57 |
// 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
|
58 |
type Client struct { |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
59 |
// This client's full JID, including resource |
72 | 60 |
Jid JID |
61 |
password string |
|
11
48be1ae93fd4
Added SASL digest authentication.
Chris Jones <chris@cjones.org>
parents:
10
diff
changeset
|
62 |
saslExpected string |
72 | 63 |
authDone bool |
144
9d7fdb1d2fc1
Renamed HandleStanza to SetCallback.
Chris Jones <christian.jones@sri.com>
parents:
142
diff
changeset
|
64 |
handlers chan *callback |
119
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
65 |
// Incoming XMPP stanzas from the remote will be published on |
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
66 |
// this channel. Information which is used by this library to |
712aa5780660
Documentation cleanup.
Chris Jones <christian.jones@sri.com>
parents:
118
diff
changeset
|
67 |
// set up the XMPP stream will not appear here. |
127
a8f9a0c07fc8
Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents:
126
diff
changeset
|
68 |
Recv <-chan Stanza |
17 | 69 |
// Outgoing XMPP stanzas to the server should be sent to this |
170
d496de556c9a
Trying to be smarter about closing channels: Ask the application not to close the Send channel, but let us do that from Close() instead.
Chris Jones <chris@cjones.org>
parents:
169
diff
changeset
|
70 |
// channel. The application should not close this channel; |
d496de556c9a
Trying to be smarter about closing channels: Ask the application not to close the Send channel, but let us do that from Close() instead.
Chris Jones <chris@cjones.org>
parents:
169
diff
changeset
|
71 |
// rather, call Close(). |
127
a8f9a0c07fc8
Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents:
126
diff
changeset
|
72 |
Send chan<- Stanza |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
73 |
sendRaw chan<- interface{} |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
74 |
statmgr *statmgr |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
75 |
// The client's roster is also known as the buddy list. It's |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
76 |
// the set of contacts which are known to this JID, or which |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
77 |
// this JID is known to. |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
78 |
Roster Roster |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
79 |
// Features advertised by the remote. |
128
8342afcffc92
Use reflection instead of constructor functions to create extended stanza structures.
Chris Jones <christian.jones@sri.com>
parents:
127
diff
changeset
|
80 |
Features *Features |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
81 |
sendFilterAdd, recvFilterAdd chan Filter |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
82 |
tlsConfig tls.Config |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
83 |
layer1 *layer1 |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
84 |
error chan error |
168 | 85 |
shutdownOnce sync.Once |
2
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
86 |
} |
4dabfef08c8c
Forgot to add the new xmpp.go from my last commit. Also added some
Chris Jones <chris@cjones.org>
parents:
diff
changeset
|
87 |
|
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
88 |
// Creates an XMPP client identified by the given JID, authenticating |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
89 |
// with the provided password and TLS config. Zero or more extensions |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
90 |
// may be specified. The initial presence will be broadcast. If status |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
91 |
// is non-nil, connection progress information will be sent on it. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
92 |
func NewClient(jid *JID, password string, tlsconf tls.Config, exts []Extension, |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
93 |
pr Presence, status chan<- Status) (*Client, error) { |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
94 |
|
175
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
95 |
// Resolve the domain in the JID. |
178
ccfebbd9f49b
Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents:
176
diff
changeset
|
96 |
_, srvs, err := net.LookupSRV(clientSrv, "tcp", jid.Domain()) |
175
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
97 |
if err != nil { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
98 |
return nil, fmt.Errorf("LookupSrv %s: %v", jid.Domain, err) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
99 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
100 |
if len(srvs) == 0 { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
101 |
return nil, fmt.Errorf("LookupSrv %s: no results", jid.Domain) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
102 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
103 |
|
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
104 |
var tcp *net.TCPConn |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
105 |
for _, srv := range srvs { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
106 |
addrStr := fmt.Sprintf("%s:%d", srv.Target, srv.Port) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
107 |
var addr *net.TCPAddr |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
108 |
addr, err = net.ResolveTCPAddr("tcp", addrStr) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
109 |
if err != nil { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
110 |
err = fmt.Errorf("ResolveTCPAddr(%s): %s", |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
111 |
addrStr, err.Error()) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
112 |
continue |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
113 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
114 |
tcp, err = net.DialTCP("tcp", nil, addr) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
115 |
if tcp != nil { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
116 |
break |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
117 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
118 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
119 |
if tcp == nil { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
120 |
return nil, err |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
121 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
122 |
|
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
123 |
return newClient(tcp, jid, password, tlsconf, exts, pr, status) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
124 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
125 |
|
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
126 |
// Connect to the specified host and port. This is otherwise identical |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
127 |
// to NewClient. |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
128 |
func NewClientFromHost(jid *JID, password string, tlsconf tls.Config, |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
129 |
exts []Extension, pr Presence, status chan<- Status, host string, |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
130 |
port int) (*Client, error) { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
131 |
|
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
132 |
addrStr := fmt.Sprintf("%s:%d", host, port) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
133 |
addr, err := net.ResolveTCPAddr("tcp", addrStr) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
134 |
if err != nil { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
135 |
return nil, err |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
136 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
137 |
tcp, err := net.DialTCP("tcp", nil, addr) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
138 |
if err != nil { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
139 |
return nil, err |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
140 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
141 |
|
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
142 |
return newClient(tcp, jid, password, tlsconf, exts, pr, status) |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
143 |
} |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
144 |
|
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
145 |
func newClient(tcp *net.TCPConn, jid *JID, password string, tlsconf tls.Config, |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
146 |
exts []Extension, pr Presence, status chan<- Status) (*Client, error) { |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
147 |
|
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
148 |
// Include the mandatory extensions. |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
149 |
roster := newRosterExt() |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
150 |
exts = append(exts, roster.Extension) |
60
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
151 |
exts = append(exts, bindExt) |
6d4f43f7dc19
Made a generic extension interface.
Chris Jones <chris@cjones.org>
parents:
59
diff
changeset
|
152 |
|
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
153 |
cl := new(Client) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
154 |
cl.Roster = *roster |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
155 |
cl.password = password |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
156 |
cl.Jid = *jid |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
157 |
cl.handlers = make(chan *callback, 100) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
158 |
cl.tlsConfig = tlsconf |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
159 |
cl.sendFilterAdd = make(chan Filter) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
160 |
cl.recvFilterAdd = make(chan Filter) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
161 |
cl.statmgr = newStatmgr(status) |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
162 |
cl.error = make(chan error, 1) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
163 |
|
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
164 |
extStanza := make(map[xml.Name]reflect.Type) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
165 |
for _, ext := range exts { |
158
2d948fcbb5d7
Renamed Extension.StanzaHandlers to StanzaTypes, and updated the doc comment.
Chris Jones <chris@cjones.org>
parents:
157
diff
changeset
|
166 |
for k, v := range ext.StanzaTypes { |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
167 |
if _, ok := extStanza[k]; ok { |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
168 |
return nil, fmt.Errorf("duplicate handler %s", |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
169 |
k) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
170 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
171 |
extStanza[k] = v |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
172 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
173 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
174 |
|
175
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
175 |
// The thing that called this made a TCP connection, so now we |
fc8702a8572e
Allow the client to specify a host and port to connect to, rather than using SRV records.
Chris Jones <chris@cjones.org>
parents:
166
diff
changeset
|
176 |
// can signal that it's connected. |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
177 |
cl.setStatus(StatusConnected) |
36
9fe022261dcc
Added a capability to use extensions. There are still some bugs with
Chris Jones <chris@cjones.org>
parents:
34
diff
changeset
|
178 |
|
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
179 |
// Start the transport handler, initially unencrypted. |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
180 |
recvReader, recvWriter := io.Pipe() |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
181 |
sendReader, sendWriter := io.Pipe() |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
182 |
cl.layer1 = cl.startLayer1(tcp, recvWriter, sendReader, |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
183 |
cl.statmgr.newListener()) |
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
184 |
|
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
185 |
// Start the reader and writer that convert to and from XML. |
147
d7679d991b17
Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents:
146
diff
changeset
|
186 |
recvXmlCh := make(chan interface{}) |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
187 |
go cl.recvXml(recvReader, recvXmlCh, extStanza) |
147
d7679d991b17
Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents:
146
diff
changeset
|
188 |
sendXmlCh := make(chan interface{}) |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
189 |
cl.sendRaw = sendXmlCh |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
190 |
go cl.sendXml(sendWriter, sendXmlCh) |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
191 |
|
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
192 |
// Start the reader and writer that convert between XML and |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
193 |
// XMPP stanzas. |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
194 |
recvRawXmpp := make(chan Stanza) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
195 |
go cl.recvStream(recvXmlCh, recvRawXmpp, cl.statmgr.newListener()) |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
196 |
sendRawXmpp := make(chan Stanza) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
197 |
go sendStream(sendXmlCh, sendRawXmpp, cl.statmgr.newListener()) |
5
faef59c8db05
Added a goroutine to read data from the remote and parse it into
Chris Jones <chris@cjones.org>
parents:
4
diff
changeset
|
198 |
|
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
199 |
// Start the managers for the filters that can modify what the |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
200 |
// app sees or sends. |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
201 |
recvFiltXmpp := make(chan Stanza) |
127
a8f9a0c07fc8
Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents:
126
diff
changeset
|
202 |
cl.Recv = recvFiltXmpp |
121
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
203 |
go filterMgr(cl.recvFilterAdd, recvRawXmpp, recvFiltXmpp) |
ebb86cbdd218
Changed the way filters work. They're now symmetrical, consisting of a paired send filter and receive filter.
Chris Jones <christian.jones@sri.com>
parents:
120
diff
changeset
|
204 |
sendFiltXmpp := make(chan Stanza) |
127
a8f9a0c07fc8
Renamed client.In and client.Out to Recv and Send, respectively.
Chris Jones <christian.jones@sri.com>
parents:
126
diff
changeset
|
205 |
cl.Send = sendFiltXmpp |
134
80b764fa2f08
Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents:
132
diff
changeset
|
206 |
go filterMgr(cl.sendFilterAdd, sendFiltXmpp, sendRawXmpp) |
80b764fa2f08
Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents:
132
diff
changeset
|
207 |
// Set up the initial filters. |
80b764fa2f08
Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents:
132
diff
changeset
|
208 |
for _, ext := range exts { |
80b764fa2f08
Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents:
132
diff
changeset
|
209 |
cl.AddRecvFilter(ext.RecvFilter) |
80b764fa2f08
Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents:
132
diff
changeset
|
210 |
cl.AddSendFilter(ext.SendFilter) |
80b764fa2f08
Fixed some logic errors and initialized some things that needed to be initialized.
Chris Jones <christian.jones@sri.com>
parents:
132
diff
changeset
|
211 |
} |
45
abf958bcc201
Added a stack of filters which can intercept data before it gets to
Chris Jones <chris@cjones.org>
parents:
44
diff
changeset
|
212 |
|
8
30a7752cf8f7
Added the ability to parse <stream:features>.
Chris Jones <chris@cjones.org>
parents:
6
diff
changeset
|
213 |
// Initial handshake. |
178
ccfebbd9f49b
Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents:
176
diff
changeset
|
214 |
hsOut := &stream{To: jid.Domain(), Version: XMPPVersion} |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
215 |
cl.sendRaw <- hsOut |
9
4fe926b03827
Reorganize so we have a layered approach to IO with the server.
Chris Jones <chris@cjones.org>
parents:
8
diff
changeset
|
216 |
|
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
217 |
// Wait until resource binding is complete. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
218 |
if err := cl.statmgr.awaitStatus(StatusBound); err != nil { |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
219 |
return nil, cl.getError(err) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
220 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
221 |
|
157
eadf15a06ff5
Don't keep the password around after we've used it.
Chris Jones <chris@cjones.org>
parents:
153
diff
changeset
|
222 |
// Forget about the password, for paranoia's sake. |
eadf15a06ff5
Don't keep the password around after we've used it.
Chris Jones <chris@cjones.org>
parents:
153
diff
changeset
|
223 |
cl.password = "" |
eadf15a06ff5
Don't keep the password around after we've used it.
Chris Jones <chris@cjones.org>
parents:
153
diff
changeset
|
224 |
|
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
225 |
// Initialize the session. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
226 |
id := NextId() |
180
3010996c1928
Changed the type of structure fields which hold JIDs from string to JID.
Chris Jones <chris@cjones.org>
parents:
178
diff
changeset
|
227 |
iq := &Iq{Header: Header{To: JID(cl.Jid.Domain()), Id: id, Type: "set", |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
228 |
Nested: []interface{}{Generic{XMLName: xml.Name{Space: NsSession, Local: "session"}}}}} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
229 |
ch := make(chan error) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
230 |
f := func(st Stanza) { |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
231 |
iq, ok := st.(*Iq) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
232 |
if !ok { |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
233 |
ch <- fmt.Errorf("bad session start reply: %#v", st) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
234 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
235 |
if iq.Type == "error" { |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
236 |
ch <- fmt.Errorf("Can't start session: %v", iq.Error) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
237 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
238 |
ch <- nil |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
239 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
240 |
cl.SetCallback(id, f) |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
241 |
cl.sendRaw <- iq |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
242 |
// Now wait until the callback is called. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
243 |
if err := <-ch; err != nil { |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
244 |
return nil, cl.getError(err) |
153
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
245 |
} |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
246 |
|
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
247 |
// This allows the client to receive stanzas. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
248 |
cl.setStatus(StatusRunning) |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
249 |
|
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
250 |
// Request the roster. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
251 |
cl.Roster.update() |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
252 |
|
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
253 |
// Send the initial presence. |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
254 |
cl.Send <- &pr |
bbd4166df95d
Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
148
diff
changeset
|
255 |
|
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
256 |
return cl, cl.getError(nil) |
6
8e425e340ca1
Implemented writing to the remote. Now we have bidirectional communication.
Chris Jones <christian.jones@sri.com>
parents:
5
diff
changeset
|
257 |
} |
162
7b5586a5e109
Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents:
158
diff
changeset
|
258 |
|
7b5586a5e109
Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents:
158
diff
changeset
|
259 |
func (cl *Client) Close() { |
7b5586a5e109
Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents:
158
diff
changeset
|
260 |
// Shuts down the receivers: |
7b5586a5e109
Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents:
158
diff
changeset
|
261 |
cl.setStatus(StatusShutdown) |
169
f59b79d032da
Make an attempt to only close the send channel if it's still open.
Chris Jones <chris@cjones.org>
parents:
168
diff
changeset
|
262 |
|
162
7b5586a5e109
Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents:
158
diff
changeset
|
263 |
// Shuts down the senders: |
170
d496de556c9a
Trying to be smarter about closing channels: Ask the application not to close the Send channel, but let us do that from Close() instead.
Chris Jones <chris@cjones.org>
parents:
169
diff
changeset
|
264 |
cl.shutdownOnce.Do(func() { close(cl.Send) }) |
162
7b5586a5e109
Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents:
158
diff
changeset
|
265 |
} |
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
266 |
|
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
267 |
// If there's a buffered error in the channel, return it. Otherwise, |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
268 |
// return what was passed to us. The idea is that the error in the |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
269 |
// channel probably preceded (and caused) the one that's passed as an |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
270 |
// argument here. |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
271 |
func (cl *Client) getError(err1 error) error { |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
272 |
select { |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
273 |
case err0 := <-cl.error: |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
274 |
return err0 |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
275 |
default: |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
276 |
return err1 |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
277 |
} |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
278 |
} |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
279 |
|
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
280 |
// Register an error that happened in the internals somewhere. If |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
281 |
// there's already an error in the channel, discard the newer one in |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
282 |
// favor of the older. |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
283 |
func (cl *Client) setError(err error) { |
170
d496de556c9a
Trying to be smarter about closing channels: Ask the application not to close the Send channel, but let us do that from Close() instead.
Chris Jones <chris@cjones.org>
parents:
169
diff
changeset
|
284 |
defer cl.Close() |
d496de556c9a
Trying to be smarter about closing channels: Ask the application not to close the Send channel, but let us do that from Close() instead.
Chris Jones <chris@cjones.org>
parents:
169
diff
changeset
|
285 |
defer cl.setStatus(StatusError) |
164
6b527647086c
Changed order of operations in setError() so that the underlying error is reported.
Chris Jones <chris@cjones.org>
parents:
163
diff
changeset
|
286 |
|
163
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
287 |
if len(cl.error) > 0 { |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
288 |
return |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
289 |
} |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
290 |
// If we're in a race between two calls to this function, |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
291 |
// trying to set the "first" error, just arbitrarily let one |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
292 |
// of them win. |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
293 |
select { |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
294 |
case cl.error <- err: |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
295 |
default: |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
296 |
} |
3f891f7fe817
Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents:
162
diff
changeset
|
297 |
} |