~blamar/+junk/openstack-api-arrrg

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/core/howto/tutorial/protocol.html

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
 
2
  <head>
 
3
<title>Twisted Documentation: The Evolution of Finger: adding features to the finger service</title>
 
4
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
 
5
  </head>
 
6
 
 
7
  <body bgcolor="white">
 
8
    <h1 class="title">The Evolution of Finger: adding features to the finger service</h1>
 
9
    <div class="toc"><ol><li><a href="#auto0">Introduction</a></li><li><a href="#auto1">Setting Message By Local Users</a></li><li><a href="#auto2">Use Services to Make Dependencies Sane</a></li><li><a href="#auto3">Read Status File</a></li><li><a href="#auto4">Announce on Web, Too</a></li><li><a href="#auto5">Announce on IRC, Too</a></li><li><a href="#auto6">Add XML-RPC Support</a></li></ol></div>
 
10
    <div class="content">
 
11
 
 
12
<span/>
 
13
 
 
14
<h2>Introduction<a name="auto0"/></h2>
 
15
 
 
16
<p> This is the second part of the Twisted tutorial <a href="index.html" shape="rect">Twisted from Scratch, or The Evolution of Finger</a>.</p>
 
17
 
 
18
<p>In this section of the tutorial, our finger server will continue to sprout
 
19
features: the ability for users to set finger announces, and using our finger
 
20
service to send those announcements on the web, on IRC and over XML-RPC.
 
21
Resources and XML-RPC are introduced in the Web Applications portion of
 
22
the <a href="../../../web/howto/index.html" shape="rect">Twisted Web howto</a>. More examples
 
23
using <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.words.protocols.irc.html" title="twisted.words.protocols.irc">twisted.words.protocols.irc</a></code> can be found
 
24
in <a href="../clients.html" shape="rect">Writing a TCP Client</a> and
 
25
the <a href="../../../words/examples/index.html" shape="rect">Twisted Words examples</a>.</p>
 
26
 
 
27
<h2>Setting Message By Local Users<a name="auto1"/></h2>
 
28
 
 
29
<p>Now that port 1079 is free, maybe we can use it with a different
 
30
server, one which will let people set their messages. It does
 
31
no access control, so anyone who can login to the machine can
 
32
set any message. We assume this is the desired behavior in
 
33
our case. Testing it can be done by simply:
 
34
</p>
 
35
 
 
36
<pre class="shell" xml:space="preserve">
 
37
% nc localhost 1079   # or telnet localhost 1079
 
38
moshez
 
39
Giving a tutorial now, sorry!
 
40
^D
 
41
</pre>
 
42
 
 
43
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
44
 2
 
45
 3
 
46
 4
 
47
 5
 
48
 6
 
49
 7
 
50
 8
 
51
 9
 
52
10
 
53
11
 
54
12
 
55
13
 
56
14
 
57
15
 
58
16
 
59
17
 
60
18
 
61
19
 
62
20
 
63
21
 
64
22
 
65
23
 
66
24
 
67
25
 
68
26
 
69
27
 
70
28
 
71
29
 
72
30
 
73
31
 
74
32
 
75
33
 
76
34
 
77
35
 
78
36
 
79
37
 
80
38
 
81
39
 
82
40
 
83
41
 
84
42
 
85
43
 
86
44
 
87
45
 
88
46
 
89
47
 
90
48
 
91
49
 
92
50
 
93
51
 
94
52
 
95
53
 
96
54
 
97
55
 
98
</p><span class="py-src-comment"># But let's try and fix setting away messages, shall we?</span>
 
99
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
 
100
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
 
101
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
102
 
 
103
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
104
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
105
        <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
 
106
 
 
107
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
108
            <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
109
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
110
 
 
111
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
112
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">message</span> + <span class="py-src-string">'\r\n'</span>)
 
113
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
 
114
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
115
 
 
116
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerFactory</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">ServerFactory</span>):
 
117
    <span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
 
118
 
 
119
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, **<span class="py-src-parameter">kwargs</span>):
 
120
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = <span class="py-src-variable">kwargs</span>
 
121
 
 
122
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
123
        <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">&quot;No such user&quot;</span>))
 
124
 
 
125
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerSetterProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
126
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
 
127
        <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span> = []
 
128
 
 
129
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">line</span>):
 
130
        <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>.<span class="py-src-variable">append</span>(<span class="py-src-variable">line</span>)
 
131
 
 
132
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionLost</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">reason</span>):
 
133
        <span class="py-src-variable">user</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>[<span class="py-src-number">0</span>]
 
134
        <span class="py-src-variable">status</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>[<span class="py-src-number">1</span>]
 
135
        <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">setUser</span>(<span class="py-src-variable">user</span>, <span class="py-src-variable">status</span>)
 
136
 
 
137
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerSetterFactory</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">ServerFactory</span>):
 
138
    <span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerSetterProtocol</span>
 
139
 
 
140
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">fingerFactory</span>):
 
141
        <span class="py-src-variable">self</span>.<span class="py-src-variable">fingerFactory</span> = <span class="py-src-variable">fingerFactory</span>
 
142
 
 
143
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">setUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">status</span>):
 
144
        <span class="py-src-variable">self</span>.<span class="py-src-variable">fingerFactory</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
 
145
 
 
146
<span class="py-src-variable">ff</span> = <span class="py-src-variable">FingerFactory</span>(<span class="py-src-variable">moshez</span>=<span class="py-src-string">'Happy and well'</span>)
 
147
<span class="py-src-variable">fsf</span> = <span class="py-src-variable">FingerSetterFactory</span>(<span class="py-src-variable">ff</span>)
 
148
 
 
149
<span class="py-src-variable">application</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">'finger'</span>, <span class="py-src-variable">uid</span>=<span class="py-src-number">1</span>, <span class="py-src-variable">gid</span>=<span class="py-src-number">1</span>)
 
150
<span class="py-src-variable">serviceCollection</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>)
 
151
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">79</span>,<span class="py-src-variable">ff</span>).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
152
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">1079</span>,<span class="py-src-variable">fsf</span>).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
153
</pre><div class="caption">Source listing - <a href="listings/finger/finger12.tac"><span class="filename">listings/finger/finger12.tac</span></a></div></div>
 
154
 
 
155
<p>This program has two protocol-factory-TCPServer pairs, which are both child 
 
156
services of the application.  Specifically, the 
 
157
<code base="API" class="twisted.application.service.Service">setServiceParent</code> 
 
158
method is used to define the two TCPServer services as children of 
 
159
<code>application</code>, which implements
 
160
<code base="API" class="twisted.application.servce">IServiceCollection</code>. 
 
161
Both services are thus started with the application.</p>
 
162
 
 
163
<h2>Use Services to Make Dependencies Sane<a name="auto2"/></h2>
 
164
 
 
165
<p>The previous version had the setter poke at the innards of the
 
166
finger factory. This strategy is usually not a good idea: this version makes
 
167
both factories symmetric by making them both look at a single
 
168
object. Services are useful for when an object is needed which is
 
169
not related to a specific network server. Here, we define a common service 
 
170
class with methods that will create factories on the fly. The service 
 
171
also contains methods the factories will depend on.</p>
 
172
 
 
173
<p>The factory-creation methods, <code>getFingerFactory</code> and 
 
174
<code>getFingerSetterFactory</code>, follow this pattern:</p>
 
175
 
 
176
<ol>
 
177
 
 
178
<li>Instantiate a generic server factory, 
 
179
<code>twisted.internet.protocol.ServerFactory</code>.</li>
 
180
 
 
181
<li>Set the protocol class, just like our factory class would have.</li>
 
182
 
 
183
<li>Copy a service method to the factory as a function attribute.  The 
 
184
function won't have access to the factory's <code>self</code>, but that's OK 
 
185
because as a bound method it has access to the service's <code>self</code>, 
 
186
which is what it needs.  For <code>getUser</code>, a custom method defined in 
 
187
the service gets copied.  For <code>setUser</code>, a standard method of the 
 
188
<code>users</code> dictionary is copied.</li>
 
189
 
 
190
</ol>
 
191
 
 
192
<p>Thus, we stopped subclassing: the service simply puts useful methods and 
 
193
attributes inside the factories. We are getting better at protocol design:
 
194
none of our protocol classes had to be changed, and neither will have to 
 
195
change until the end of the tutorial.</p>
 
196
 
 
197
<p>As an application 
 
198
<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.application.service.service.html" title="twisted.application.service.service">service</a></code> , this new 
 
199
finger service implements the 
 
200
<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.application.service.IService.html" title="twisted.application.service.IService">IService</a></code> interface 
 
201
and can be started and stopped in a standardized manner.  We'll make use of 
 
202
this in the next example.</p>
 
203
 
 
204
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
205
 2
 
206
 3
 
207
 4
 
208
 5
 
209
 6
 
210
 7
 
211
 8
 
212
 9
 
213
10
 
214
11
 
215
12
 
216
13
 
217
14
 
218
15
 
219
16
 
220
17
 
221
18
 
222
19
 
223
20
 
224
21
 
225
22
 
226
23
 
227
24
 
228
25
 
229
26
 
230
27
 
231
28
 
232
29
 
233
30
 
234
31
 
235
32
 
236
33
 
237
34
 
238
35
 
239
36
 
240
37
 
241
38
 
242
39
 
243
40
 
244
41
 
245
42
 
246
43
 
247
44
 
248
45
 
249
46
 
250
47
 
251
48
 
252
49
 
253
50
 
254
51
 
255
52
 
256
53
 
257
54
 
258
55
 
259
56
 
260
57
 
261
58
 
262
59
 
263
</p><span class="py-src-comment"># Fix asymmetry</span>
 
264
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
 
265
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
 
266
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
267
 
 
268
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
269
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
270
        <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
 
271
 
 
272
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
273
            <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
274
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
275
 
 
276
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
277
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">message</span> + <span class="py-src-string">'\r\n'</span>)
 
278
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
 
279
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
280
 
 
281
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerSetterProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
282
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
 
283
        <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span> = []
 
284
 
 
285
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">line</span>):
 
286
        <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>.<span class="py-src-variable">append</span>(<span class="py-src-variable">line</span>)
 
287
 
 
288
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionLost</span>(<span class="py-src-parameter">self</span>,<span class="py-src-parameter">reason</span>):
 
289
        <span class="py-src-variable">user</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>[<span class="py-src-number">0</span>]
 
290
        <span class="py-src-variable">status</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>[<span class="py-src-number">1</span>]
 
291
        <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">setUser</span>(<span class="py-src-variable">user</span>, <span class="py-src-variable">status</span>)
 
292
 
 
293
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerService</span>(<span class="py-src-parameter">service</span>.<span class="py-src-parameter">Service</span>):
 
294
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, **<span class="py-src-parameter">kwargs</span>):
 
295
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = <span class="py-src-variable">kwargs</span>
 
296
 
 
297
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
298
        <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">&quot;No such user&quot;</span>))
 
299
 
 
300
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">setUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">status</span>):
 
301
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
 
302
 
 
303
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getFingerFactory</span>(<span class="py-src-parameter">self</span>):
 
304
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ServerFactory</span>()
 
305
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
 
306
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
307
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
308
 
 
309
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getFingerSetterFactory</span>(<span class="py-src-parameter">self</span>):
 
310
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ServerFactory</span>()
 
311
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerSetterProtocol</span>
 
312
        <span class="py-src-variable">f</span>.<span class="py-src-variable">setUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">setUser</span>
 
313
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
314
 
 
315
<span class="py-src-variable">application</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">'finger'</span>, <span class="py-src-variable">uid</span>=<span class="py-src-number">1</span>, <span class="py-src-variable">gid</span>=<span class="py-src-number">1</span>)
 
316
<span class="py-src-variable">f</span> = <span class="py-src-variable">FingerService</span>(<span class="py-src-variable">moshez</span>=<span class="py-src-string">'Happy and well'</span>)
 
317
<span class="py-src-variable">serviceCollection</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>)
 
318
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">79</span>,<span class="py-src-variable">f</span>.<span class="py-src-variable">getFingerFactory</span>()
 
319
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
320
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">1079</span>,<span class="py-src-variable">f</span>.<span class="py-src-variable">getFingerSetterFactory</span>()
 
321
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
322
</pre><div class="caption">Source listing - <a href="listings/finger/finger13.tac"><span class="filename">listings/finger/finger13.tac</span></a></div></div>
 
323
 
 
324
 
 
325
 
 
326
<h2>Read Status File<a name="auto3"/></h2>
 
327
 
 
328
<p>This version shows how, instead of just letting users set their
 
329
messages, we can read those from a centrally managed file. We cache
 
330
results, and every 30 seconds we refresh it. Services are useful
 
331
for such scheduled tasks.</p>
 
332
 
 
333
<div class="listing"><pre>
 
334
moshez: happy and well
 
335
shawn: alive 
 
336
</pre><div class="caption">sample /etc/users file - <a href="listings/finger/etc.users"><span class="filename">listings/finger/etc.users</span></a></div></div>
 
337
 
 
338
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
339
 2
 
340
 3
 
341
 4
 
342
 5
 
343
 6
 
344
 7
 
345
 8
 
346
 9
 
347
10
 
348
11
 
349
12
 
350
13
 
351
14
 
352
15
 
353
16
 
354
17
 
355
18
 
356
19
 
357
20
 
358
21
 
359
22
 
360
23
 
361
24
 
362
25
 
363
26
 
364
27
 
365
28
 
366
29
 
367
30
 
368
31
 
369
32
 
370
33
 
371
34
 
372
35
 
373
36
 
374
37
 
375
38
 
376
39
 
377
40
 
378
41
 
379
42
 
380
43
 
381
44
 
382
45
 
383
46
 
384
47
 
385
48
 
386
49
 
387
50
 
388
51
 
389
52
 
390
53
 
391
54
 
392
55
 
393
</p><span class="py-src-comment"># Read from file</span>
 
394
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
 
395
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
 
396
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
397
 
 
398
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
399
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
400
        <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
 
401
 
 
402
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
403
            <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
404
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
405
 
 
406
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
407
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">message</span> + <span class="py-src-string">'\r\n'</span>)
 
408
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
 
409
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
410
 
 
411
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerService</span>(<span class="py-src-parameter">service</span>.<span class="py-src-parameter">Service</span>):
 
412
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">filename</span>):
 
413
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = {}
 
414
        <span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span> = <span class="py-src-variable">filename</span>
 
415
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>()
 
416
 
 
417
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_read</span>(<span class="py-src-parameter">self</span>):
 
418
        <span class="py-src-keyword">for</span> <span class="py-src-variable">line</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">file</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span>):
 
419
            <span class="py-src-variable">user</span>, <span class="py-src-variable">status</span> = <span class="py-src-variable">line</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">':'</span>, <span class="py-src-number">1</span>)
 
420
            <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">strip</span>()
 
421
            <span class="py-src-variable">status</span> = <span class="py-src-variable">status</span>.<span class="py-src-variable">strip</span>()
 
422
            <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
 
423
        <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span> = <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">30</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>)
 
424
 
 
425
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">startService</span>(<span class="py-src-parameter">self</span>):
 
426
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>()
 
427
        <span class="py-src-variable">service</span>.<span class="py-src-variable">Service</span>.<span class="py-src-variable">startService</span>(<span class="py-src-variable">self</span>)
 
428
 
 
429
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">stopService</span>(<span class="py-src-parameter">self</span>):
 
430
        <span class="py-src-variable">service</span>.<span class="py-src-variable">Service</span>.<span class="py-src-variable">stopService</span>(<span class="py-src-variable">self</span>)
 
431
        <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span>.<span class="py-src-variable">cancel</span>()
 
432
 
 
433
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
434
        <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">&quot;No such user&quot;</span>))
 
435
 
 
436
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getFingerFactory</span>(<span class="py-src-parameter">self</span>):
 
437
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ServerFactory</span>()
 
438
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
 
439
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
440
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
441
 
 
442
<span class="py-src-variable">application</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">'finger'</span>, <span class="py-src-variable">uid</span>=<span class="py-src-number">1</span>, <span class="py-src-variable">gid</span>=<span class="py-src-number">1</span>)
 
443
<span class="py-src-variable">f</span> = <span class="py-src-variable">FingerService</span>(<span class="py-src-string">'/etc/users'</span>)
 
444
<span class="py-src-variable">finger</span> = <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">79</span>, <span class="py-src-variable">f</span>.<span class="py-src-variable">getFingerFactory</span>())
 
445
 
 
446
<span class="py-src-variable">finger</span>.<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>))
 
447
<span class="py-src-variable">f</span>.<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>))
 
448
</pre><div class="caption">Source listing - <a href="listings/finger/finger14.tac"><span class="filename">listings/finger/finger14.tac</span></a></div></div>
 
449
 
 
450
<p>Since this verison is reading data from a file (and refreshing the data 
 
451
every 30 seconds), there is no <code>FingerSetterFactory</code> and thus 
 
452
nothing listening on port 1079.</p>
 
453
 
 
454
<p>Here we override the standard 
 
455
<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.application.service.Service.startService.html" title="twisted.application.service.Service.startService">startService</a></code> 
 
456
and 
 
457
<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.application.service.Service.stopService.html" title="twisted.application.service.Service.stopService">stopService</a></code> 
 
458
hooks in the Finger service, which is set up as a child service of 
 
459
the application in the last line of the code. <code>startService</code> calls 
 
460
<code>_read</code>, the function responsible for reading the data; 
 
461
<code>reactor.callLater</code> is then used to schedule it to run again after 
 
462
thirty seconds every time it is called. <code>reactor.callLater</code> returns 
 
463
an object that lets us cancel the scheduled run in <code>stopService</code> 
 
464
using its <code>cancel</code> method.</p>
 
465
 
 
466
<h2>Announce on Web, Too<a name="auto4"/></h2>
 
467
 
 
468
<p>The same kind of service can also produce things useful for
 
469
other protocols. For example, in twisted.web, the factory
 
470
itself (<code base="API" class="twisted.web.server">Site</code>) is almost 
 
471
never subclassed — instead, it is given a resource, which represents the tree 
 
472
of resources available via URLs. That hierarchy is navigated by 
 
473
<code base="API" class="twisted.web.server">Site</code>
 
474
and overriding it dynamically is possible with 
 
475
<code base="API" class="twisted.web.resource.Resource">getChild</code>.</p>
 
476
 
 
477
<p>To integrate this into the Finger application (just because we can), we set
 
478
up a new TCPServer that calls the <code base="API" class="twisted.web.server">Site</code> factory and retrieves resources via a
 
479
new function of <code>FingerService</code> named <code>getResource</code>.
 
480
This function specifically returns a <code base="API" class="twisted.web.resource">Resource</code> object with an overridden <code base="API" class="twisted.web.resource.Resource">getChild</code> method.</p>
 
481
 
 
482
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
483
 2
 
484
 3
 
485
 4
 
486
 5
 
487
 6
 
488
 7
 
489
 8
 
490
 9
 
491
10
 
492
11
 
493
12
 
494
13
 
495
14
 
496
15
 
497
16
 
498
17
 
499
18
 
500
19
 
501
20
 
502
21
 
503
22
 
504
23
 
505
24
 
506
25
 
507
26
 
508
27
 
509
28
 
510
29
 
511
30
 
512
31
 
513
32
 
514
33
 
515
34
 
516
35
 
517
36
 
518
37
 
519
38
 
520
39
 
521
40
 
522
41
 
523
42
 
524
43
 
525
44
 
526
45
 
527
46
 
528
47
 
529
48
 
530
49
 
531
50
 
532
51
 
533
52
 
534
53
 
535
54
 
536
55
 
537
56
 
538
57
 
539
58
 
540
59
 
541
60
 
542
61
 
543
62
 
544
63
 
545
64
 
546
65
 
547
66
 
548
67
 
549
68
 
550
69
 
551
70
 
552
71
 
553
72
 
554
73
 
555
74
 
556
75
 
557
76
 
558
</p><span class="py-src-comment"># Read from file, announce on the web!</span>
 
559
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
 
560
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
 
561
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
562
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">resource</span>, <span class="py-src-variable">server</span>, <span class="py-src-variable">static</span>
 
563
<span class="py-src-keyword">import</span> <span class="py-src-variable">cgi</span>
 
564
 
 
565
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
566
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
567
        <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
 
568
 
 
569
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
570
            <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
571
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
572
 
 
573
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
574
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">message</span> + <span class="py-src-string">'\r\n'</span>)
 
575
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
 
576
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
577
 
 
578
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerResource</span>(<span class="py-src-parameter">resource</span>.<span class="py-src-parameter">Resource</span>):
 
579
 
 
580
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">users</span>):
 
581
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = <span class="py-src-variable">users</span>
 
582
        <span class="py-src-variable">resource</span>.<span class="py-src-variable">Resource</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>)
 
583
 
 
584
    <span class="py-src-comment"># we treat the path as the username</span>
 
585
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getChild</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">username</span>, <span class="py-src-parameter">request</span>):
 
586
        <span class="py-src-string">&quot;&quot;&quot;
 
587
        'username' is a string.
 
588
        'request' is a 'twisted.web.server.Request'.
 
589
        &quot;&quot;&quot;</span>
 
590
        <span class="py-src-variable">messagevalue</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">username</span>)
 
591
        <span class="py-src-variable">username</span> = <span class="py-src-variable">cgi</span>.<span class="py-src-variable">escape</span>(<span class="py-src-variable">username</span>)
 
592
        <span class="py-src-keyword">if</span> <span class="py-src-variable">messagevalue</span> <span class="py-src-keyword">is</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">None</span>:
 
593
            <span class="py-src-variable">messagevalue</span> = <span class="py-src-variable">cgi</span>.<span class="py-src-variable">escape</span>(<span class="py-src-variable">messagevalue</span>)
 
594
            <span class="py-src-variable">text</span> = <span class="py-src-string">'&lt;h1&gt;%s&lt;/h1&gt;&lt;p&gt;%s&lt;/p&gt;'</span> % (<span class="py-src-variable">username</span>,<span class="py-src-variable">messagevalue</span>)
 
595
        <span class="py-src-keyword">else</span>:
 
596
            <span class="py-src-variable">text</span> = <span class="py-src-string">'&lt;h1&gt;%s&lt;/h1&gt;&lt;p&gt;No such user&lt;/p&gt;'</span> % <span class="py-src-variable">username</span>
 
597
        <span class="py-src-keyword">return</span> <span class="py-src-variable">static</span>.<span class="py-src-variable">Data</span>(<span class="py-src-variable">text</span>, <span class="py-src-string">'text/html'</span>)
 
598
 
 
599
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerService</span>(<span class="py-src-parameter">service</span>.<span class="py-src-parameter">Service</span>):
 
600
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">filename</span>):
 
601
        <span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span> = <span class="py-src-variable">filename</span>
 
602
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = {}
 
603
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>()
 
604
 
 
605
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_read</span>(<span class="py-src-parameter">self</span>):
 
606
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">clear</span>()
 
607
        <span class="py-src-keyword">for</span> <span class="py-src-variable">line</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">file</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span>):
 
608
            <span class="py-src-variable">user</span>, <span class="py-src-variable">status</span> = <span class="py-src-variable">line</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">':'</span>, <span class="py-src-number">1</span>)
 
609
            <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">strip</span>()
 
610
            <span class="py-src-variable">status</span> = <span class="py-src-variable">status</span>.<span class="py-src-variable">strip</span>()
 
611
            <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
 
612
        <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span> = <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">30</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>)
 
613
 
 
614
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
615
        <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">&quot;No such user&quot;</span>))
 
616
 
 
617
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getFingerFactory</span>(<span class="py-src-parameter">self</span>):
 
618
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ServerFactory</span>()
 
619
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
 
620
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
621
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
622
 
 
623
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getResource</span>(<span class="py-src-parameter">self</span>):
 
624
        <span class="py-src-variable">r</span> = <span class="py-src-variable">FingerResource</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>)
 
625
        <span class="py-src-keyword">return</span> <span class="py-src-variable">r</span>
 
626
 
 
627
<span class="py-src-variable">application</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">'finger'</span>, <span class="py-src-variable">uid</span>=<span class="py-src-number">1</span>, <span class="py-src-variable">gid</span>=<span class="py-src-number">1</span>)
 
628
<span class="py-src-variable">f</span> = <span class="py-src-variable">FingerService</span>(<span class="py-src-string">'/etc/users'</span>)
 
629
<span class="py-src-variable">serviceCollection</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>)
 
630
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">79</span>, <span class="py-src-variable">f</span>.<span class="py-src-variable">getFingerFactory</span>()
 
631
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
632
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">server</span>.<span class="py-src-variable">Site</span>(<span class="py-src-variable">f</span>.<span class="py-src-variable">getResource</span>())
 
633
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
634
</pre><div class="caption">Source listing - <a href="listings/finger/finger15.tac"><span class="filename">listings/finger/finger15.tac</span></a></div></div>
 
635
 
 
636
 
 
637
<h2>Announce on IRC, Too<a name="auto5"/></h2>
 
638
 
 
639
<p>This is the first time there is client code. IRC clients often
 
640
act a lot like servers: responding to events from the network.
 
641
The reconnecting client factory will make sure that severed links
 
642
will get re-established, with intelligent tweaked exponential
 
643
back-off algorithms. The IRC client itself is simple: the only
 
644
real hack is getting the nickname from the factory in connectionMade.</p>
 
645
 
 
646
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
647
 2
 
648
 3
 
649
 4
 
650
 5
 
651
 6
 
652
 7
 
653
 8
 
654
 9
 
655
10
 
656
11
 
657
12
 
658
13
 
659
14
 
660
15
 
661
16
 
662
17
 
663
18
 
664
19
 
665
20
 
666
21
 
667
22
 
668
23
 
669
24
 
670
25
 
671
26
 
672
27
 
673
28
 
674
29
 
675
30
 
676
31
 
677
32
 
678
33
 
679
34
 
680
35
 
681
36
 
682
37
 
683
38
 
684
39
 
685
40
 
686
41
 
687
42
 
688
43
 
689
44
 
690
45
 
691
46
 
692
47
 
693
48
 
694
49
 
695
50
 
696
51
 
697
52
 
698
53
 
699
54
 
700
55
 
701
56
 
702
57
 
703
58
 
704
59
 
705
60
 
706
61
 
707
62
 
708
63
 
709
64
 
710
65
 
711
66
 
712
67
 
713
68
 
714
69
 
715
70
 
716
71
 
717
72
 
718
73
 
719
74
 
720
75
 
721
76
 
722
77
 
723
78
 
724
79
 
725
80
 
726
81
 
727
82
 
728
83
 
729
84
 
730
85
 
731
86
 
732
87
 
733
88
 
734
89
 
735
90
 
736
91
 
737
</p><span class="py-src-comment"># Read from file, announce on the web, irc</span>
 
738
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
 
739
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
 
740
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">words</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span>
 
741
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
742
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">resource</span>, <span class="py-src-variable">server</span>, <span class="py-src-variable">static</span>
 
743
 
 
744
<span class="py-src-keyword">import</span> <span class="py-src-variable">cgi</span>
 
745
 
 
746
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
747
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
748
        <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
 
749
 
 
750
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
751
            <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
752
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
753
 
 
754
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
755
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">message</span> + <span class="py-src-string">'\r\n'</span>)
 
756
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
 
757
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
758
 
 
759
 
 
760
<span class="py-src-keyword">class</span> <span class="py-src-identifier">IRCReplyBot</span>(<span class="py-src-parameter">irc</span>.<span class="py-src-parameter">IRCClient</span>):
 
761
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
 
762
        <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">nickname</span>
 
763
        <span class="py-src-variable">irc</span>.<span class="py-src-variable">IRCClient</span>.<span class="py-src-variable">connectionMade</span>(<span class="py-src-variable">self</span>)
 
764
 
 
765
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">privmsg</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">channel</span>, <span class="py-src-parameter">msg</span>):
 
766
        <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'!'</span>)[<span class="py-src-number">0</span>]
 
767
        <span class="py-src-keyword">if</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>.<span class="py-src-variable">lower</span>() == <span class="py-src-variable">channel</span>.<span class="py-src-variable">lower</span>():
 
768
            <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">msg</span>)
 
769
 
 
770
            <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
771
                <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
772
            <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
773
 
 
774
            <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
775
                <span class="py-src-variable">irc</span>.<span class="py-src-variable">IRCClient</span>.<span class="py-src-variable">msg</span>(<span class="py-src-variable">self</span>, <span class="py-src-variable">user</span>, <span class="py-src-variable">msg</span>+<span class="py-src-string">': '</span>+<span class="py-src-variable">message</span>)
 
776
            <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
777
 
 
778
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerService</span>(<span class="py-src-parameter">service</span>.<span class="py-src-parameter">Service</span>):
 
779
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">filename</span>):
 
780
        <span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span> = <span class="py-src-variable">filename</span>
 
781
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = {}
 
782
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>()
 
783
 
 
784
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_read</span>(<span class="py-src-parameter">self</span>):
 
785
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">clear</span>()
 
786
        <span class="py-src-keyword">for</span> <span class="py-src-variable">line</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">file</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span>):
 
787
            <span class="py-src-variable">user</span>, <span class="py-src-variable">status</span> = <span class="py-src-variable">line</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">':'</span>, <span class="py-src-number">1</span>)
 
788
            <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">strip</span>()
 
789
            <span class="py-src-variable">status</span> = <span class="py-src-variable">status</span>.<span class="py-src-variable">strip</span>()
 
790
            <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
 
791
        <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span> = <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">30</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>)
 
792
 
 
793
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
794
        <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">&quot;No such user&quot;</span>))
 
795
 
 
796
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getFingerFactory</span>(<span class="py-src-parameter">self</span>):
 
797
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ServerFactory</span>()
 
798
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
 
799
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
800
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
801
 
 
802
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getResource</span>(<span class="py-src-parameter">self</span>):
 
803
        <span class="py-src-variable">r</span> = <span class="py-src-variable">resource</span>.<span class="py-src-variable">Resource</span>()
 
804
        <span class="py-src-variable">r</span>.<span class="py-src-variable">getChild</span> = (<span class="py-src-keyword">lambda</span> <span class="py-src-variable">path</span>, <span class="py-src-variable">request</span>:
 
805
                      <span class="py-src-variable">static</span>.<span class="py-src-variable">Data</span>(<span class="py-src-string">'&lt;h1&gt;%s&lt;/h1&gt;&lt;p&gt;%s&lt;/p&gt;'</span> %
 
806
                      <span class="py-src-variable">tuple</span>(<span class="py-src-variable">map</span>(<span class="py-src-variable">cgi</span>.<span class="py-src-variable">escape</span>,
 
807
                      [<span class="py-src-variable">path</span>,<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">path</span>,
 
808
                      <span class="py-src-string">&quot;No such user &lt;p/&gt; usage: site/user&quot;</span>)])),
 
809
                      <span class="py-src-string">'text/html'</span>))
 
810
        <span class="py-src-keyword">return</span> <span class="py-src-variable">r</span>
 
811
 
 
812
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getIRCBot</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">nickname</span>):
 
813
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ReconnectingClientFactory</span>()
 
814
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">IRCReplyBot</span>
 
815
        <span class="py-src-variable">f</span>.<span class="py-src-variable">nickname</span> = <span class="py-src-variable">nickname</span>
 
816
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
817
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
818
 
 
819
<span class="py-src-variable">application</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">'finger'</span>, <span class="py-src-variable">uid</span>=<span class="py-src-number">1</span>, <span class="py-src-variable">gid</span>=<span class="py-src-number">1</span>)
 
820
<span class="py-src-variable">f</span> = <span class="py-src-variable">FingerService</span>(<span class="py-src-string">'/etc/users'</span>)
 
821
<span class="py-src-variable">serviceCollection</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>)
 
822
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">79</span>, <span class="py-src-variable">f</span>.<span class="py-src-variable">getFingerFactory</span>()
 
823
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
824
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">server</span>.<span class="py-src-variable">Site</span>(<span class="py-src-variable">f</span>.<span class="py-src-variable">getResource</span>())
 
825
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
826
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPClient</span>(<span class="py-src-string">'irc.freenode.org'</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">f</span>.<span class="py-src-variable">getIRCBot</span>(<span class="py-src-string">'fingerbot'</span>)
 
827
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
828
</pre><div class="caption">Source listing - <a href="listings/finger/finger16.tac"><span class="filename">listings/finger/finger16.tac</span></a></div></div>
 
829
 
 
830
<p><code>FingerService</code> now has another new function, 
 
831
<code>getIRCbot</code>, which returns the 
 
832
<code>ReconnectingClientFactory</code>.  This factory in turn will instantiate 
 
833
the <code>IRCReplyBot</code> protocol.  The IRCBot is configured in the last 
 
834
line to connect to <code>irc.freenode.org</code> with a nickname of 
 
835
<code>fingerbot</code>.</p>
 
836
 
 
837
<p>By overriding <code>irc.IRCClient.connectionMade</code>, 
 
838
<code>IRCReplyBot</code> can access the <code>nickname</code> attribute of the 
 
839
factory that instantiated it.</p>
 
840
 
 
841
<h2>Add XML-RPC Support<a name="auto6"/></h2>
 
842
 
 
843
<p>In Twisted, XML-RPC support is handled just as though it was
 
844
another resource. That resource will still support GET calls normally
 
845
through render(), but that is usually left unimplemented. Note
 
846
that it is possible to return deferreds from XML-RPC methods.
 
847
The client, of course, will not get the answer until the deferred
 
848
is triggered.</p>
 
849
 
 
850
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
851
 2
 
852
 3
 
853
 4
 
854
 5
 
855
 6
 
856
 7
 
857
 8
 
858
 9
 
859
10
 
860
11
 
861
12
 
862
13
 
863
14
 
864
15
 
865
16
 
866
17
 
867
18
 
868
19
 
869
20
 
870
21
 
871
22
 
872
23
 
873
24
 
874
25
 
875
26
 
876
27
 
877
28
 
878
29
 
879
30
 
880
31
 
881
32
 
882
33
 
883
34
 
884
35
 
885
36
 
886
37
 
887
38
 
888
39
 
889
40
 
890
41
 
891
42
 
892
43
 
893
44
 
894
45
 
895
46
 
896
47
 
897
48
 
898
49
 
899
50
 
900
51
 
901
52
 
902
53
 
903
54
 
904
55
 
905
56
 
906
57
 
907
58
 
908
59
 
909
60
 
910
61
 
911
62
 
912
63
 
913
64
 
914
65
 
915
66
 
916
67
 
917
68
 
918
69
 
919
70
 
920
71
 
921
72
 
922
73
 
923
74
 
924
75
 
925
76
 
926
77
 
927
78
 
928
79
 
929
80
 
930
81
 
931
82
 
932
83
 
933
84
 
934
85
 
935
86
 
936
87
 
937
88
 
938
89
 
939
90
 
940
91
 
941
</p><span class="py-src-comment"># Read from file, announce on the web, irc, xml-rpc</span>
 
942
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
 
943
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
 
944
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">words</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span>
 
945
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
946
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">resource</span>, <span class="py-src-variable">server</span>, <span class="py-src-variable">static</span>, <span class="py-src-variable">xmlrpc</span>
 
947
<span class="py-src-keyword">import</span> <span class="py-src-variable">cgi</span>
 
948
 
 
949
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
950
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
951
        <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
 
952
 
 
953
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
954
            <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
955
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
956
 
 
957
        <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
958
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">message</span> + <span class="py-src-string">'\r\n'</span>)
 
959
            <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
 
960
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
961
 
 
962
<span class="py-src-keyword">class</span> <span class="py-src-identifier">IRCReplyBot</span>(<span class="py-src-parameter">irc</span>.<span class="py-src-parameter">IRCClient</span>):
 
963
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
 
964
        <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">nickname</span>
 
965
        <span class="py-src-variable">irc</span>.<span class="py-src-variable">IRCClient</span>.<span class="py-src-variable">connectionMade</span>(<span class="py-src-variable">self</span>)
 
966
 
 
967
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">privmsg</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">channel</span>, <span class="py-src-parameter">msg</span>):
 
968
        <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'!'</span>)[<span class="py-src-number">0</span>]
 
969
        <span class="py-src-keyword">if</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>.<span class="py-src-variable">lower</span>() == <span class="py-src-variable">channel</span>.<span class="py-src-variable">lower</span>():
 
970
            <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">msg</span>)
 
971
 
 
972
            <span class="py-src-keyword">def</span> <span class="py-src-identifier">onError</span>(<span class="py-src-parameter">err</span>):
 
973
                <span class="py-src-keyword">return</span> <span class="py-src-string">'Internal error in server'</span>
 
974
            <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">onError</span>)
 
975
 
 
976
            <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeResponse</span>(<span class="py-src-parameter">message</span>):
 
977
                <span class="py-src-variable">irc</span>.<span class="py-src-variable">IRCClient</span>.<span class="py-src-variable">msg</span>(<span class="py-src-variable">self</span>, <span class="py-src-variable">user</span>, <span class="py-src-variable">msg</span>+<span class="py-src-string">': '</span>+<span class="py-src-variable">message</span>)
 
978
            <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeResponse</span>)
 
979
 
 
980
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerService</span>(<span class="py-src-parameter">service</span>.<span class="py-src-parameter">Service</span>):
 
981
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">filename</span>):
 
982
        <span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span> = <span class="py-src-variable">filename</span>
 
983
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = {}
 
984
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>()
 
985
 
 
986
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_read</span>(<span class="py-src-parameter">self</span>):
 
987
        <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">clear</span>()
 
988
        <span class="py-src-keyword">for</span> <span class="py-src-variable">line</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">file</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span>):
 
989
            <span class="py-src-variable">user</span>, <span class="py-src-variable">status</span> = <span class="py-src-variable">line</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">':'</span>, <span class="py-src-number">1</span>)
 
990
            <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">strip</span>()
 
991
            <span class="py-src-variable">status</span> = <span class="py-src-variable">status</span>.<span class="py-src-variable">strip</span>()
 
992
            <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
 
993
        <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span> = <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">30</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>)
 
994
 
 
995
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
996
        <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">&quot;No such user&quot;</span>))
 
997
 
 
998
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getFingerFactory</span>(<span class="py-src-parameter">self</span>):
 
999
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ServerFactory</span>()
 
1000
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
 
1001
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
1002
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
1003
 
 
1004
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getResource</span>(<span class="py-src-parameter">self</span>):
 
1005
        <span class="py-src-variable">r</span> = <span class="py-src-variable">resource</span>.<span class="py-src-variable">Resource</span>()
 
1006
        <span class="py-src-variable">r</span>.<span class="py-src-variable">getChild</span> = (<span class="py-src-keyword">lambda</span> <span class="py-src-variable">path</span>, <span class="py-src-variable">request</span>:
 
1007
                      <span class="py-src-variable">static</span>.<span class="py-src-variable">Data</span>(<span class="py-src-string">'&lt;h1&gt;%s&lt;/h1&gt;&lt;p&gt;%s&lt;/p&gt;'</span> %
 
1008
                      <span class="py-src-variable">tuple</span>(<span class="py-src-variable">map</span>(<span class="py-src-variable">cgi</span>.<span class="py-src-variable">escape</span>,
 
1009
                      [<span class="py-src-variable">path</span>,<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">path</span>, <span class="py-src-string">&quot;No such user&quot;</span>)])),
 
1010
                      <span class="py-src-string">'text/html'</span>))
 
1011
        <span class="py-src-variable">x</span> = <span class="py-src-variable">xmlrpc</span>.<span class="py-src-variable">XMLRPC</span>()
 
1012
        <span class="py-src-variable">x</span>.<span class="py-src-variable">xmlrpc_getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
1013
        <span class="py-src-variable">r</span>.<span class="py-src-variable">putChild</span>(<span class="py-src-string">'RPC2'</span>, <span class="py-src-variable">x</span>)
 
1014
        <span class="py-src-keyword">return</span> <span class="py-src-variable">r</span>
 
1015
 
 
1016
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">getIRCBot</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">nickname</span>):
 
1017
        <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">ReconnectingClientFactory</span>()
 
1018
        <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">IRCReplyBot</span>
 
1019
        <span class="py-src-variable">f</span>.<span class="py-src-variable">nickname</span> = <span class="py-src-variable">nickname</span>
 
1020
        <span class="py-src-variable">f</span>.<span class="py-src-variable">getUser</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">getUser</span>
 
1021
        <span class="py-src-keyword">return</span> <span class="py-src-variable">f</span>
 
1022
 
 
1023
<span class="py-src-variable">application</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">'finger'</span>, <span class="py-src-variable">uid</span>=<span class="py-src-number">1</span>, <span class="py-src-variable">gid</span>=<span class="py-src-number">1</span>)
 
1024
<span class="py-src-variable">f</span> = <span class="py-src-variable">FingerService</span>(<span class="py-src-string">'/etc/users'</span>)
 
1025
<span class="py-src-variable">serviceCollection</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">IServiceCollection</span>(<span class="py-src-variable">application</span>)
 
1026
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">79</span>, <span class="py-src-variable">f</span>.<span class="py-src-variable">getFingerFactory</span>()
 
1027
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
1028
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">server</span>.<span class="py-src-variable">Site</span>(<span class="py-src-variable">f</span>.<span class="py-src-variable">getResource</span>())
 
1029
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
1030
<span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPClient</span>(<span class="py-src-string">'irc.freenode.org'</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">f</span>.<span class="py-src-variable">getIRCBot</span>(<span class="py-src-string">'fingerbot'</span>)
 
1031
                   ).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">serviceCollection</span>)
 
1032
</pre><div class="caption">Source listing - <a href="listings/finger/finger17.tac"><span class="filename">listings/finger/finger17.tac</span></a></div></div>
 
1033
 
 
1034
<p>Instead of a web browser, we can test the XMLRPC finger using a simple 
 
1035
client based on Python's built-in <code>xmlrpclib</code>, which will access 
 
1036
the resource we've made available at <code>localhost/RPC2</code>.</p>
 
1037
 
 
1038
<div class="py-listing"><pre><p class="py-linenumber">1
 
1039
2
 
1040
3
 
1041
4
 
1042
5
 
1043
</p><span class="py-src-comment"># testing xmlrpc finger</span>
 
1044
 
 
1045
<span class="py-src-keyword">import</span> <span class="py-src-variable">xmlrpclib</span>
 
1046
<span class="py-src-variable">server</span> = <span class="py-src-variable">xmlrpclib</span>.<span class="py-src-variable">Server</span>(<span class="py-src-string">'http://127.0.0.1:8000/RPC2'</span>)
 
1047
<span class="py-src-keyword">print</span> <span class="py-src-variable">server</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-string">'moshez'</span>)
 
1048
</pre><div class="caption">Source listing - <a href="listings/finger/fingerXRclient.py"><span class="filename">listings/finger/fingerXRclient.py</span></a></div></div>
 
1049
 
 
1050
</div>
 
1051
 
 
1052
    <p><a href="../index.html">Index</a></p>
 
1053
    <span class="version">Version: 10.0.0</span>
 
1054
  </body>
 
1055
</html>
 
 
b'\\ No newline at end of file'