1# Copyright 2021-2022 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# ----------------------------------------------------------------------------- 16# Imports 17# ----------------------------------------------------------------------------- 18import asyncio 19import logging 20 21from .common import Transport, ParserSource 22 23# ----------------------------------------------------------------------------- 24# Logging 25# ----------------------------------------------------------------------------- 26logger = logging.getLogger(__name__) 27 28 29# ----------------------------------------------------------------------------- 30async def open_udp_transport(spec: str) -> Transport: 31 ''' 32 Open a UDP transport. 33 The parameter string has this syntax: 34 <local-host>:<local-port>,<remote-host>:<remote-port> 35 36 Example: 0.0.0.0:9000,127.0.0.1:9001 37 ''' 38 39 class UdpPacketSource(asyncio.DatagramProtocol, ParserSource): 40 def datagram_received(self, data, addr): 41 self.parser.feed_data(data) 42 43 class UdpPacketSink: 44 def __init__(self, transport): 45 self.transport = transport 46 47 def on_packet(self, packet): 48 self.transport.sendto(packet) 49 50 def close(self): 51 self.transport.close() 52 53 local, remote = spec.split(',') 54 local_host, local_port = local.split(':') 55 remote_host, remote_port = remote.split(':') 56 ( 57 udp_transport, 58 packet_source, 59 ) = await asyncio.get_running_loop().create_datagram_endpoint( 60 UdpPacketSource, 61 local_addr=(local_host, int(local_port)), 62 remote_addr=(remote_host, int(remote_port)), 63 ) 64 packet_sink = UdpPacketSink(udp_transport) 65 66 return Transport(packet_source, packet_sink) 67