зеркало из https://github.com/mozilla/gecko-dev.git
Bug 857668: Teach test TURN server to open additional ports, on which it will respond with 300. r=mjf,ahal
Differential Revision: https://phabricator.services.mozilla.com/D115276
This commit is contained in:
Родитель
fd55c6b4ca
Коммит
d1fc4209b2
|
@ -61,6 +61,12 @@ SOFTWARE = 0x8022
|
|||
ALTERNATE_SERVER = 0x8023
|
||||
FINGERPRINT = 0x8028
|
||||
|
||||
STUN_PORT = 3478
|
||||
STUNS_PORT = 5349
|
||||
|
||||
TURN_REDIRECT_PORT = 3479
|
||||
TURNS_REDIRECT_PORT = 5350
|
||||
|
||||
|
||||
def unpack_uint(bytes_buf):
|
||||
result = 0
|
||||
|
@ -368,6 +374,11 @@ class StunMessage(object):
|
|||
digest = self.calculate_message_digest(username, realm, password)
|
||||
self.find(MESSAGE_INTEGRITY).data = digest
|
||||
|
||||
def add_alternate_server(self, host, port):
|
||||
address = ipaddr.IPAddress(host)
|
||||
version = STUN_IPV6 if address.version == 6 else STUN_IPV4
|
||||
self.add_address(int(address), version, port, ALTERNATE_SERVER)
|
||||
|
||||
|
||||
class Allocation(protocol.DatagramProtocol):
|
||||
"""
|
||||
|
@ -682,6 +693,40 @@ class StunHandler(object):
|
|||
return self.make_success_response(request)
|
||||
|
||||
|
||||
class StunRedirectHandler(StunHandler):
|
||||
"""
|
||||
Frames and handles STUN messages by redirecting to the "real" server port.
|
||||
Performs the redirect with auth, so does a 401 to unauthed requests.
|
||||
Can be used to test port-based redirect handling.
|
||||
"""
|
||||
|
||||
def __init__(self, transport_handler):
|
||||
super(StunRedirectHandler, self).__init__(transport_handler)
|
||||
|
||||
def handle_stun(self, stun_message, address):
|
||||
self.client_address = address
|
||||
if stun_message.msg_class == REQUEST:
|
||||
challenge_response = self.check_long_term_auth(stun_message)
|
||||
|
||||
if challenge_response.msg_class == SUCCESS_RESPONSE:
|
||||
return self.make_redirect_response(stun_message).build()
|
||||
|
||||
return challenge_response.build()
|
||||
|
||||
def make_redirect_response(self, request):
|
||||
response = self.make_error_response(request, 300, "Try alternate")
|
||||
port = STUN_PORT
|
||||
if self.transport_handler.transport.getHost().port == TURNS_REDIRECT_PORT:
|
||||
port = STUNS_PORT
|
||||
|
||||
response.add_alternate_server(
|
||||
self.transport_handler.transport.getHost().host, port
|
||||
)
|
||||
|
||||
response.add_message_integrity(turn_user, turn_realm, turn_pass)
|
||||
return response
|
||||
|
||||
|
||||
class UdpStunHandler(protocol.DatagramProtocol):
|
||||
"""
|
||||
Represents a UDP listen port for TURN.
|
||||
|
@ -695,6 +740,19 @@ class UdpStunHandler(protocol.DatagramProtocol):
|
|||
self.transport.write(bytes(data), (address.host, address.port))
|
||||
|
||||
|
||||
class UdpStunRedirectHandler(protocol.DatagramProtocol):
|
||||
"""
|
||||
Represents a UDP listen port for TURN that will redirect.
|
||||
"""
|
||||
|
||||
def datagramReceived(self, data, address):
|
||||
stun_handler = StunRedirectHandler(self)
|
||||
stun_handler.data_received(data, to_ipaddress("UDP", address[0], address[1]))
|
||||
|
||||
def write(self, data, address):
|
||||
self.transport.write(bytes(data), (address.host, address.port))
|
||||
|
||||
|
||||
class TcpStunHandlerFactory(protocol.Factory):
|
||||
"""
|
||||
Represents a TCP listen port for TURN.
|
||||
|
@ -736,6 +794,31 @@ class TcpStunHandler(protocol.Protocol):
|
|||
self.transport.write(bytes(data))
|
||||
|
||||
|
||||
class TcpStunRedirectHandlerFactory(protocol.Factory):
|
||||
"""
|
||||
Represents a TCP listen port for TURN that will redirect.
|
||||
"""
|
||||
|
||||
def buildProtocol(self, addr):
|
||||
return TcpStunRedirectHandler(addr)
|
||||
|
||||
|
||||
class TcpStunRedirectHandler(protocol.DatagramProtocol):
|
||||
def __init__(self, addr):
|
||||
self.address = addr
|
||||
self.stun_handler = None
|
||||
|
||||
def dataReceived(self, data):
|
||||
# This needs to persist, since it handles framing. Framing matters here
|
||||
# because we do a round of auth before redirecting.
|
||||
if not self.stun_handler:
|
||||
self.stun_handler = StunRedirectHandler(self)
|
||||
self.stun_handler.data_received(data, self.address)
|
||||
|
||||
def write(self, data, address):
|
||||
self.transport.write(bytes(data))
|
||||
|
||||
|
||||
def get_default_route(family):
|
||||
dummy_socket = socket.socket(family, socket.SOCK_DGRAM)
|
||||
if family is socket.AF_INET:
|
||||
|
@ -820,12 +903,26 @@ if __name__ == "__main__":
|
|||
interface_6 = "::1"
|
||||
hostname = "localhost"
|
||||
|
||||
reactor.listenUDP(3478, UdpStunHandler(), interface=interface_4)
|
||||
reactor.listenTCP(3478, TcpStunHandlerFactory(), interface=interface_4)
|
||||
reactor.listenUDP(STUN_PORT, UdpStunHandler(), interface=interface_4)
|
||||
reactor.listenTCP(STUN_PORT, TcpStunHandlerFactory(), interface=interface_4)
|
||||
|
||||
reactor.listenUDP(
|
||||
TURN_REDIRECT_PORT, UdpStunRedirectHandler(), interface=interface_4
|
||||
)
|
||||
reactor.listenTCP(
|
||||
TURN_REDIRECT_PORT, TcpStunRedirectHandlerFactory(), interface=interface_4
|
||||
)
|
||||
|
||||
try:
|
||||
reactor.listenUDP(3478, UdpStunHandler(), interface=interface_6)
|
||||
reactor.listenTCP(3478, TcpStunHandlerFactory(), interface=interface_6)
|
||||
reactor.listenUDP(STUN_PORT, UdpStunHandler(), interface=interface_6)
|
||||
reactor.listenTCP(STUN_PORT, TcpStunHandlerFactory(), interface=interface_6)
|
||||
|
||||
reactor.listenUDP(
|
||||
TURN_REDIRECT_PORT, UdpStunRedirectHandler(), interface=interface_6
|
||||
)
|
||||
reactor.listenTCP(
|
||||
TURN_REDIRECT_PORT, TcpStunRedirectHandlerFactory(), interface=interface_6
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -838,16 +935,26 @@ if __name__ == "__main__":
|
|||
KEY_FILE, CERT_FILE, SSL.TLSv1_2_METHOD
|
||||
)
|
||||
reactor.listenSSL(
|
||||
5349, TcpStunHandlerFactory(), tls_context_factory, interface=interface_4
|
||||
STUNS_PORT,
|
||||
TcpStunHandlerFactory(),
|
||||
tls_context_factory,
|
||||
interface=interface_4,
|
||||
)
|
||||
|
||||
try:
|
||||
reactor.listenSSL(
|
||||
5349,
|
||||
STUNS_PORT,
|
||||
TcpStunHandlerFactory(),
|
||||
tls_context_factory,
|
||||
interface=interface_6,
|
||||
)
|
||||
|
||||
reactor.listenSSL(
|
||||
TURNS_REDIRECT_PORT,
|
||||
TcpStunRedirectHandlerFactory(),
|
||||
tls_context_factory,
|
||||
interface=interface_6,
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -872,7 +979,7 @@ if __name__ == "__main__":
|
|||
template = Template(
|
||||
'[\
|
||||
{"urls":["stun:$hostname", "stun:$hostname?transport=tcp"]}, \
|
||||
{"username":"$user","credential":"$pwd","urls": \
|
||||
{"username":"$user","credential":"$pwd","turn_redirect_port":"$TURN_REDIRECT_PORT","turns_redirect_port":"$TURNS_REDIRECT_PORT","urls": \
|
||||
["turn:$hostname", "turn:$hostname?transport=tcp" $turns_url] \
|
||||
$cert_prop}]' # Hack to make it easier to override cert checks
|
||||
)
|
||||
|
@ -884,6 +991,8 @@ $cert_prop}]' # Hack to make it easier to override cert checks
|
|||
hostname=hostname,
|
||||
turns_url=turns_url,
|
||||
cert_prop=cert_prop,
|
||||
TURN_REDIRECT_PORT=TURN_REDIRECT_PORT,
|
||||
TURNS_REDIRECT_PORT=TURNS_REDIRECT_PORT,
|
||||
)
|
||||
)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче