Browse Source

start working on message i/o

William Pitcock 3 years ago
parent
commit
dff2a5eb76
2 changed files with 101 additions and 0 deletions
  1. 0
    0
      aiobgp/__init__.py
  2. 101
    0
      aiobgp/messages.py

+ 0
- 0
aiobgp/__init__.py View File


+ 101
- 0
aiobgp/messages.py View File

@@ -0,0 +1,101 @@
1
+import sys
2
+import struct
3
+import math
4
+
5
+
6
+"""
7
+aiobgp.messages - Serialization and deserialization of BGP messages in an independent way.
8
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
+
10
+The ``aiobgp.messages`` module provides functions for serializing and deserializing BGP messages.
11
+It has no dependency on any particular event-loop and can be used to create adaptors to other event
12
+loops than AsyncIO.
13
+"""
14
+
15
+
16
+BGP_MESSAGE_HEADERLEN = 0x13
17
+
18
+
19
+BGP_MESSAGE_NIL = 0x0
20
+BGP_MESSAGE_OPEN = 0x1
21
+BGP_MESSAGE_UPDATE = 0x2
22
+BGP_MESSAGE_NOTIFICATION = 0x3
23
+BGP_MESSAGE_KEEPALIVE = 0x4
24
+
25
+
26
+BGP_MESSAGE_MARKER = b'\xff' * 16
27
+
28
+
29
+class BGPMessage:
30
+    """The BGPMessage class provides an abstract view of a BGP message, given a collection of bytes.  It
31
+    also handles rendering a message back to a collection of bytes, through the ``encode()`` function.  Messages
32
+    are decoded via the ``decode()`` function."""
33
+    __messagetype__ = BGP_MESSAGE_NIL
34
+    def __init__(self):
35
+        self.length = BGP_MESSAGE_HEADERLEN
36
+        self.msg_type = self.__messagetype__
37
+
38
+    def encode_header(self, data):
39
+        assert self.__messagetype__ > BGP_MESSAGE_NIL
40
+
41
+        length = len(data) + BGP_MESSAGE_HEADERLEN
42
+        return BGP_MESSAGE_MARKER + struct.pack('!H', length) + bytearray([self.__messagetype__]) + data
43
+
44
+    def encode(self):
45
+        return self.encode_header(b'')
46
+
47
+    @staticmethod
48
+    def decode_header(data):
49
+        if len(data) < 19:
50
+            return None
51
+
52
+        length, msg_type = struct.unpack_from('!HB', data, offset=16)
53
+        return {'length': length, 'msg_type': msg_type}
54
+
55
+    @classmethod
56
+    def decode(cls, data):
57
+        if len(data) < 19:
58
+            return None
59
+
60
+        header = BGPMessage.decode_header(data)
61
+        if not header:
62
+            return None
63
+
64
+        out = cls()
65
+        out.length = header['length']
66
+        out.msg_type = header['msg_type']
67
+        return out
68
+
69
+    def __repr__(self):
70
+        return "<{0}: type={1} length={2}>".format(self.__class__.__name__, self.msg_type, self.length)
71
+
72
+
73
+class OpenMessage(BGPMessage):
74
+    __messagetype__ = BGP_MESSAGE_OPEN
75
+
76
+
77
+class UpdateMessage(BGPMessage):
78
+    __messagetype__ = BGP_MESSAGE_UPDATE
79
+
80
+
81
+class NotificationMessage(BGPMessage):
82
+    __messagetype__ = BGP_MESSAGE_NOTIFICATION
83
+
84
+
85
+class KeepAliveMessage(BGPMessage):
86
+    __messagetype__ = BGP_MESSAGE_KEEPALIVE
87
+
88
+
89
+message_types = {
90
+    BGP_MESSAGE_OPEN: OpenMessage,
91
+    BGP_MESSAGE_UPDATE: UpdateMessage,
92
+    BGP_MESSAGE_NOTIFICATION: NotificationMessage,
93
+    BGP_MESSAGE_KEEPALIVE: KeepAliveMessage
94
+}
95
+
96
+
97
+if __name__ == '__main__':
98
+    print(repr(KeepAliveMessage()))
99
+    print(repr(KeepAliveMessage().encode()))
100
+
101
+    assert repr(KeepAliveMessage()) == repr(KeepAliveMessage.decode(KeepAliveMessage().encode()))