1
by Jesse Andrews
initial commit |
1 |
# -*- test-case-name: twisted.pair.test.test_rawudp -*-
|
2 |
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
|
|
3 |
# See LICENSE for details.
|
|
4 |
||
5 |
#
|
|
6 |
||
7 |
"""Implementation of raw packet interfaces for UDP"""
|
|
8 |
||
9 |
import struct |
|
10 |
||
11 |
from twisted.internet import protocol |
|
12 |
from twisted.pair import raw |
|
13 |
from zope.interface import implements |
|
14 |
||
15 |
class UDPHeader: |
|
16 |
def __init__(self, data): |
|
17 |
||
18 |
(self.source, self.dest, self.len, self.check) \ |
|
19 |
= struct.unpack("!HHHH", data[:8]) |
|
20 |
||
21 |
class RawUDPProtocol(protocol.AbstractDatagramProtocol): |
|
22 |
implements(raw.IRawDatagramProtocol) |
|
23 |
def __init__(self): |
|
24 |
self.udpProtos = {} |
|
25 |
||
26 |
def addProto(self, num, proto): |
|
27 |
if not isinstance(proto, protocol.DatagramProtocol): |
|
28 |
raise TypeError, 'Added protocol must be an instance of DatagramProtocol' |
|
29 |
if num < 0: |
|
30 |
raise TypeError, 'Added protocol must be positive or zero' |
|
31 |
if num >= 2**16: |
|
32 |
raise TypeError, 'Added protocol must fit in 16 bits' |
|
33 |
if num not in self.udpProtos: |
|
34 |
self.udpProtos[num] = [] |
|
35 |
self.udpProtos[num].append(proto) |
|
36 |
||
37 |
def datagramReceived(self, |
|
38 |
data, |
|
39 |
partial, |
|
40 |
source, |
|
41 |
dest, |
|
42 |
protocol, |
|
43 |
version, |
|
44 |
ihl, |
|
45 |
tos, |
|
46 |
tot_len, |
|
47 |
fragment_id, |
|
48 |
fragment_offset, |
|
49 |
dont_fragment, |
|
50 |
more_fragments, |
|
51 |
ttl): |
|
52 |
header = UDPHeader(data) |
|
53 |
for proto in self.udpProtos.get(header.dest, ()): |
|
54 |
proto.datagramReceived(data[8:], |
|
55 |
(source, header.source)) |