Skip to content

Instantly share code, notes, and snippets.

@Fahrradkette
Last active February 28, 2018 00:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Fahrradkette/3678faa152b5d6258cf7 to your computer and use it in GitHub Desktop.
Save Fahrradkette/3678faa152b5d6258cf7 to your computer and use it in GitHub Desktop.
UDP lag-inducing proxy server using python asyncio
import asyncio
import sys
class FakeServerProtocol(asyncio.DatagramProtocol):
def __init__(self, target_addr, stc_delay, cts_delay, loop=None):
self.loop = loop
if self.loop is None:
self.loop = asyncio.get_event_loop()
self.transport = None
self.target_addr = target_addr
self.client_addr = None
self.stc_delay = stc_delay
self.cts_delay = cts_delay
self.loop.call_later(2, self.update_delay, self.loop)
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
if addr != self.target_addr:
if self.client_addr == None:
self.client_addr = addr
elif addr != self.client_addr:
self.client_addr = addr
self.loop.call_later(self.cts_delay, lambda: self.transport.sendto(data, self.target_addr))
else:
if self.client_addr != None:
self.loop.call_later(self.stc_delay, lambda: self.transport.sendto(data, self.client_addr))
def update_delay(self, loop):
self.stc_delay = stc_delay
self.cts_delay = cts_delay
self.loop.call_later(1, self.update_delay, self.loop)
def handle_stdin():
data = sys.stdin.readline()
delays = data.split(' ')
stc = ""
cts = ""
if len(delays) > 1:
cts = delays[1]
else:
cts = delays[0]
try:
stc_ = float(delays[0])
cts_ = float(cts)
except ValueError:
print("Please enter numbers only")
return
print("new server to client delay: {}ms".format(stc_))
print("new client to server delay: {}ms".format(cts_))
global stc_delay
global cts_delay
stc_delay = stc_/1000
cts_delay = cts_/1000
# access the proxy on this address
proxy_address = ('192.168.0.6', 12345)
# the udp server it's being proxied to
target_addr = ('192.168.0.6', 34197)
# server to client delay in seconds
stc_delay = 0.6
# client to server delay in seconds
cts_delay = 0.7
loop = asyncio.get_event_loop()
print("Starting UDP proxy server on {}:{}, target: {}:{}".format(
proxy_address[0],
proxy_address[1],
target_addr[0],
target_addr[1]))
print("server to client delay: {}ms, client to server delay: {}ms".format(
int(stc_delay*1000), int(cts_delay*1000)))
listen = loop.create_datagram_endpoint(
lambda: FakeServerProtocol(target_addr, stc_delay, cts_delay),
local_addr=proxy_address
)
serve_transport, protocol = loop.run_until_complete(listen)
loop.add_reader(sys.stdin, handle_stdin)
print()
print("Enter one or two numbers, seperated by a space, to adjust the simulated lag.")
print("The first number will be server to client, the second client to server delay.")
print("If you ommit the second number, both delays will have the same value.")
print()
print("Hit Ctrl+C to abort")
try:
loop.run_forever()
except KeyboardInterrupt:
pass
serve_transport.close()
loop.remove_reader(sys.stdin)
loop.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment