-
Notifications
You must be signed in to change notification settings - Fork 0
/
udp.py
93 lines (66 loc) · 2.69 KB
/
udp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import socket, untwisted
from twisted.internet import udp
from untwisted import promise
# A connected UDP socket is slightly different from a standard one - it can
# only send and receive datagrams to/from a single address, but this does not
# in any way imply a connection. Datagrams may still arrive in any order, and
# the port on the other side may have no one listening,
# http://twistedmatrix.com/documents/current/core/howto/udp.html#auto2
def connect(host, port):
class result(udp.Port):
class __metaclass__(type):
def __call__(ctx):
transport = promise.promise()
@untwisted.call
class protocol:
datagramReceived = promise.sequence()
# Avoid AttributeError: protocol instance has no attribute 'doStop'
def doStop(ctx):
pass
@transport.then
@promise.resume
def makeConnection(transport):
nstHost = host
try:
try:
transport.connect(host, port)
except ValueError:
# Avoid ImportError: cannot import name dns
from untwisted import dns
nstHost = (yield dns.lookup(host)).answer[0].address
transport.connect(nstHost, port)
# tcp.Connector calls socket.getservbyname() but .connect() doesn't : (
except TypeError:
nstPort = socket.getservbyname(port, 'udp')
# Avoid RuntimeError: already connected
transport._connectedAddr = None
transport.connect(nstHost, nstPort)
raise StopIteration(transport)
type.__call__(ctx, None, protocol).startListening()
return transport
# Avoid socket.bind()
def _bindSocket(ctx):
ctx.socket = ctx.createInternetSocket()
ctx.fileno = ctx.socket.fileno
recv = lambda ctx: ctx.protocol.datagramReceived.shift().then(lambda asdf, _: asdf)
return result
def listen(port, interface=''):
class result(udp.Port):
class __metaclass__(type):
def __call__(ctx):
transport = promise.promise()
@untwisted.call
class protocol:
datagramReceived = promise.sequence()
# Avoid AttributeError: protocol instance has no attribute 'doStop'
def doStop(ctx):
pass
makeConnection = transport
try:
type.__call__(ctx, port, protocol, interface).startListening()
# tcp.Connector calls socket.getservbyname() but udp.Port doesn't : (
except TypeError:
nstPort = socket.getservbyname(port, 'udp')
type.__call__(ctx, nstPort, protocol, interface).startListening()
return transport
return result