Coverage for aiocoap/transports/generic_udp.py: 82%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

34 statements  

1# This file is part of the Python aiocoap library project. 

2# 

3# Copyright (c) 2012-2014 Maciej Wasilak <http://sixpinetrees.blogspot.com/>, 

4# 2013-2014 Christian Amsüss <c.amsuess@energyharvesting.at> 

5# 

6# aiocoap is free software, this file is published under the MIT license as 

7# described in the accompanying LICENSE file. 

8 

9from aiocoap import interfaces, error, util 

10from aiocoap import COAP_PORT, Message 

11 

12class GenericMessageInterface(interfaces.MessageInterface): 

13 """GenericMessageInterface is not a standalone implementation of a 

14 message inteface. It does implement everything between the MessageInterface 

15 and a not yet fully specified interface of "bound UDP sockets". 

16 

17 It delegates sending through the address objects (which persist through 

18 some time, given this is some kind of bound-socket scenario). 

19 

20 The user must: 

21 * set up a ._pool after construction with a shutdown and a connect method 

22 * provide their addresses with a send(bytes) method 

23 * pass incoming data to the _received_datagram and _received_exception methods 

24 """ 

25 

26 def __init__(self, mman: interfaces.MessageManager, log, loop): 

27 self._mman = mman 

28 self._log = log 

29 self._loop = loop 

30 

31 # Callbacks to be hooked up by the user of the class; feed data on to the 

32 # message manager 

33 

34 def _received_datagram(self, address, datagram): 

35 try: 

36 message = Message.decode(datagram, remote=address) 

37 except error.UnparsableMessage: 

38 self._log.warning("Ignoring unparsable message from %s", address) 

39 return 

40 

41 self._mman.dispatch_message(message) 

42 

43 def _received_exception(self, address, exception): 

44 self._mman.dispatch_error(exception, address) 

45 

46 # Implementations of MessageInterface 

47 

48 def send(self, message): 

49 if self._mman is None: 

50 self._log.info("Not sending message %r: transport is already shutting down.", message) 

51 else: 

52 message.remote.send(message.encode()) 

53 

54 async def shutdown(self): 

55 await self._pool.shutdown() 

56 self._mman = None 

57 

58 async def determine_remote(self, request): 

59 if request.requested_scheme not in ('coap', None): 

60 return None 

61 

62 if request.unresolved_remote is not None: 

63 host, port = util.hostportsplit(request.unresolved_remote) 

64 port = port or COAP_PORT 

65 elif request.opt.uri_host: 

66 host = request.opt.uri_host 

67 port = request.opt.uri_port or COAP_PORT 

68 else: 

69 raise ValueError("No location found to send message to (neither in .opt.uri_host nor in .remote)") 

70 

71 return await self._pool.connect((host, port))