0
# Network Protocols
1
2
Implementations of various network protocols including FTP, IRC, XMPP, AMP (Asynchronous Messaging Protocol), and utilities for building custom protocols. Twisted provides a rich ecosystem of protocol implementations.
3
4
## Capabilities
5
6
### Basic Protocol Building Blocks
7
8
Fundamental protocol classes for building line-oriented and length-prefixed protocols.
9
10
```python { .api }
11
class basic.LineReceiver:
12
"""
13
Protocol that receives data line by line.
14
15
Attributes:
16
- delimiter: Line delimiter (default: b'\\r\\n')
17
- MAX_LENGTH: Maximum line length
18
- clearLineBuffer: Whether to clear buffer on line length exceeded
19
"""
20
delimiter = b'\r\n'
21
MAX_LENGTH = 16384
22
clearLineBuffer = False
23
24
def lineReceived(self, line):
25
"""
26
Called when a complete line is received.
27
28
Args:
29
line (bytes): Received line (without delimiter)
30
"""
31
32
def lineLengthExceeded(self, line):
33
"""
34
Called when line exceeds MAX_LENGTH.
35
36
Args:
37
line (bytes): Partial line data
38
"""
39
40
def sendLine(self, line):
41
"""
42
Send a line with delimiter.
43
44
Args:
45
line (bytes): Line to send
46
"""
47
48
def setLineMode(self, extra=b''):
49
"""
50
Switch to line-based receiving mode.
51
52
Args:
53
extra (bytes): Extra data to process
54
"""
55
56
def setRawMode(self):
57
"""Switch to raw data receiving mode."""
58
59
class basic.IntNStringReceiver:
60
"""
61
Protocol that receives length-prefixed strings.
62
63
Attributes:
64
- structFormat: Struct format for length field
65
- prefixLength: Length of length prefix
66
- MAX_LENGTH: Maximum string length
67
"""
68
structFormat = '!I' # 32-bit big-endian unsigned int
69
prefixLength = 4
70
MAX_LENGTH = 99999999
71
72
def stringReceived(self, string):
73
"""
74
Called when a complete string is received.
75
76
Args:
77
string (bytes): Received string
78
"""
79
80
def lengthLimitExceeded(self, length):
81
"""
82
Called when string length exceeds MAX_LENGTH.
83
84
Args:
85
length (int): Attempted string length
86
"""
87
88
def sendString(self, string):
89
"""
90
Send a length-prefixed string.
91
92
Args:
93
string (bytes): String to send
94
"""
95
96
class basic.Int32StringReceiver(basic.IntNStringReceiver):
97
"""32-bit length-prefixed string receiver."""
98
structFormat = '!I'
99
prefixLength = 4
100
101
class basic.Int16StringReceiver(basic.IntNStringReceiver):
102
"""16-bit length-prefixed string receiver."""
103
structFormat = '!H'
104
prefixLength = 2
105
106
class basic.Int8StringReceiver(basic.IntNStringReceiver):
107
"""8-bit length-prefixed string receiver."""
108
structFormat = '!B'
109
prefixLength = 1
110
111
class basic.NetstringReceiver:
112
"""
113
Protocol that receives netstring-encoded data.
114
115
Netstring format: <length>:<data>,
116
"""
117
MAX_LENGTH = 99999999
118
119
def stringReceived(self, string):
120
"""
121
Called when a complete netstring is received.
122
123
Args:
124
string (bytes): Received string data
125
"""
126
127
def lengthLimitExceeded(self, length):
128
"""
129
Called when netstring length exceeds MAX_LENGTH.
130
131
Args:
132
length (int): Attempted string length
133
"""
134
135
def sendString(self, string):
136
"""
137
Send a netstring.
138
139
Args:
140
string (bytes): String to send
141
"""
142
143
class basic.StatefulStringProtocol:
144
"""
145
Protocol with multiple states for complex parsing.
146
147
States are methods named 'proto_<STATE>' that return next state.
148
"""
149
def proto_init(self):
150
"""
151
Initial protocol state.
152
153
Returns:
154
str: Next state name
155
"""
156
```
157
158
**Basic Protocol Usage Example**:
159
160
```python
161
from twisted.protocols import basic
162
from twisted.internet import protocol, reactor, endpoints
163
164
class ChatProtocol(basic.LineReceiver):
165
delimiter = b'\n'
166
167
def connectionMade(self):
168
self.sendLine(b"Welcome to chat server!")
169
self.factory.clients.append(self)
170
171
def connectionLost(self, reason):
172
if self in self.factory.clients:
173
self.factory.clients.remove(self)
174
175
def lineReceived(self, line):
176
message = f"User says: {line.decode()}"
177
# Broadcast to all clients
178
for client in self.factory.clients:
179
if client != self:
180
client.sendLine(message.encode())
181
182
class ChatFactory(protocol.ServerFactory):
183
def __init__(self):
184
self.clients = []
185
186
def buildProtocol(self, addr):
187
protocol = ChatProtocol()
188
protocol.factory = self
189
return protocol
190
191
# Start server
192
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8080)
193
endpoint.listen(ChatFactory())
194
reactor.run()
195
```
196
197
### Asynchronous Messaging Protocol (AMP)
198
199
High-level RPC protocol with structured commands and responses.
200
201
```python { .api }
202
class amp.AMP:
203
"""
204
Asynchronous Messaging Protocol implementation.
205
206
Provides structured command/response messaging over TCP.
207
"""
208
def __init__(self, boxReceiver=None, locator=None):
209
"""
210
Args:
211
boxReceiver: Custom box receiver
212
locator: Command locator
213
"""
214
215
def callRemote(self, command, **kwargs):
216
"""
217
Call remote command.
218
219
Args:
220
command: AMP command class
221
**kwargs: Command arguments
222
223
Returns:
224
Deferred: Response from remote
225
"""
226
227
def callRemoteString(self, commandName, **kwargs):
228
"""
229
Call remote command by name.
230
231
Args:
232
commandName (str): Command name
233
**kwargs: Command arguments
234
235
Returns:
236
Deferred: Response from remote
237
"""
238
239
class amp.Command:
240
"""
241
Base class for AMP commands.
242
243
Attributes:
244
- commandName: Command name (bytes)
245
- arguments: List of command arguments
246
- response: List of response arguments
247
- errors: Dict of error mappings
248
- requiresAnswer: Whether command expects response
249
"""
250
commandName = None
251
arguments = []
252
response = []
253
errors = {}
254
requiresAnswer = True
255
256
@classmethod
257
def makeArguments(cls, objects, proto):
258
"""
259
Serialize command arguments.
260
261
Args:
262
objects (dict): Argument values
263
proto: Protocol instance
264
265
Returns:
266
dict: Serialized arguments
267
"""
268
269
@classmethod
270
def parseResponse(cls, strings, proto):
271
"""
272
Parse command response.
273
274
Args:
275
strings (dict): Response data
276
proto: Protocol instance
277
278
Returns:
279
dict: Parsed response
280
"""
281
282
# AMP argument types
283
class amp.Argument:
284
"""Base class for AMP argument types."""
285
286
def toString(self, inObject):
287
"""
288
Serialize argument to string.
289
290
Args:
291
inObject: Python object
292
293
Returns:
294
bytes: Serialized form
295
"""
296
297
def fromString(self, inString):
298
"""
299
Deserialize argument from string.
300
301
Args:
302
inString (bytes): Serialized form
303
304
Returns:
305
Python object
306
"""
307
308
class amp.Integer(amp.Argument):
309
"""Integer argument type."""
310
311
class amp.String(amp.Argument):
312
"""String argument type."""
313
314
class amp.Unicode(amp.Argument):
315
"""Unicode string argument type."""
316
317
class amp.Boolean(amp.Argument):
318
"""Boolean argument type."""
319
320
class amp.Float(amp.Argument):
321
"""Float argument type."""
322
323
class amp.Decimal(amp.Argument):
324
"""Decimal argument type."""
325
326
class amp.DateTime(amp.Argument):
327
"""DateTime argument type."""
328
329
class amp.ListOf(amp.Argument):
330
"""List argument type."""
331
def __init__(self, elementType):
332
"""
333
Args:
334
elementType: Type of list elements
335
"""
336
```
337
338
**AMP Usage Example**:
339
340
```python
341
from twisted.protocols import amp
342
from twisted.internet import reactor, defer
343
344
# Define commands
345
class Sum(amp.Command):
346
commandName = b'sum'
347
arguments = [
348
(b'a', amp.Integer()),
349
(b'b', amp.Integer()),
350
]
351
response = [
352
(b'result', amp.Integer()),
353
]
354
355
class Greeting(amp.Command):
356
commandName = b'greeting'
357
arguments = [
358
(b'name', amp.Unicode()),
359
]
360
response = [
361
(b'message', amp.Unicode()),
362
]
363
364
# Server implementation
365
class MathServer(amp.AMP):
366
def sum(self, a, b):
367
return {'result': a + b}
368
369
def greeting(self, name):
370
return {'message': f'Hello, {name}!'}
371
372
# Client usage
373
class MathClient(amp.AMP):
374
def connectionMade(self):
375
amp.AMP.connectionMade(self)
376
377
# Call remote commands
378
d1 = self.callRemote(Sum, a=5, b=3)
379
d1.addCallback(lambda result: print(f"Sum: {result['result']}"))
380
381
d2 = self.callRemote(Greeting, name="Alice")
382
d2.addCallback(lambda result: print(f"Greeting: {result['message']}"))
383
```
384
385
### FTP Protocol
386
387
File Transfer Protocol client and server implementations.
388
389
```python { .api }
390
class ftp.FTP:
391
"""
392
FTP server protocol implementation.
393
394
Attributes:
395
- shell: Avatar object providing file system interface
396
- workingDirectory: Current working directory
397
"""
398
shell = None
399
workingDirectory = None
400
401
def ftp_USER(self, params):
402
"""Handle USER command."""
403
404
def ftp_PASS(self, params):
405
"""Handle PASS command."""
406
407
def ftp_LIST(self, params):
408
"""Handle LIST command."""
409
410
def ftp_RETR(self, params):
411
"""Handle RETR command."""
412
413
def ftp_STOR(self, params):
414
"""Handle STOR command."""
415
416
class ftp.FTPFactory:
417
"""
418
FTP server factory.
419
"""
420
def __init__(self):
421
self.timeOut = 600 # Session timeout
422
self.welcomeMessage = "Welcome to FTP server"
423
424
class ftp.FTPClient:
425
"""
426
FTP client protocol implementation.
427
"""
428
def __init__(self, username='anonymous', password='twisted@twistedmatrix.com', passive=1):
429
"""
430
Args:
431
username (str): FTP username
432
password (str): FTP password
433
passive (bool): Use passive mode
434
"""
435
436
def retrieveFile(self, filename, callback, offset=0):
437
"""
438
Retrieve file from server.
439
440
Args:
441
filename (str): Remote filename
442
callback: Function to receive file data
443
offset (int): Start offset
444
445
Returns:
446
Deferred: Completion indicator
447
"""
448
449
def storeFile(self, filename, file, offset=0):
450
"""
451
Store file on server.
452
453
Args:
454
filename (str): Remote filename
455
file: File-like object to upload
456
offset (int): Start offset
457
458
Returns:
459
Deferred: Completion indicator
460
"""
461
462
def list(self, path, callback):
463
"""
464
List directory contents.
465
466
Args:
467
path (str): Directory path
468
callback: Function to receive listing data
469
470
Returns:
471
Deferred: Completion indicator
472
"""
473
474
def makeDirectory(self, path):
475
"""
476
Create directory.
477
478
Args:
479
path (str): Directory path
480
481
Returns:
482
Deferred: Completion indicator
483
"""
484
485
def removeFile(self, path):
486
"""
487
Remove file.
488
489
Args:
490
path (str): File path
491
492
Returns:
493
Deferred: Completion indicator
494
"""
495
496
class ftp.FTPClientBasic:
497
"""
498
Basic FTP client with simple interface.
499
"""
500
def __init__(self, username='anonymous', password='twisted@twistedmatrix.com'):
501
"""
502
Args:
503
username (str): FTP username
504
password (str): FTP password
505
"""
506
507
def connectTo(self, host, port=21):
508
"""
509
Connect to FTP server.
510
511
Args:
512
host (str): Server hostname
513
port (int): Server port
514
515
Returns:
516
Deferred[FTPClient]: Connected client
517
"""
518
```
519
520
### Protocol Policies
521
522
Wrappers and policies for controlling protocol behavior.
523
524
```python { .api }
525
class policies.ProtocolWrapper:
526
"""
527
Base class for protocol wrappers.
528
"""
529
def __init__(self, protocol, factory):
530
"""
531
Args:
532
protocol: Wrapped protocol
533
factory: Wrapper factory
534
"""
535
536
class policies.WrappingFactory:
537
"""
538
Base factory for protocol wrappers.
539
"""
540
def __init__(self, wrappedFactory):
541
"""
542
Args:
543
wrappedFactory: Factory being wrapped
544
"""
545
546
def buildProtocol(self, addr):
547
"""
548
Build wrapped protocol.
549
550
Args:
551
addr: Connection address
552
553
Returns:
554
ProtocolWrapper: Wrapped protocol
555
"""
556
557
class policies.ThrottlingFactory:
558
"""
559
Factory that limits connection rate.
560
"""
561
def __init__(self, wrappedFactory, maxConnectionsPerIP=10):
562
"""
563
Args:
564
wrappedFactory: Factory being wrapped
565
maxConnectionsPerIP (int): Max connections per IP
566
"""
567
568
class policies.TimeoutFactory:
569
"""
570
Factory that enforces connection timeouts.
571
"""
572
def __init__(self, wrappedFactory, timeoutPeriod=30*60):
573
"""
574
Args:
575
wrappedFactory: Factory being wrapped
576
timeoutPeriod (int): Timeout in seconds
577
"""
578
579
class policies.TrafficLoggingFactory:
580
"""
581
Factory that logs all network traffic.
582
"""
583
def __init__(self, wrappedFactory, logfile):
584
"""
585
Args:
586
wrappedFactory: Factory being wrapped
587
logfile: File to log traffic to
588
"""
589
```
590
591
### Loopback Testing
592
593
Utilities for testing protocols without network connections.
594
595
```python { .api }
596
def loopback.loopback(server, client, pumpPolicy=None):
597
"""
598
Connect two protocols in loopback for testing.
599
600
Args:
601
server: Server protocol instance
602
client: Client protocol instance
603
pumpPolicy: Data pumping policy
604
605
Returns:
606
Deferred: Fires when loopback complete
607
"""
608
609
def loopback.loopbackTCP(server, client, port=0):
610
"""
611
Connect protocols via TCP loopback.
612
613
Args:
614
server: Server protocol instance
615
client: Client protocol instance
616
port (int): Port number (0 for random)
617
618
Returns:
619
Deferred: Fires when connection established
620
"""
621
622
def loopback.loopbackUNIX(server, client):
623
"""
624
Connect protocols via Unix socket loopback.
625
626
Args:
627
server: Server protocol instance
628
client: Client protocol instance
629
630
Returns:
631
Deferred: Fires when connection established
632
"""
633
```
634
635
**Loopback Testing Example**:
636
637
```python
638
from twisted.protocols import basic, loopback
639
from twisted.test import proto_helpers
640
from twisted.trial import unittest
641
642
class EchoProtocol(basic.LineReceiver):
643
def lineReceived(self, line):
644
self.sendLine(line)
645
646
class TestEcho(unittest.TestCase):
647
def test_echo_loopback(self):
648
server = EchoProtocol()
649
client = EchoProtocol()
650
651
# Set up data collection
652
client_data = []
653
def collect_data(line):
654
client_data.append(line)
655
client.lineReceived = collect_data
656
657
# Run loopback test
658
d = loopback.loopback(server, client)
659
660
# Send test data
661
client.sendLine(b"Hello")
662
client.sendLine(b"World")
663
664
# Verify echo
665
def check_result(_):
666
self.assertEqual(client_data, [b"Hello", b"World"])
667
668
d.addCallback(check_result)
669
return d
670
```
671
672
### Additional Protocol Implementations
673
674
Brief overview of other protocol implementations available in Twisted.
675
676
```python { .api }
677
# IRC Protocol (twisted.words.protocols.irc)
678
class irc.IRCClient:
679
"""IRC client protocol with event handlers."""
680
681
def joined(self, channel):
682
"""Called when joined a channel."""
683
684
def privmsg(self, user, channel, msg):
685
"""Called when receiving private message."""
686
687
# IDENT Protocol (twisted.protocols.ident)
688
class ident.IdentServer:
689
"""Ident server protocol (RFC 1413)."""
690
691
class ident.IdentClient:
692
"""Ident client protocol."""
693
694
# Memcached Protocol (twisted.protocols.memcache)
695
class memcache.MemCacheProtocol:
696
"""Memcached protocol client."""
697
698
def get(self, keys):
699
"""Get values by keys."""
700
701
def set(self, key, value, flags=0, expireTime=0):
702
"""Set key-value pair."""
703
704
# SOCKS Protocol (twisted.protocols.socks)
705
class socks.SOCKSv4:
706
"""SOCKS version 4 proxy protocol."""
707
708
class socks.SOCKSv4Factory:
709
"""SOCKS v4 factory."""
710
```