ethernet.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. # -*- test-case-name: twisted.pair.test.test_ethernet -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. #
  5. """Support for working directly with ethernet frames"""
  6. import struct
  7. from twisted.internet import protocol
  8. from twisted.pair import raw
  9. from zope.interface import implementer, Interface
  10. class IEthernetProtocol(Interface):
  11. """An interface for protocols that handle Ethernet frames"""
  12. def addProto():
  13. """Add an IRawPacketProtocol protocol"""
  14. def datagramReceived():
  15. """An Ethernet frame has been received"""
  16. class EthernetHeader:
  17. def __init__(self, data):
  18. (self.dest, self.source, self.proto) \
  19. = struct.unpack("!6s6sH", data[:6+6+2])
  20. @implementer(IEthernetProtocol)
  21. class EthernetProtocol(protocol.AbstractDatagramProtocol):
  22. def __init__(self):
  23. self.etherProtos = {}
  24. def addProto(self, num, proto):
  25. proto = raw.IRawPacketProtocol(proto)
  26. if num < 0:
  27. raise TypeError('Added protocol must be positive or zero')
  28. if num >= 2**16:
  29. raise TypeError('Added protocol must fit in 16 bits')
  30. if num not in self.etherProtos:
  31. self.etherProtos[num] = []
  32. self.etherProtos[num].append(proto)
  33. def datagramReceived(self, data, partial=0):
  34. header = EthernetHeader(data[:14])
  35. for proto in self.etherProtos.get(header.proto, ()):
  36. proto.datagramReceived(data=data[14:],
  37. partial=partial,
  38. dest=header.dest,
  39. source=header.source,
  40. protocol=header.proto)