James R
James R

Reputation: 4656

UDP Proxy server using python 3.6 async

I'm curious to see how I can create a UDP proxy server using the async module. I tried earlier today with Twisted, but wasn't making much headway. I did find some simple solutions here on stackoverflow using sockets directly, but i'm wondering if this is possible using the async lib.

For clarity, what I'm looking for is:

Step 1: client A (can be many) speaks to proxy B Step 2: proxy B sends the request along to server C. Step 3: Server C responds to proxy B Sep 4: Proxy B responds to client A.

Here's what I have so far:

import asyncio

class EchoServerProtocol(asyncio.DatagramProtocol):
    def connection_made(self, transport):
        self.transport = transport

    def datagram_received(self, data, addr, args=None):
        message = data
        server_addr = ('localhost', 27015)
        print('Received %r from %s' % (message, addr))
        print('Send %r to %s' % (message, server_addr))
        self.transport.sendto(data, server_addr)

loop = asyncio.get_event_loop()
print("Starting UDP server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
    EchoServerProtocol,
    local_addr=('0.0.0.0', 27016),
)
transport, protocol = loop.run_until_complete(listen)

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

transport.close()
loop.close()

The above is basically this:

https://docs.python.org/3/library/asyncio-protocol.html#udp-echo-server-protocol

What I have will get you to step 3, but of course fails at step 4. It sends it back to server C.

You will note that one of the other protocol examples, EchoServerClientProtocol, creates a new instance for each connection. I assume I need to create a new instance for every connection, I believe, because then I can store the original address in the instance, and return that. I assume this doesn't apply to create_datagram_endpoint, or I can't figure out how to do it.

There might be a better approach though.

Upvotes: 3

Views: 3675

Answers (1)

Vincent
Vincent

Reputation: 13425

You need a local endpoint for server B, plus a remote endpoint to server C for each client A.

Here is a possible implementation.

Also, you might be interested in this module providing high-level UDP endpoints for asyncio.

Upvotes: 4

Related Questions